2023. 4. 28. 10:23ㆍ해킹/SQL Injection
Blind SQLi은 말 그대로 Blind.
데이터의 결과 Result가 안보이는곳에서 주로 쓰입니다만. 거의 모든곳에서 사용할수있는 놈입니다.
어떤 기법이냐면. 로그인할때를 예시로 들어보겠습니다.
로그인 할때 알맞는 아이디를 입력하면 로그인이 성공되었습니다가 뜨겠죠.
하지만 알맞지 않는 아이디를 입력한다면? 로그인이 실패되었습니다가 뜨겠죠.
이를 통해서 참과 거짓을 구별할수만 있다면 조건을 삽입해서 맞추어 나가는겁니다.
이러한 SQL 이 있다고 가정해보겠습니다.
select id,password from member
where id = ?
데이터베이스에는 이러한 정보가 있다고 가정해보겠습니다.
id : testhack
password : 1234
그렇다면. testhack를 입력하면 저기 조건이 참으로 나오면서 로그인 성공이 나오겠죠?
select * from member
where id = 'testhack'
그러면 여기서 한가지 조건을 추가해보겠습니다.
select * from member
where id = 'testhack' and (select database() = 'database123')
이런 조건을 삽입했다면, 실제로 database의 이름이 database123이라면 참조건이 되서 로그인이 되고 이름이 맞지않으면 로그인 실패가 뜨겠죠.
감이 오실겁니다.
저 database123자리에 계속해서 대입해서 맞는지 안맞는지 보는거에요
하지만.. 너무 맞추기가 어렵죠.
그래서 1자리씩 분할해서 비교하는겁니다.
substring 이라는 함수를 통해서 분할이 가능합니다.
substring('database123',1,1); 이런식으로 하면 database123의 첫번째부터 1개까지를 뜻합니다.
따라서 d가 출력됩니다.
database의 첫번째 글자가 a가맞니? b가 맞니? 이런식으로 비교하는거죠!
그러면 substring('database123',2,2);
를 한다면 2번째에서 2개를 해당하니까 at가 나옵니다.
여기까지만 해도 가능합니다.
하지만 프로그래머는 어떠해야죠?
최적화,효율화,자동화를 기본적으로 생각하고있어야죠.
좀 더 효율적으로 할 수 있는 방법이 있습니다.
바로 ascii코드입니다.
아스키코드는 10진수로 따지면 0부터 127까지 숫자로 이루어진 코드입니다.
3개의 어쩌구비트 4개의 어쩌구비트로 2의 7승까지 표현이 가능한데 마지막 비트는 페티리 비트로 127까지 표현이 가능합니다. (사실 나도 잘 모름 검색 ㄱㄱ)
암튼 97은 a 98은 b 이런식으로 되어있습니다.
이게 왜 필요한지는 나중에 말하고 일단 해봅시다.
문자를 ascii 코드로 바꾸려면 ascii() 함수를 사용합니다.
select ascii('t'); 이런식으로 해보세용
116번이 출력되네요.
그러면 이런식으로 할수가 있겠네요
문자열을 1개로 쪼개고 그걸 ascii로 변환해서 값이 큰가 작은가.
SELECT * FROM member
WHERE id = 'ww' and (ascii(SUBSTRING((select DATABASE()),1,1)) > 116);
이런식으로 해서 비교를 합시다.
ascii 코드로 변환한 이유는 다음과 같습니다.
숫자는 큰지 작은지를 비교해서 빠르게 찾아낼수 있습니다.
처음에는 0을 대입해서 작동하는지 확인합니다.(0보다 작은 문자는 존재하지 않기때문에 모두 참일것.)
작동을 한다면. 아스키코드는 아까 뭐라고 헀죠? 0부터 127까지 존재한다고 했죠.
그래서 50보다 크니? 70보다 크니? 100보다 크니? 이런식으로 반절씩 비교를 하면 더 빠르게 찾을 수 있습니다.
이것을 2진탐색 알고리즘이라고 합니다.
즉 2진탐색 알고리즘을 위해서 아스키코드로 변환했다 라고 할수가 있죠.
네. 끝입니다. 이제 방법을 알았으니까 저번 Union과 똑같이 순차적으로 database를 털면 됩니다.
database만 예시로 공격해보겠습니다.
하기전에 아이디는 무조건 참이여야합니다. 해커 자신이 회원가입을 하거나 아니면 OR 1=1까지 집어넣어야겠죠.
1234라는 아이디가 있다고 가정해보고 진행하겠습니다.
이런 쿼리문을 작성했었죠. 일단 1번째 글자는 T라는것을 알았으니까 두번째 글자를 구해봅시다.
2번째 글자가 50보다 큰가를 비교했는데 결과가 나왔습니다. 100을 넣어보겠습니다.
결과가 나온것을 볼 수 있습니다.
120을 넣었지만? 결과가 나오지 않았네요.. 즉 100보다는 크고 120보다는 작다는것.
110을 넣었지만 똑같이 안나오네요.
105를 넣어도 안나옵니다.(뒤에 sss는 무시하세요 실수로 적은거입니다.)
102를 해보아도 나오지 않습니다.
101을 해보아도 나오지 않습니다. 즉 DATABASE의 두번째 문자는 아스키코드의 101번이라는 뜻입니다.
결과가 안나왔는데 왜 101번인가요?
아까 100을 비교했을때 100은 출력되었습니다.
비교문이 뭐였죠? 100보다 큰가였습니다. 따라서 100보다 크다라고 할 수가 있고
101보다 큰가를 했을때 거짓이였습니다 따라서 100보다 크고 101보다 크지 않다는 결론이 나옵니다.
101이라고 말할수가 있는거죠.
아스키코드표를 보면 101번은 e 입니다. 따라서
database의 첫번째 글자는 t이고 두번째 글자는 e라는것을 알아냈습니다.
이 작업을 반복해서 db명을 알아내고 union과 똑같이 테이블명 컬럼명 순서대로 터는것입니다.
아무리 최적화 했더라도 너무 오래걸리죠...
다음시간에는 자동화를 해보겠습니다.
'해킹 > SQL Injection' 카테고리의 다른 글
SQL Injection - 대응방안 (0) | 2023.04.28 |
---|---|
로그인 우회 3번째문제 (0) | 2023.04.23 |
데이터 추출 두번째 문제 (0) | 2023.04.23 |