1.No-SQL Injection이란?
No-SQL
▷No-SQL 이란, 많은 수의 비정형적인 데이터를 다루기 위해 전통적 SQL에 비해 확장성과 유연성, 수행 능력에 초점을 맞춘 데이터베이스 형태로 4가지 형태로 구분할 수 있습니다.
①Document Store 형태
-Json, Bson, XML 와 같은 형태를 사용해 유연하게 데이터를 문서 형태로 저장하는 방식.
-Example: MongoDB, CouchDB
②Key-Value Store 형태
-Key:Value 형태로 저장되어 각 데이터 필드는 고유한 키 문자열과 연결.
-Example: Redis, Amazon DynamoDB
③Wide-Column Store 형태
-행을 대신해 열을 이용해 유연한 데이터를 구성.
-Example: Apache Cassandra, Apache HBase
④Graph databases
-data entity들을 저장하기 위해 노드를, entity들 간 관계를 저장하기 위해 edge를 사용하는 방식.
-Example: Neo4j, Amazon Neptune
No-SQL Injection
▷No-SQL Injection이란, Web Application에서 입력받아 데이터베이스로 전달하는 정상적인 No-SQL 질의를 변조, 삽입하여 불법 로그인, DB 데이터 열람/수정, 시스템 명령 실행 등을 수행하여 비정상적인 데이터베이스 접근을 시도하는 공격 기법입니다.
*아래 예시는 대표적인 No-SQL Database인 MongoDB를 기준으로 작성했습니다.
2.No-SQL Injection 공격 유형
syntax Injection
▷or, and 문법등을 이용한 N0-SQL Injection 방식으로, '인증 우회', '정보 추출' 등이 가능합니다.
#참, 거짓 조건에 따른 정보 추출
?category=fizzy’+%26%26+0%2F%2F
?category=fizzy’+%26%26+1%2F%2F
→’ && 0// 과 '&& 1//의 결과를 비교
→GET 파라미터 category의 값을 이용해 'category' 필드의 데이터를 조회하고, No-SQL Injection이 가능할 경우, AND 연산자(&&)와 0(거짓 조건) 혹은 1(참 조건)을 뒤에 삽입해 응답 결과를 바탕으로 정보를 추출하는 일종의 Blind SQL Injection 형식 공격입니다.
#추가 조건을 이용한 인증 우회
?passwd=fizzy%27%7c%7c%27%31%27%3d%3d%27%31
→’||’1’=='1 로 조건 덮어쓰기
→GET 파라미터 passwd 값을 이용해 'passwd' 필드의 데이터를 조회하고, No-SQL Injection이 가능할 경우, OR 연산자(||)와 참 조건('1'='1)을 이용해 앞 내용과 상관없이 결과를 참으로 만들어 인증을 우회하는 공격입니다.
operator injection
▷'$' 문자로 시작되는 operator를 이용해 특정조건 유무에 따라 정보를 추출하는 방식의 공격입니다.
→No-SQL 중 MongoDB는 $ne(같지 않음), $gt(더 큼), $gte(크거나 같음), $in(배열에 포함됨), $nin(배열에 포함되지 않음)과 같은 다양한 연산자들이 존재합니다. 해당 조건을 필드 연산에 추가하여 필드 자체에 대한 정보나 필드에 저장된 정보를 추출합니다.
#$regex 연산자를 이용한 필드 정보 추출
{"username":"admin","password":{"$regex":"^a.*"}}
→password 필드의 데이터를 사용자를 통해 받고 있고 No-SQL Injection이 가능할 경우, $regex 연산자를 통해 password 필드 값이 'a'로 시작하는지 질의하는 구문으로 Brute-Force를 통해 정보 추출이 가능합니다.
메소드에 따른 데이터 삽입 방법
▷GET 파라미터 값을 이용해 데이터를 변화시키는 페이지가 존재할 때, 공격자가 미리 파라미터 값을 설정해 URL을 제작하고 이를 피해자에게 클릭하도록 유도하여 피해자가 원치 않는 악의적 요청이 전송되게 하는 방식의 CSRF.
3.대응법
사용자 입력 검증
▷No-SQL Database는 종류가 다양하기 때문에 해당 DB의 문서를 참고하여 사용자 입력 검증을 진행하는 것이 가장 최선의 대응법입니다.
// sanitization 함수 정의
var username = req.body.username;
if (!/^[a-zA-Z0-9_]+$/.test(username)) {
throw new Error("Invalid username format");
}
*실제로 사용하기 위해서는 다양한 입력값 조건을 생각해야 하므로 더 세밀한 regex 정의가 필요할 것입니다.
// mongo-sanitize module 사용
var sanitize = require('mongo-sanitize');
var name = sanitize(req.params.name);
var password = sanitize(req.params.password);
4.Advanced
Time Based No-SQL Injection
▷$where 연산자를 사용해 필드를 조회하는 경우 javascript 구문을 허용하고 있을 수 있습니다. 이를 이용하면 sleep 함수를 사용해 시간 차를 이용해 정보를 추출할 수 있습니다.
//structure: {"$where": "this.username == 'admin'"}
admin’+function(x){if(x.password[0]==="a"){sleep(5000)};}(this)+'
→username 필드 값을 이용자로부터 받고 있는 예시로, password 필드의 첫번째 index 값([0])이 'a'인지 확인 후 참이라면 sleep(5000)을 실행하는 구문입니다.
*참고 자료
-https://portswigger.net/web-security/nosql-injection
'knowledge > web' 카테고리의 다른 글
Athentication&Athorization Vulnerability (0) | 2024.08.01 |
---|---|
File vulnerability (0) | 2024.07.29 |
Cross-Site-Script (0) | 2024.06.13 |
SQL Injection (0) | 2024.05.09 |
Solar, exploiting log4j - Tryhackme (0) | 2024.04.29 |