티스토리 뷰

1. NoSQL은 표(테이블)에 얽매이지 않고 데이터를 자유롭게 저장하는 데이터베이스입니다.
2. 대용량·고속·유연한 구조가 필요할 때 쓰며, RDBMS를 대체하기보다 함께 씁니다.
3. SQL을 안 쓴다고 인젝션이 없는 게 아닙니다. NoSQL 인젝션과 무인증 노출이 핵심 위험입니다.
신규 서비스 취약점 점검을 하다 보면 이런 답변을 자주 듣습니다. "저희는 MongoDB라서 SQL 인젝션 항목은 해당 없습니다."
틀린 말은 아닙니다. SQL을 쓰지 않으니 SQL 인젝션은 성립하지 않습니다.
그런데 로그인 요청의 password 값을 {"$ne": null}로 바꿔 보내면, 비밀번호 없이 admin으로 로그인되는 경우가 있습니다. 이름만 다를 뿐 인젝션은 그대로 살아 있는 상태입니다. 이 글에서는 NoSQL이 무엇이고 왜 쓰는지, 어떤 종류가 있고 어디에 쓰는지, 그리고 보안 점검 시 무엇을 봐야 하는지를 정리했습니다.
🎯 NoSQL이란?
NoSQL은 "Not Only SQL"의 줄임말입니다. "SQL을 쓰지 않는다"가 아니라 "SQL 방식만 고집하지 않는다"는 뜻입니다.
| 구분 | RDBMS (관계형 DB) | NoSQL (비관계형 DB) |
|---|---|---|
| 비유 | 칸이 정해진 엑셀 표 | 자유롭게 쓰는 서류철 |
| 데이터 구조 | 테이블 · 행 · 열 (고정 스키마) | 키-값 · 문서 · 컬럼 · 그래프 (유연한 스키마) |
| 쿼리 언어 | SQL (표준) | 제품마다 다름 (MongoDB Query, Redis 명령어 등) |
| 확장 방식 | 주로 Scale-up | 주로 Scale-out |
| 일관성 | 강한 일관성 (ACID) | 제품에 따라 최종 일관성 허용 |
| 대표 제품 | MySQL, Oracle, PostgreSQL | MongoDB, Redis, Cassandra, Neo4j |

RDBMS에서 회원의 관심사를 저장하려면 별도 테이블을 만들고 JOIN을 해야 합니다. 문서형 NoSQL은 한 문서 안에 배열째 넣으면 끝납니다. 이 차이가 NoSQL의 장점이자, 뒤에서 볼 보안 문제의 출발점이기도 합니다.
🧩 왜 NoSQL을 쓸까?
| 문제 상황 | RDBMS의 한계 | NoSQL의 해결 방식 |
|---|---|---|
| 데이터 폭증 | 서버 한 대 성능을 키우는 데 한계 | 서버를 옆으로 늘리는 수평 확장 |
| 데이터 형태가 제각각 | 컬럼 추가·변경(ALTER)이 부담 | 스키마 없이 바로 저장 |
| 초고속 응답 필요 | JOIN·트랜잭션 비용 | 단순 구조로 빠른 읽기·쓰기 |
| 무중단 서비스 | 단일 서버 장애 시 전체 중단 | 복제·분산으로 장애 흡수 |

🔍 NoSQL 4가지 유형

| 유형 | 저장 방식 | 대표 제품 | 주요 용도 | 기본 포트 |
|---|---|---|---|---|
| 키-값 | Key 하나에 Value 하나 | Redis, DynamoDB | 로그인 세션, 캐시, 실시간 순위 | 6379 (Redis) |
| 문서형 | JSON(BSON) 문서 | MongoDB, Couchbase | 회원·상품·게시판 | 27017 (MongoDB) |
| 컬럼 패밀리 | 행마다 다른 컬럼 묶음 | Cassandra, HBase | 대량 로그, IoT 시계열 | 9042 (Cassandra) |
| 그래프형 | 노드와 관계(엣지) | Neo4j, Amazon Neptune | 친구 추천, 이상거래 탐지 | 7687 (Neo4j) |
기본 포트는 점검 시 외부 노출 여부를 확인할 때 그대로 쓰이니 같이 기억해 두면 좋습니다.
🛠 실제로는 이렇게 섞어 씁니다
현업 서비스는 DB 하나로 끝나지 않습니다. 데이터 성격에 맞춰 여러 DB를 조합하는데, 이를 폴리글랏 퍼시스턴스(Polyglot Persistence)라고 부릅니다.
| 데이터 | 추천 DB | 이유 |
|---|---|---|
| 결제·주문·계좌 | RDBMS | 정합성(트랜잭션)이 최우선 |
| 로그인 세션·인기 상품 캐시 | Redis | 메모리 기반, 밀리초 단위 응답 |
| 형식이 자주 바뀌는 상품 상세 | MongoDB | 스키마 변경 없이 필드 추가 |
| 대량 접속 로그 | Cassandra / Elasticsearch | 쓰기 성능과 확장성 |
| 연관 관계 분석 (추천·FDS) | Neo4j | 관계 탐색이 빠름 |
⚖️ 장단점 정리
| 구분 | ✅ 장점 | ❌ 단점 |
|---|---|---|
| 확장성 | 노드 추가만으로 수평 확장 | 분산 환경 운영 복잡도 증가 |
| 유연성 | 스키마 없이 빠른 개발 | 규칙이 없으면 데이터가 엉망이 됨 |
| 성능 | 단순 조회·대량 쓰기에 강함 | 복잡한 JOIN·집계는 비효율 |
| 일관성 | 가용성을 우선할 수 있음 | 강한 트랜잭션 보장이 약한 제품이 있음 |
| 표준화 | 용도별 최적 제품 선택 가능 | 제품마다 쿼리·보안 설정이 전부 다름 |
마지막 줄이 보안 담당자에게 가장 중요합니다. SQL은 하나를 알면 대부분 통하지만, NoSQL은 제품마다 인증·권한·인젝션 방식이 다릅니다. 점검 기준도 제품별로 따로 봐야 합니다.
⚠️ 보안 ① — NoSQL 인젝션

MongoDB는 쿼리를 문자열이 아니라 객체(JSON)로 받습니다. 그래서 입력값이 문자열이 아니라 객체로 들어오면, 값이 아니라 조건 자체가 바뀝니다.
// 공격자가 보낸 요청 (Content-Type: application/json)
{ "username": "admin", "password": { "$ne": null } }
// 취약한 서버 코드 — 요청 body를 그대로 조건에 넣음
db.users.findOne({ username: req.body.username, password: req.body.password })
// 실제 실행 조건 = "admin 이고 비밀번호가 null이 아니면" → 항상 참
| 공격 유형 | 삽입 예시 | 결과 |
|---|---|---|
| 연산자 인젝션 | {"$ne": null}, {"$gt": ""} |
조건이 항상 참 → 로그인 우회 |
| 정규식 인젝션 | {"$regex": "^a"} |
한 글자씩 비밀번호·토큰 추측 |
| JavaScript 인젝션 | $where 절에 코드 삽입 |
서버 측 JS 실행, DoS |
| 폼 파라미터 변조 | password[$ne]=x |
JSON이 아니어도 파서가 객체로 변환 |
password[$ne]=x 같은 일반 폼 요청도 객체로 바꿔주기 때문에, "JSON 요청이 아니니까 괜찮다"는 판단도 틀릴 수 있습니다.대응 방법
| 대책 | 내용 |
|---|---|
| 타입 검증 | 문자열이어야 할 값이 객체·배열이면 거부 |
| 연산자 필터링 | $로 시작하거나 .이 포함된 키 제거 (express-mongo-sanitize, Mongoose sanitizeFilter 등) |
$where 금지 |
서버 측 JavaScript 실행 비활성화 (security.javascriptEnabled: false) |
| 스키마 검증 | 앱 단(Joi, Zod 등) 또는 DB 단(JSON Schema Validator)에서 형식 강제 |
⚠️ 보안 ② — 인증 없이 열려 있는 DB
NoSQL 사고의 상당수는 해킹 기술이 아니라 설정 문제입니다. 인증 없이 인터넷에 열린 MongoDB·Elasticsearch·Redis가 통째로 삭제되고 복구 대가를 요구받는 사례가 반복돼 왔습니다.
| 제품 | 흔한 문제 | 확인 포인트 |
|---|---|---|
| MongoDB | 인증 미설정, bindIp: 0.0.0.0 |
security.authorization: enabled 여부 |
| Redis | requirepass 미설정, protected-mode 해제 |
무인증 접속 시 명령 실행 가능 여부 |
| Elasticsearch | 보안 기능 비활성화로 REST API 공개 | 9200 포트 무인증 응답 여부 |
| 공통 | 평문 통신, 관리자 계정 공용 사용 | TLS 적용, 계정별 최소 권한 |
rename-command, ACL)를 권장합니다.📋 점검 체크리스트
| 확인 항목 | 확인 방법 (예시) | 체크 |
|---|---|---|
| 외부에서 DB 포트가 열려 있지 않은가 | nmap -p 6379,9042,9200,27017 <대상IP> |
☐ |
| MongoDB 인증이 활성화되어 있는가 | mongod.conf의 security.authorization |
☐ |
| MongoDB 바인딩 IP가 제한되어 있는가 | net.bindIp 값 확인 |
☐ |
| Redis 비밀번호/ACL이 설정되어 있는가 | CONFIG GET requirepass / ACL LIST |
☐ |
| Redis protected-mode가 켜져 있는가 | CONFIG GET protected-mode |
☐ |
| 앱 계정이 최소 권한인가 (root/admin 미사용) | db.getUsers() 권한 목록 |
☐ |
| 입력값 타입 검증·연산자 필터링이 있는가 | 로그인·검색 API에 {"$ne":null} 테스트 |
☐ |
| 서버 JS 실행이 비활성화되어 있는가 | security.javascriptEnabled |
☐ |
| DB 통신에 TLS가 적용되어 있는가 | net.tls.mode |
☐ |
| 백업·접근 로그가 남고 있는가 | 백업 주기, 감사 로그 설정 | ☐ |
🚫 이런 판단은 하지 마세요
① "SQL을 안 쓰니 인젝션 항목은 해당 없음"
SQL 인젝션은 해당 없어도 NoSQL 인젝션은 해당됩니다. "SQL 인젝션"이 아니라 "쿼리 인젝션" 관점으로 보고, 실제 요청을 변조해서 확인해야 합니다.
② "내부망이라 인증 안 걸어도 된다"
내부망 PC 한 대만 감염돼도 무인증 DB는 바로 털립니다. 내부 네트워크 스캔에서 무인증 Redis·MongoDB가 나오면 고위험으로 분류하는 게 맞습니다.
③ "클라우드 관리형이라 알아서 안전하다"
관리형 서비스는 패치와 인프라를 대신해 줄 뿐, 네트워크 공개 범위·계정 권한·입력값 검증은 여전히 사용자 몫입니다.
④ "스키마리스니까 검증도 필요 없다"
스키마가 없다는 건 DB가 대신 검증해 주지 않는다는 뜻입니다. 그만큼 애플리케이션에서 더 엄격하게 검증해야 합니다.
💬 자주 나오는 질문
Q. NoSQL이 RDBMS보다 좋은 건가요?
우열이 아니라 용도 차이입니다. 돈이 오가는 데이터는 RDBMS, 대량·고속·유연한 데이터는 NoSQL이 맞고, 대부분의 서비스는 둘을 함께 씁니다.
Q. 정적 분석(SAST) 도구가 NoSQL 인젝션도 잡나요?
도구와 룰셋에 따라 다릅니다. SQL 인젝션 룰만 켜져 있으면 MongoDB 쿼리 패턴은 누락될 수 있으니, NoSQL 관련 룰이 활성화되어 있는지 확인하고 동적 점검으로 교차 검증하는 편이 안전합니다.
Q. Redis는 캐시일 뿐인데 보안이 그렇게 중요한가요?
캐시에 세션 토큰이 들어 있는 경우가 많습니다. 세션이 털리면 로그인 없이 사용자 계정을 탈취할 수 있고, 앞서 본 것처럼 서버 장악까지 이어질 수 있습니다.
Q. 입력값 필터링 라이브러리만 쓰면 끝인가요?
1차 방어로는 효과적이지만, 타입 검증 + 최소 권한 계정 + 네트워크 차단을 함께 적용해야 합니다. 하나가 뚫려도 다음 단계에서 막히는 구조가 목표입니다.
🎉 정리
- NoSQL은 "Not Only SQL" — 표에 얽매이지 않는 데이터베이스의 총칭이다.
- 목적은 확장성·속도·유연성이다. 대신 복잡한 조회와 강한 일관성은 약하다.
- 키-값·문서·컬럼·그래프 4가지 유형이 있고 용도가 다르다.
- RDBMS를 대체하는 게 아니라 함께 쓴다.
- SQL을 안 써도 인젝션은 있다. 입력값이 객체로 들어오는 순간 쿼리 구조가 바뀐다.
- 사고의 상당수는 설정 문제다. 인증·바인딩 IP·포트 노출부터 확인하자.
- 제품마다 보안 설정이 다르다. "NoSQL 점검"이 아니라 "MongoDB 점검", "Redis 점검"으로 봐야 한다.
"MongoDB라 인젝션 해당 없음"이라는 답변을 들으면, 로그인 API에 {"$ne": null} 한 번만 보내보세요. 그 한 번의 요청이 점검 결과를 바꿉니다.
🔗 참고 자료
'정보보안 > Web&Mobile' 카테고리의 다른 글
| [Android OS] Hot Swap 단말에서 USIM 변경 확인하는 방법 (0) | 2026.10.08 |
|---|---|
| 안드로이드 악성코드 방지 , Play Integrity API로 조치 (0) | 2026.10.07 |
| Flutter iOS 앱, 네이티브 호출부는 난독화하지 않아도 될까? (0) | 2026.09.22 |
| 가재코드(Gajae-Code), 구독으로 돌리는 코딩 에이전트 (0) | 2026.09.16 |
| Flutter 앱, 네이티브 난독화 안 해도 될까? (iOS 보안점검) (0) | 2026.09.11 |
- Total
- Today
- Yesterday
- 보안상식
- 취약점
- 개발자보안
- 자율침투테스트
- 소스코드진단
- 개인정보유출
- 펜테스트
- AI모의해킹
- sast
- 사이버보안
- IEC62443
- 정보보안
- AI보안
- 해킹주의
- 오픈소스보안
- 랜섬웨어
- 해킹예방
- 전자금융기반시설취약점분석평가
- cve
- E27
- 공급망공격
- 개인정보보호
- 시큐어코딩
- DevSecOps
- 선박사이버보안
- 악성코드
- 보안뉴스
- IACS
- 전자금융기반시설
- 금취분평
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
