buuctf6
[BJDCTF2020]The mystery of ip
算是一道比较意外的题目吧,发现X-Forwarded-For的内容会被显示,想说会不会是命令注入尝试了一下发现被原样输出了,接下来就没有其他思路了
看了一下wp,发现是ssti注入,但是跟以前又不同,这里可以直接使用系统命令,所以是php模板注入!
paylaod:
1 | {{system('ls')}} |
[BJDCTF2020]Mark loves cat
git泄露,扫一波拿到源码
1 |
|
审计审计~
$$导致的变量覆盖问题
1.$$介绍
$$这种写法称为可变变量
一个可变变量获取了一个普通变量的值作为这个可变变量的变量名。
1 |
|
2.漏洞产生
使用foreach来遍历数组中的值,然后再将获取到的数组键名作为变量,数组中的键值作为变量的值。因此就产生了变量覆盖漏洞。
举例
1 |
|
get得到的数据$key和$value,关键第3行,${$key}用get传进来的$key做为新的变量,将get传进来的$value赋值给它。
get ?a=1 第3行回解析为$a=1。就造成了变量覆盖。
exit()函数:在函数结束脚本的运行时会输出一个信息
在此题中,一开始我以为只要绕过那几个判断,执行到echo的判断就行了,但是其实是不行的,我没有注意到期间$flag的值是否会发生改变,因为这是include’flag.php’的,在index.php修改$flag的值也会覆盖修改flag.php当中的值,那么此时就有两种思路:
1.绕过两个判断但是不改变最终echo里面$flag的值(失败~)
2.进入判断,让判断中exit的变量等于flag的值:
这里需要先了解一下代码的执行过程:
可以看到x为键名,y为键值,弄清楚这个,开始正式构造payload,先代码分析一波: 搞清楚这个继续往下方法一:
从exit(yds)入手试试:这里就很简单了,直接用get类型的传入一个yds=flag
方法二:
1 | is=flag&flag=flag |
[BJDCTF2020]ZJCTF,不过如此
1 | ?text=php://input&file=php://filter/read=convert.base64-encode/resource=next.php |
考察伪协议,使用inpu传入I have a dream绕过第一个判断 进入文件包含,此时过滤flag.php 但是又无法使用data协议看到提示next.php,于是使用filter协议打开:
1 | <?php |
到了这里就是只是盲区了,一直在想如何引用getFlag这个函数,但主要是正则表达式没读懂,
preg_replace函数之命令执行
preg_replace:(PHP 5.5)
功能 : 函数执行一个正则表达式的搜索和替换
定义 :
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
搜索 subject 中匹配 pattern 的部分, 如果匹配成功以 replacement 进行替换
- $pattern 存在 /e 模式修正符,允许代码执行
- /e 模式修正符,使preg_reslace() 将 $replacement 当做php代码来执行
漏洞解析:
这道题目考察的是 preg_replace 函数使用 /e 模式,导致代码执行的问题。我们发现在上图代码 第11行 处,将 GET 请求方式传来的参数用在了 complexStrtolower 函数中,而变量 $regex 和 $value 又用在了存在代码执行模式的 preg_replace 函数中。所以,我们可以通过控制 preg_replace 函数第1个、第3个参数,来执行代码。但是可被当做代码执行的第2个参数,却固定为 ‘strtolower(“\\1”)’ 。
1 | 反向引用 |
这边比较难理解的应该是这个反向引用,所以我用了代码调试一下:
1 | 这里先阐述一下我的理解,\1可以储存表达式,pattern匹配到的subject的内容将会被存储在strtolower中执行,所以此时我们需要做的就是看什么样的函数构造形式可以在strtolower("")中执行,所以此时引入可变变量的知识,上一关的可变变量中,我们理解了$$a实际上是先解析执行了$a这里我们引入${phpinfo()}也是这种用处,我们传入这个值接下来就变成$str=${phpinfo()}也就是$${phpinfo()},此时{phpinfo()}就会被执行返回1,变成$1,而且需要注意的是由于这里是双引号才可以这样解析,总结起来就是: |
1 | var_dump(phpinfo()); // 布尔true |
接下来还有一个难点,就是正则匹配式中匹配语句该如何书写呢?:
. |
匹配除换行符以外的任意字符 |
---|---|
\s |
匹配任意的空白符 |
\S |
匹配任何非空白字符 |
+ |
匹配前面的子表达式一次或多次 |
但是这里无法使用. 因为php的解析特性,会被转义成_就改变来原来我们想要的效果,所以这里需要的是\S*
由于这里是eval函数执行,所以我们可以直接构造一句话木马:
payload:
1 | ?\S*={${eval($_POST['1'])} |