1. NOSQL injection
nosql: sql을 사용하지않고 복잡하지 않은 데이터를 저장해, 단순 검색 및 추가 검색 작업을 위해
매우 최적화된 공간
Non-Relational DBMS)
-MongoDB
: json 형태인 도큐먼트를 저장/ sql 처럼 쿼리문이 아닌, 객체 기반의 쿼리를 사용
-MongoDB 연산자
comparison | $eq | 지정된 값과 같은 값을 찾음 |
$in | 배열 안의 값들과 일치하는 값을 찾음 | |
$ne (not equal) | 지정된 값과 같지 않은 값을 찾음 | |
$nin (not in) | 배열 안의 값들과 일치하지않는 값을 찾음 | |
Logical | $and | 논리적 and, 각각의 쿼리를 모두 만족하는 문서 반환 |
$nor | 논리적 nor, 각각의 쿼리를 모두 만족하지않는 문서가 반환 | |
$or | 논리적 or, 각각의 쿼리 중 하나 이상 만족하는 문서 반환 | |
$not | 쿼리 식의 효과를 반전시킴 | |
element | $exists | 지정된 필드가 있는 문서를 찾음 |
$type | 지정된 필드가 지정된 유형인 문서를 선택 | |
Evaluation | $expr | 쿼리 언어 내에서 집계 식을 사용o |
$regex | 지정된 정규식과 일치하는 문서를 선택 | |
$text | 지정된 텍스트를 검색 |
-Mongo의 기본 문법 (취약점을 읽어내기 위한 기본 지식 획득!) <- nosql injection 발생 가능성 존재
#문서 조회
db.account.find()
db.account.find(
{ user_id: "admin" }
)
db.account.find(
{ user_id: "admin" },
{ user_idx:1, _id:0 }
)
#insert
db.account.insertOne(
{ user_id: "guest",user_pw: "guest" }
)
#delete
db.account.remove()
db.account.remove(
{user_id: "guest"}
)
#update
db.account.updateOne(
{ user_idx: 2 },
{ $set: { user_id: "guest2" } }
)
-MongoDB의 nosql injection은 어떻게 발생할까?
ex.
# 사용자 로그인 로직
db.users.findOne({ username: req.body.username, password: req.body.password });
1. 사용자의 입력을 그대로 쿼리에 사용하는 경우,
{
"username": { "$ne": null }, #$ne: 지정된 값이 아닌 값을 찾음
"password": { "$ne": null }
}
2. 공격자는 위와 같이 입력이 가능.
db.users.findOne({ username: { $ne: null }, password: { $ne: null } });
3. 그 경우, 사용자 이름과 비밀번호가 null이 아닌 모든 사용자 중 하나를 반환하게 됨
-대응 방안: 사용자의 입력값을 검증
ex2.
blind nosql injection을 이용해 공격도 가능!
$expr | 쿼리 언어 내에서 집계 식 사용 가능 |
$regex | 지정된 정규식과 일치하는 문서를 선택 |
$text | 지정된 텍스트를 검색 |
$where | javascript 표현식을 만족하는 문서와 일치 |
#이런 코드를 이용해서 upw의 첫 글자를 한글자씩 비교해, 알아낼 수 있음
db.user.find({$where: "this.upw.substring(0,1)=='a'"})
db.user.find({$where: `this.uid=='${req.query.uid}'&&this.upw=='${req.query.upw}'`});
/*
/?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
=> 시간 지연 발생.
*/
이런식으로, 시간 지연을 통해서 참, 거짓 결과를 확인할 수 있다.
-> 참을 반환할 때 sleep 함수를 실행
Non-Relational DBMS)
-Redis
: 키-값의 쌍을 가진 데이터를 저장
다른 DB와는 다르게, 메모리 기반의 DBMS-> 다른 DBMS보다 훨씬 빠르게 수행
임시 데이터를 캐싱하는 용도
(캐싱: 파일 복사본을 캐시 또는 임시 저장 위치에 저장하여 보다 빠르게 액세스할 수 있도록 함)
-데이터 조회 및 조작 명령어
GET | GET key | 데이터 조회 |
SET | SET key value | 새로운 데이터 추가 |
-관리 명령어
명령어 | 구조 | 설명 |
INFO | INFO[section] | DBMS 정보 조회 |
CONFIG GET | CONFIG GET parameter | 설정 조회 |
CONFIG SET | CONFIG SET parameter value | 새로운 설정을 입력 |
parameter: 매개변수
-Redis <- command injection 발생 가능성 존재!
그렇다면 어떤식으로 발생할 수 있는걸까?
(command injection: 운영체제에 명령어를 주입시켜, 공격자 마음대로 공격실행)
ex.
username = request.GET['username']
user_data = redis.get("user:" + username)
1. 로그인 시 사용자 이름을 받아서 Redis에서 정보를 조회하는 코드가 있음
username=admin\r\nSET user:admin hacked
#\r\n: 다른 명령어로 이어지게 하는 줄바꿈 문자
#SET: 새로운 데이터를 추가하는 명령어
2. 공격자가 악의적인 의도로 위와 같은 코드를 작성할 시,
GET user:admin
SET user:admin hacked
3. 컴퓨터는 이렇게 인식하게 되고, admin 계정을 hacked로 덮어쓸 수 있게 된다.
Non-Relational DBMS)
-CouchDB
: MongoDB와 같이 JSON 형태인 도큐먼트를 저장.
웹 기반의 DBMS
REST API 형식으로 요청처리
-특수 구성 요소
Server
/ | 인스턴스에 대한 메타 정보 반환 |
/_all_dbs | 인스턴스의 데이터베이스 목록을 반환 |
/_utils | 관리자 페이지로 이동 |
Database
/db | 지정된 데이터베이스에 대한 정보를 반환 |
/{db}/_all_docs | 지정된 데이터베이스에 포함된 모든 도큐먼트 반환 |
/{db}/_find | 지정된 데이터베이스에서 JSON쿼리에 해당하는 모든 도큐먼트 반환 |
-> couchDB와 MangoDB는 비슷하게 injection방식이 발생할 수 있음
2. command injection
: 운영체제에 명령어를 주입시키는 방식
-이용자의 입력을 시스템 명령어로 실행하게 하는 취약점
-명령어를 실행하는 함수에 이용자가 임의의 인자를 전달할 수 있을 때 발생
ex. 특수 환경인 특정 관리 콘솔에 시스템 명령어 실행을 할 수 있는 경우에 존재
command injection | sql injection |
사용자 입력값을 통해서 시스템 명령어 실행하는 기능하는 경우 command injection의 잠재성이 존재 | application과 데이터베이스와 연결되어 값을 반환할 때 공격자가 sql 구문 삽입을 통해 공격 당할 잠재성이 존재 |
-어떤 식으로 발생하는가?
(사용자 입력 값+미완성된 시스템 명령어 구문)의 형태에서
공격자가 CMD로 입력 값을 주입하고, 완성된 시스템의 명령어 구문을 만들어 공격
ex.
정상적인 입력값: nslookup www.test.co.kr
비정상적인 입력값: nslookup www.test.co.kr&ifconfig
#명령어 후 공격자가 원하는 명령어인 ifconfig(반환값을 알려줌)을 실행
*웹쉘과 비슷한 역할을 한다고 볼 수 있다.
+웹쉘이란?
1. 공격 대상의 컴퓨터에 악성파일을 설치
2. 공격자가 특정 웹사이트에 접속해 명령어를 입력하면, 공격 대상에 대한 정보를 빼낼 수 있음
-> 이러한 과정을 거친 공격방식을 웹쉘이라 함
-command injection에 사용되는 메타 문자들
" | " 안에 들어있는 명령어를 실행한 결과로 치환 |
$() | 명령어 치환. $() 안에 들어있는 명령어를 실행한 결과로 치환 |
&& | 명령어 연속 실행. AND |
|| | 명령어 연속 실행. OR |
; | 한줄에 여러 명령어를 사용하고 싶을 때 단순히 명령어를 구분짓고, 앞 명령어의 에러 유무와 관계없이 뒷 명령어를 실행 |
| | 파이프. 앞 명령어의 결과가 뒷 명령어의 입력으로 들어감 |
-command injection의 대응방안
:사용자의 입력값을 검사하는 방향으로 가야함
3. 워게임 풀이
#1 command injection -1
step1 | 코드분석-> host의 답을 받아 별도의 검사없이 넣음 |
step2 | 취약점 분석-> 즉, command injection 이 가능하다 공격 코드 생각-> flag는 flag.py 파일에 존재, 읽어들여야함 |
step3 | 코드 입력<- 특수 문자를 넣을 시 로그인이 안되는 옵션이 있었음 따라서, 개발자 툴을 이용해서 특수 문자를 넣을 수 있도록 조취함 |
생각해낸 코드 (로그인을 구성하는 파이썬 코드의 경우 cmd = f'ping -c 3 "{host}"'
“; cat flag.py” | O | 세미콜론 개수 맞춤 , ;가 존재, 명령어 실행 |
;”cat flag.py” | X | " 안에 ;가 존재 X, 단순히 문자열로 인식 |
127.0.0.1 "|| cat flag.py" | O | "; 의 이유가 마찬가지 |
127.0.0.1 ; cat flag.py | X | 코드의 " 처리가 되지않음 |
127.0.0.1" && cat flag.py" | O | 가능 |
결론: 세미콜론의 개수를 맞추고, 제대로 된 메타문자를 작성할 시 문제는 쉽게 풀린다.
#2 simple_sqli_chatgpt
step1 | 코드에서 취약점 확인 ->Sql injection 취약 코드 확인 가능 Sql injection이 일어나는 코드 res = query_db(f"select * from users where userlevel='{userlevel}'") 유의사항: flag를 얻을 수 있는 아이디가 데이터 베이스의 첫번째 인덱스가 아니기 때문에 admin을 지정해야함 |
step2 | 코드 생성 (level =0 이어야하고, 닉네임이 admin이어야함) |
+문제를 풀며 추가적으로 안 부분
get 방식과 post 방식의 차이
get: 데이터 조회, 정보요청
post: 데이터 전송
#3 baby-union
step1 | 원인파악: 로그인 시도 테이블로 어떻게 flag를 얻을 것인가 -> 코드를 다운받아보니, 테이블을 조회하는 등의 작업을 하면 flag를 얻을 수 있는 키가 있는 듯 함 |
step2 | 테이블 목록화 ‘union select table_name, null, null, null from information_schema.tables# |
step3 | 칼럼 목록화 ' union select column_name, null, null, null from information_schema.columns where table_name='onlyflag' # |
step4 | 데이터 목록화 ' union select svalue, sflag, null, sclose from onlyflag # |
'1. Web hacking (웹 해킹) > 2) 개념 정리' 카테고리의 다른 글
[25.05.16] 웹 떠봐요 5주차 활동 (0) | 2025.05.16 |
---|---|
[25.05.09]웹 떠봐요 4주차 활동 (0) | 2025.05.09 |
[25.04.04]웹 떠봐요 2주차 활동 (0) | 2025.04.04 |
[24.11.02] XSS(Cross-Site Scripting) / 파라미터 변조 (0) | 2024.11.08 |
[24.10.26] SQL Injectio (0) | 2024.11.01 |