NoSQL Injection 기법을 이용해서 flag 값을 얻어내는 문제이다.
문제 사이트 들어갔을 때의 모습이다.
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');
문제 파일을 확인해 보자
/login 페이지 코드이며 쿼리를 통해서 데이터베이스에서 이용자의 정보를 반환하는 것을 확인 했고
admin 계정으로 로그인을 해야하는 것을 알 수 있다.
(존재할 경우 해당 uid 전송, 아닐 경우 'undefined' 출력)
일부 문자열을 필터링하는 함수가 포함되어 있으며 'admin' , 'dh', 'admi'가 포함된 요청을 필터링하는 것을 확인할 수 있다.
어드민의 비밀번호에 플래그가 있고 어드민과 플래그 시작 문자열(dh)은 필터링 된 상태이므로 쿼리를 이용해 우회해야함을 알 수 있다.
쿼리문으로 데이터베이스에 있는 정보를 가져올 수 있으며 변수의 타입을 필터링하지 않기에 연산자를 사용할 수 있다.
[$regex]를 통해서 입력값이 맞는지 아닌지를 각각 따져볼 수 있다.
한 번씩 검증해야하는 NoSQL 기법으로 일일이 입력하는 것은 힘들 것 같아 파이썬으로 자동화 코드를 써보았다.
HOST에 사이트 주소를 입력 후 경로를 지정하는 곳에 연산자 regex를 포함해 반복하는 코드를 만들어 실행했다.
반복문을 통해서 플래그 값을 구할 수 있다.
'Write up - WEB' 카테고리의 다른 글
Dream Hack - Webhacking - Image Storage(File vunerability) (0) | 2023.04.01 |
---|---|
Dream Hack - Webhacking - command-injection-1 (0) | 2023.04.01 |
Dream Hack - Webhacking - simple_sqli (0) | 2023.04.01 |
Dream Hack - Webhacking - CSRF-2 (0) | 2023.04.01 |
Dream Hack - Webhacking - csrf-1 (0) | 2023.04.01 |