SQL Injection이 가능한 대상은 parameter를 서버로 요청하고 받는 곳에서 SQL Injection이 일어 날 수 있다.
단순 게시판의 검색, 로그인창과 같은 input 태그의 사용되는 곳 뿐만이 아니다.
CASE 1 쿠키
마이 페이지를 요청하는 request와 response다.
mypage를 요청 할 때 GET Method로 요청을 진행하지만 쿼리 파라미터에 값은 보이지 않지만 cookie에 user라는 항목을 볼 수 있다.
해당 페이지는 cookie에 있는 user 항목으로 mypage를 불러온다고 유추 할 수 있으며 해당 쿼리는
select 컬럼 from 테이블 where 유저컬럼 = '___쿠키값___' 이라고 유추할 수 있다.
이를 통해 SQL Injection이 가능한지 확인해보자
3가지 방법으로 테스트를 진행해보자
1. ABCD
2. ABCD' and '1'='1
3. ABCD' and '1'='2
SQL Injection이 가능하다면 1번케이스와 2번케이스는 동일한 값이 나오며 3번 케이스에서는 값이 나오지 않게 될 것이다.
위의 결과로 1,2번의 케이스는 두번 째 항목에 notthing here값이 나왔으나 3번 케이스의 경우 빈 칸이 나왔다.
첫 번째 항목의 경우 값 false임에도 출력이 되는 것을 보아 DB에서 user 값을 가져오는 것이 아닌 Cookie의 값을 그대로 사용 함을 추측해 볼 수 있다.
CASE 2 where 절의 컬럼
게시판의 검색을 작성자, 제목, 내용으로 검색 할 수 있다.
옵션이 title로 념어가는 것을 볼 수 있다.
만약 SQL이 가능 하도록 구성되어 있다면
select {컬럼} from {테이블} where {option_val} like '{board_search}'
의 형식으로 되어 있을 것이다.
option_val에 SQL Injection을 한다면
where 1=1 and title like '%1%' 형태로 넣어 볼 수 있을 것이다.
case 1: title like '%1%'
SQL Injection을 시도 하지 않은 결과:
case 2: 1=1 and title like '%1%'
option_val=1=1 and title:
case 3: 1=2 and title like '%1%'
option_val=1=2 and title
위와 같이 직접 입력하지 않는 부분이라도 SQL Injection이 가능 한 것을 확인 할 수 있다.
CASE 3 order by
request에 sort가 추가 된 것을 확인 할 수 있다.
sort를 사용한다는 것으로 order by 구문이 사용됨을 유추 할수 있으며 쿼리는 아래와 같을 수 있다.
select {컬럼} from {테이블} where {option_val} like '{board_search}' order by {sort}
order by에 SQL Injection을 사용해보자
case 1: order by title
case 2: order by (select 1 from dual union select 2 from dual where 1=1)
order by에 select 구문으로 1, 2 두개의 row가 생기기 때문에 문법 오류가 발생하므로 결과가 나오지 않는다.
이를 통해 Blind SQL Inection이 가능하다.
Ex (select 1 from dual union select 2 from dual where length(database()) = 11) -> 확인 결과 db의 길이는 11 이다.(참 조건일 경우 화면에 아무 결과 없음)
case 2: order by (select 1 from dual union select 2 from dual where 1=2)
거짓 조건의 경우 화면에 결과가 출력된다.
결론
SQL Injection은 단순 화면에서 입력가능 한 부분이 아니라 SQL로 전달 되는 모든 파라미터에서 가능 할 수 있다.
SQL Injection의 대처방법
SQL Injection의 대처방법은 매우 간단하다. prepared Statement를 사용하면 된다.
prepared Statement란 SQL 질의문을 미리 컴팡일링하여 캐시에서 사용하도록 하는 방식이다.
이를통해 SQL 질의문을 전달 받을 때마다 컴파일 할 필요가 없기에 속도 향상에 이점이 있다
부가적으로 입력받는 parameter를 제외하고 모두 컴파일링을 진행 해두었기 때문에 추가적인 SQL Injection이 들어와도 동작하지 않게된다.
Ex )
select * from user where userName =(컴파일)=> 10101010111010101010 ? =(파라미터 입력)=> 10101010111010101010 '팥들었슈' and '1'='1'
위는 예시일 뿐이며 정확이 이와 동일하게 동작하지는 않는다.
prepared Statement를 사용할 수 없는 SQL 구문이 있다.
order by 구문이다.
동적은 order by를 사용하고 SQL Inection을 방지하려면 입력받는 order by 구문을 화이트리스트로 관리하는 것이 적절하다.
if (sortWhiteList.include(request.getSort())) {
// 입력 받은 sort가 화이트 리스트에 있는 경우 진행
} else {
// 입력 받은 sort가 화이트 리스트에 없다면 기본값으로 세팅
request.setSort("기본값");
}
PS. 구문해석하기
case 1: sotingAd=,(case+when+ascii(substr((select+user+from+dual),1,1))=0+then+1+else+(1/0)+end)
case 2: page=1&board_id=&sorting=A.REG_DT&sotingAd=ASC;if+substring((select%20user_name()),1,1)=%27a%27+waitfor+delay+%270:0:1%27&startDt=&endDt=&keyword=
case1은 request의 sorting에 넣은 값으로 보여지며 +는 url encoding의 space이다.
sql에 들어가는 구문으로 변경해본다면
select * from user order
by Ad, (case when ascii(substr((select user from dual),1,1))=0 then 1 else (1/0) end)
로 변경되어 SQL에 들어가게 되며 Ad, 뒷부분이 injection이 된다.
'user' 문자열을 1,1로 substr 하였기 때문에 나오는 값은 u
u를 ascii로 변환하면 117이며 117 = 0 은 false 이기 때문에 1/0이 실행되지만 0으로 값을 나눌 수 없기 때문에 에러가 발생
즉 참이라면 화면의 결과가 나오고 거짓이라면 에러가 발생하기 때문에 화면에 값이 표출 않는다. 즉 blind SQL을 사용하기 위한 구문
case2을 url decode 하면
if substring((select user_name()),1,1)='a' waitfor delay '0:0:1'&startDt=&endDt=&keyword=
sql Injection 되는 부분은 order by A.REG_DT ASC 구문 이후가 될 것이다.
select * from user order
by order by A.REG_DT ASC;
if substring((select user_name()),1,1)='a' waitfor delay '0:0:1'
가 될텐데
; 이후 if 문이 가능한가???
'웹 해킹 코스 > 내용 정리' 카테고리의 다른 글
11차 HTML의 DOM 접근 (0) | 2024.01.15 |
---|---|
9주차 XSS(크로스 사이트 스크립트) (0) | 2023.12.21 |
6주차 union을 사용한 SQL Injection (0) | 2023.11.30 |
5주차 SQL Ijection (2) | 2023.11.26 |
4주차 (burp suitte) (0) | 2023.11.15 |