## Материал для самостоятельного изучения Содержание: 1. Примеры уязвимого кода 2. Примеры атак и уязвимых приложений ### Примеры уязвимого кода Уязвимость может быть обнаружена в исходном коде, в основном из-за использования так называемых `сырых` запросов, которые заполняются параметрами от пользователя. Ниже приведены примеры таких уязвимых конструкций. PHP ```php $user=$_POST['user']; $pass=$_POST['pass']; if($_GET['act']=='logout'){ session_unset(); $contenttowrite = $contenttowrite.'<tr><td colspan="2">Çıkış yaptınız!</td></tr>'; }else if($_GET['act']=='login'){ $link = mysql_connect(DB_HOST, DB_USER, DB_PASS); if (!$link) die ("Out of service"); mysql_select_db(DB_DATABASE, $link) or die ("Out of service"); $queryusercheck = mysql_query("SELECT count(id) FROM cc_users WHERE USERNAME='$user' AND `PASSWORD`='".computeHash($user, $pass)."'",$link); $usercheck_value = mysql_fetch_array ($queryusercheck); ``` C# ```C# using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System; using System.Data.SqlClient; namespace WebFox.Controllers { [ApiController] [Route("[controller]")] public class Sqli : ControllerBase { private readonly ILogger<Sqli> _logger; public Sqli(ILogger<Sqli> logger) { _logger = logger; } [HttpGet("{id}")] public string DoSqli(string id) { string conString = "I AM a connection String"; using (SqlCommand cmd = new SqlCommand("SELECT * FROM users WHERE userId = '" + id + "'")) { using (SqlConnection con = new SqlConnection(conString)) { con.Open(); cmd.Connection = con; SqlDataReader reader = cmd.ExecuteReader(); string res = ""; while (reader.Read()) { res += reader["userName"]; } return res; } } } } } ``` Java ```Java // Get username from parameters String username = request.getParameter("username"); // Create a statement from database connection Statement statement = connection.createStatement(); // Create unsafe query by concatenating user defined data with query string String query = "SELECT secret FROM Users WHERE (username = '" + username + "' AND NOT role = 'admin')"; // ... OR ... // Insecurely format the query string using user defined data String query = String.format("SELECT secret FROM Users WHERE (username = '%s' AND NOT role = 'admin')", username); // Execute query and return the results ResultSet result = statement.executeQuery(query); ``` Ruby ```Ruby class ApplicationController < ActionController::Base protect_from_forgery with: :exception end class UsersController < ApplicationController def update con = Mysql.new 'localhost', 'user', 'pwd' con.query 'UPDATE users set name = ' + params[:name] + ' where id = ' + params[:id] con.close end end ``` nodeJS ```javascript var mysql = require('db-mysql'); var http = require('http'); var out; var valTom; var req = http.request(options, function(res) { res.on('data', function(chunk) { valTom = chunk; } ); } ); new mysql.Database( { hostname: 'localhost', user: 'user', password: 'password', database: 'test' } ).connect(function(error) { var the_Query = "INSERT INTO Customers (CustomerName, ContactName) VALUES ('Tom'," + valTom + ")"; this.query(the_Query).execute(function(error, result) { if (error) { console.log("Error: " + error); } else { console.log('GENERATED id: ' + result.id); } } ); out = resIn; } ); ``` Лучший вариант митигации подобных уязвимостей, которые представлены в исходниках выше - использовать дополнительную абстракцию. Для этого принято использовать ORM механизм, поддерживается он в любых языка программирования. Однако, не стоит доверять на 100% такому коду и избегать прописывания части сырого запроса для ORM. Ниже несколько примеров уязвимого кода: nodeJS ```javascript db.query('SELECT Desc FROM Items WHERE Username IN (:names)', { replacements: { names: ["Bobby", "'); DELETE FROM Items WHERE 1=1; --')"] } }); ``` Ruby ```Ruby params[:column] = "age) FROM users WHERE name = 'Bob';" Order.calculate(:sum, params[:column]) ``` Большой набор примеров для Ruby можно найти [тут](https://rails-sqli.org). Набор можно использовать как рекомендации и для остальных языков программирования. ### Примеры атак и уязвимых приложений Уязвимые приложения можно тестировать на платформах: - [root-me](https://www.root-me.org/?lang=en) - [portswigger Academy](https://portswigger.net/web-security/all-labs) - [ringzer0team](https://ringzer0ctf.com) При поиске SQLi в приложении важно понимать какие именно механизмы наиболее вероятно используют системы хранения данных. Несколько примеров: - Поиск - Контроль сессии - Формы аутентификации Идентификация может производиться в слепом или режиме показа ошибок. В первом случае фиксируется поведение приложения (данные на интрефейсе, размер ответа, время задержки ответа) Во втором случае, атакующий может получить избыточную информацию из лога ошибки, которая показывается на экране. После идентификации параметров вероятным действием является примерное восстановление запроса. Этот этап достаточно хорошо автоматизируется. За примерами тестирования можно обращаться в презентацию этого занятия. #### Задание располагается по адресу: https://portswigger.net/web-security/sql-injection/lab-retrieve-hidden-data Приложение представляет собой уязимый магазин, где можно производить управление частью запроса. Уязвимый параметр находится в механизме поиска. Переправим запрос в Repeater: ![](https://i.imgur.com/tjWV0mv.png) Попробуем показать все данные из базы, для этого нужно добавить условие, при котором не будет выполняться фильтр для данных. Например `' or 1<2 --` ![](https://i.imgur.com/1wMFyAS.png) О результатах запроса можно судить по количеству продуктов, которые стали доступны на странице сервиса. По обычному запросу их будет не больше 3х. #### Задание располагается по адресу: https://ringzer0ctf.com/challenges/1 Приложение представляет собой форму для аутентификации. Задачей злоумышленника для такого интерфейса может стать обычное манипулирование логикой работы приложения, а именно - вывод о правильно логине или пароле. Тестирование таких приложений начинается с того факта, что в приложении может находиться какой-то известный и широко используемый логин, который может использоваться для администрирования системы. Наиболее частые варианты для тестирования: - root - admin - administrator Попробуем определить можем ли мы произвести атаку на эту форму. ![](https://i.imgur.com/9Exb7Xm.png) Приложение помимо уязвимости SQLi так же содержит мисконфигурацию для вывода ошибок. На основании ответа приложения можем выбрать синтаксис той базы, которая обслуживает приложение и успешно завершить атаку. Успешную атаку для таких форм можно выполнить по 2м сценариям: 1. Использование конструкции SQL языка с комментарием 2. Ипользование конструкции SQL языка с корректным дополнением синтаксиса оригинального запроса Для первого варианта атаки отправим тестовые данные `admin' or 1=1# `: ![](https://i.imgur.com/t4sXMlq.png) Для второго варианта атаки отправим тестовые данные `admin' or 'a' or 'a' or 'a`: ![](https://i.imgur.com/XZYOxUU.png) #### Автоматизация Тестирование sqli можно автоматизировать. Самый популярный способ - проект [sqlmap](https://github.com/sqlmapproject/sqlmap). Так же можно найти в `BApp Store` [плагин-обертка](https://github.com/portswigger/sqli-py). Пример автоматизации рассмотрим на задании по [адресу](https://www.root-me.org/fr/Challenges/Web-Serveur/SQL-injection-String) Перед началом автоматизации рекомендуется поставить sqlmap из официального репозитория. Чем новее - тем больше функционала. Подробнейшие инструкции по используемым параметрам можно найти [здесь](https://github.com/sqlmapproject/sqlmap/wiki/Usage). Автоматизацию разобъем на шаги: 1. Скопировать запрос из Burp Suite и сохранить в файл req.txt: ![](https://i.imgur.com/Vzd4bSY.png) 2. Запустить из консоли команду: ``` sqlmap -r ./req.txt -p recherche --risk=2 --level=2 --tables --columns ``` Так как sqlmap поддерживает все виды техник для тестирования уязвимости sqli, то можно использовать флаг --technique для ускорения процесса поиска уязвимости и/или сбора данных. Каждая техника обозначается по её названию первой буквой. Например `Error Based` атака будет обозначаться как `E`. Добавим к этой технике `union` вариант тестирования. ``` sqlmap -r ./req.txt -p recherche --risk=2 --level=2 --tables --columns --technique=EU ``` Результат работы sqlmap: ![](https://i.imgur.com/ckaIqQZ.png) ::: danger Использования risk/level выше, чем 1 и 3 соответственно может привести к удалению данных в базе или выводу из строя сервер базы данных. Поэтому использовать эти параметры нужно очень осторожно! ::: ### Полезные материалы - https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection - https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html - https://cheatsheetseries.owasp.org/cheatsheets/Injection_Prevention_in_Java_Cheat_Sheet.html