源码分析
- 主要看
hello_shell
函数, 后面的接受 GET 请求参数显示源码就不说了-
首先是一个判断语句, 判断的条件是
preg_match
函数的结果- 在这里
preg_match
有两个参数 - 一个是
"/flag/"
, 一个是函数的cmd
参数 - 其作用就是检测
cmd
中是否有flag
字符 - 或许会问, 为什么是
flag
, 两个/
去哪了- 其实前面 重点看
preg_replace('/_/', '-', $_SESSION['random_func']);
函数 就提到了 / /
是 PHP 中 正则表达式 的定界符, 用来表示正则表达式的区间
- 其实前面 重点看
- 而判断语句内是
die
函数- 这个函数是用于停止整个PHP脚本, 并且返回其内容
- 这个函数是用于停止整个PHP脚本, 并且返回其内容
- 在这里
-
总体看来, 就是判断
cmd
参数是否有flag
字符, 如果有的话就退出脚本, 如果没有的话就继续执行函数接下来语句- 而这个就是一个最简单的 WAF, 即网页应用防火墙 (在不管是CTF, 还是Web渗透中, 最常见的就是绕过WAF吧 🙃)
-
接下来的语句就是把
cmd
作为系统命令去执行了
-
解题分析
- 整代码看下来, 我们要通过 GET 请求传入
cmd
参数, 参数中是获取 flag 的语句, 但是其中又不能含有flag
字符 - 这里就可以看到注释中给的提示, 可以通过 通配符 和 空字符来绕过(注意了, 这里是在Shell命令中)
空字符
- 简单来说就是使用引号包裹的字符(或者什么都包裹), 在运行时会除去引号运行
?cmd=cat /f''lag ?cmd=cat /f'l'ag
- 即上述两个
Payload
都是执行cat /flag
- 即上述两个
通配符(这里引用一下靶场的WP)
通配符 | 功能说明 | 示例 | 用途 |
---|---|---|---|
* | 匹配零个或多个字符 | *.txt | 匹配所有以 .txt 结尾的文件 |
? | 匹配单个字符 | file?.txt | 匹配 file1.txt , file2.txt 等单个字符的文件名 |
[] | 匹配方括号内的任意一个字符 | file[1-3].txt | 匹配 file1.txt , file2.txt , file3.txt |
[^] | 匹配不在方括号内的字符 | file[^a-c].txt | 匹配不包含 a 到 c 之间字符的文件 |
{} | 匹配大括号内的任意一个字符串,使用逗号分隔 | file{1,2,3}.txt | 匹配 file1.txt , file2.txt , file3.txt |
~ | 表示当前用户的主目录 | ~/Documents | 访问主目录下的 Documents 文件夹 |
! | 表示取反,在一些条件测试或模式匹配中使用 | ls !(*.txt) | 列出所有不是 .txt 结尾的文件 |
\ | 转义字符,取消通配符的特殊意义,使其作为普通字符处理 | file\*.txt | 匹配文件名为 file*.txt 的文件 |
- 如果会 正则表达式 对于通配符应该不陌生, 就是通过一些特殊符号(即通配符), 使一个字符串可以匹配多个字符串
- 如 (
不举例, 上面的表格已经是例子了)
- 如 (
解题步骤
- 那我就随机取一个绕过方式简单截个图 (这里是 GET 请求, 就不用BP抓包截图了)
- 这里的引号自动被浏览器进行 URL编码 了, 原本的 Payload 为
?cmd=cat /f'l'ag