본문 바로가기
SeSAC/보안관제

[SeSAC 성동캠퍼스 1기] 온프레미스와 클라우드 환경의 보안관제 실무 2일차

by zivvon 2023. 12. 27.
목차 접기

[ URL 구조 ]

ex) https://test.com/?abcd=1234

- https : 사용하는 프로토콜 

- test.com : 도메인 (절대 변하지 않는 값, 고정된 주소)

- ?abcd : 변수 (파라미터)

- 1234 : 변수에 대입할 데이터 값

 

ex) https://test.com/abcd/1234

- abcd : path(경로)를 나타냄

- 1234 : page를 나타냄

 

ㄴ abcd 또는 1234에 sql쿼리나, LFI, XSS 등을 입력 해도 실행 안됨

ㄴ why? https//test.com/abcd/1234는 모두 path로 인식

 

ex) https://test.com/abcd/<script>alert('test')</script> 를 WAF는 탐지를 하는데 이를 오탐이라고 함.

>> 대표적 오탐

 

오탐인지 정탐인지 구분하는 법 알기!

 

관제는 취약점에 대한 이해도가 높아야 함

그래야 빠르게 진단


 

[ 웹 취약점 진단 ]

1. 파라미터 변조

2. 게시글 입력

3. 프로세스 검증 -> 탐지 불가능

why? 웹 방화벽에서는 정상적 실행 흐름인지 아닌지 진단 못 함

유일하게 할 수 있는 것은 웹 서버 소스코드 상에서 검증해야됨

 

공격 : 일련의 절차를 통해 접근해야할 페이지가 있을 때, 절차 무시하고 특정 페이지 호출하는 과정 (프로세스 검증이 없음)

 

4. 자동화 스캔

공격 : 파라미터 변조와 같이 사용됨. url 주소 고정시켜두고 그 뒤에 들어갈 데이터 값만 변조함 or 취약한 패스워드 ?예?

 

=> 1, 2, 4번만 웹 방화벽으로 탐지 가능

 

[ 웹 취약점 이해 ]

1. Command Injection : 명령어 주입 공격 (시스템에서 사용하는 명령어를 사용할 수 있는 환경)

>> 취약점 발생 조건 : 소스코드 내 시스템 함수 사용

ㄴ 소스코드 시스템 함수 : exec, system, cmd, shell과 같은 함수 사용

>> 취약점 검증 : ' ; ', ' | ', ' || ', '&& '를 통해 검증 가능

ㄴ ' ; ' : 첫 번째 명령어랑 상관 없이 두 번째 명령어 실행

ㄴ ' | ' : 첫 번째 명령어 에러 발생 시 두 번째 명령어 실행

ㄴ ' || ' : 첫 번째 명령어 성공 시 두 번째 명령어 실행 안 함

ㄴ ' && ' : 첫 번째 명령어 실행 시, 두 번쨰 명령어 실행

 

✅ 파라미터 데이터에 ';ls'와 같이 입력하여 실행 여부 확인!

ㄴ 입력되는 데이터의 인코딩 여부 고려를 해야함

 

- 일반적인 웹에서는 취약점이 거의 없음, 네트워크 장비의 관리자 페이지에서 command injection과 같은 취약점이 많이 발생됨

~> 단순히 웹 서버만 보호할 게 아니라 모든 대역에 대한 보호가 필요!

 

2. File Inclusion : 파일 참조 공격

-1. LFI : local

>> ../../../../../를 통해 특정 위치 파일 참조 (or file:///로 특정 파일 열람)

ex) ?page=file1.php와 같은 구조는 취약점 확률이 높음

LFI 취약점 검증

 

-2. RFI : remote

>> http://~ 원격지 주소

RFI 취약점 검증 *include 옵션이 꺼져있어서 빈 화면이 출력

 

=> 취약점 원인 : include, locate, show, content, action 등의 함수에서 발생

=> 취약점 검증 : 파라미터 데이터에 입력, 리퀘스트 바디(본문) 필드에 입력하여 검증

 

=> LIF는 단순히 타겟 서버에 저장되어 있는 파일을 열람하는 수준에서 그치지만, RFI는 공격자가 만들어놓은 취약한 페이지를 타겟시스템으로 import(임포트)하여 실행하기 때문에 RCE(Remote Code Excution) 공격으로 연계 가능

= 즉, RFI가 가능하면 원격지에서 타겟시스템에 원하는 파일을 생성하거나 실행이 가능하다!

 

3. FileUpload : 게시판의 업로드 기능을 통해 악성 파일을 업로드하여 실행

- 취약점 : 확장자 기반의 필터링, 헤더 정보에 컨텐츠 타입 필터링

- 취약점 검증 : php, sh, html 등 확장자를 가지는 파일 업로드

- FileUpload는 게시판 뿐만 아니라 Method를 통해서도 강제 업로드 가능(WAF(웹 방화벽)로 대응 불가)

ㄴ PUT 메소드가 활성화 되어 있어도, 해당 디렉토리에 쓰기 권한이 없으면 사용 불가

ㄴ 사용되는 method는 path 별로 각각 설정도 가능!

= 즉 폴더별로 쓰기권한이 다를 경우 취약점이 없을 수 있음, *서브 도메인까지 모두 확인 필요!

ex)*서브 도메인 : http://mail.test.com (메인 도메인은 http://test.com) 

 

4. SQL Injection : SQL 쿼리를 통해 원하는 정보를 추출하는 취약점, 또한 SQL DB를 통해 쉘(OS Shell) 실행도 가능

ex) SELECT first_name, last_name FROM users WHERE user_id = '$id'

  • select : 검색 쿼리
  • first_name, last_name : 컬럼명
  • FROM users : 검색할 테이블 지정
  • WHERE : 조건 설정
  • user_id='$id' : id가 N 입력될 경우 first name & last name 출력 

ex) WHERE user_id = '1 ' or '1'='1' #' 조건절만 확인하면 됨!

ㄴ why?

  • SQLi 원리 : 1 ' or '1'='1' # => 쿼리를 완성하여 구조(문법)오류 제거
  • or은 둘 중 하나가 참이면 무조건 반환(저장된 첫 번째 행 데이터가 출력됨)

ex) WHERE user_id = 'test' AND pass=' ' or 1=1 #'

  • 로그인 우회 : 'or 1=1 # , 'or 1=1 -- ( #, -- : 주석처리 구문) 

ex) WHERE user_id = ' 'union select 1, 2, 3# : 컬럼 개수 파악

  • 정보 추출 : 테이블에 저장된 데이터들을 전부 조회, 'union select 구문(다중 검색 구문)을 사용'
  • 컬럼 개수 파악은 내가 쿼리를 입력하고 있는 페이지 기준! -> 반환되는 데이터 구조 ex) 게시글 조회 시, id, content, date, name처럼 4개의 컬럼으로 구성 시 union select 1, 2, 3, 4#을 입력해야 정보추출(SQLi)이 가능한지 확인 가능
  • 1, 2, 3을 하나씩 증가하여 입력 컬럼 개수 찾음

- login 과정, 게시판 글 조회, 검색 시 SQL 쿼리를 통해 이루어짐

  • login : 내가 입력한 ID, PW를 DB에 저장되어 있는지 조회
  • 게시판 글 : 게시판에 대한 고유 번호, 컨텐츠 내용, 작성일, 작성자와 같은 정보가 DB에 저장 >> 게시글 조회 시 DB에 저장된 글인지 확인
  • 검색 : 입력한 키워드를 통해 SQL 쿼리를 사용해 DB에 저장된 데이터가 있는지 조회

=> WAF 로그에 다양한 SQL 쿼리 로그 식별 시, 홈페이지에 SQLi 취약점이 있는지 확인만 하면 됨!

(가장 기본이 되는 구문 입력으로 실행 가능여부 판단)

 

현재 사용하고 있는 컬럼 개수 확인 (2개)
버전 정보 출력

 

- 유저 정보 확인 쿼리 : 1'union select 1,schema_name from information_schema.schemata#

  • schema_name : DB 이름
  • information_schema : table, DB 정보 가지고 있는 테이블(DB 이름, Table 이름, 컬럼명을 저장)

user 정보 확인, dvwa : 웹 서버 구성하고 있는 데이터베이스

 

- 테이블 출력 쿼리  : 1'union select 1,table_name from information_schema.tables#

+ 조건 붙이기 : 1'union select 1,table_name from information_schema.tables where table_schema='dvwa'#

 

- 컬럼명 출력 쿼리  : 1'union select 1,column_name from information_schema.columns where table_name='users'#

 

- user, password 컬럼 값 추출하기  : 1'union select user,password  from users#

 

crackstation.net

 

5. XSS(Cross Site Script) : 스크립트를 통해 정보를 전송하거나 다운로드 할 수 있게 하는 취약점

*CSRF : XSS 취약점이 있어야 가능

 

- <script>, <img>, <div>와 같은 태그가 허용 되어 있을 경우 가능

  • <script>alert("test")</script>로 취약점 검증

- XSS를 가지고 할 수 있는 고도화된 공격은 없음 (악의적인 페이지로 리다이렉트 되도록 코딩 가능)

 

 

 

[ DB 이해 ]

- 데이터베이스 : 테이블이 저장되어 있는 전체 구조

- 테이블 : 특정 목적을 가지는 컬럼과 행으로 구성

- 컬럼 : 더이상 쪼개질 수 없는 속성 정보 

- 행 : 저장되는 데이터

 

* 일반적으로 WEB 서버는 1개의 DB 안에 여러 개의 Table로 구성

 

[ DB와 아파트 ]

- 데이터베이스 = 아파트 이름 ex) 래미안

- 테이블 = 각 호실 의미 ex) 903호

- 컬럼 ex) 주방 기기, 욕실, 식탁 등

- 행 ex) 주방 안에 있는 실제 용품들(도마, 식탁 ...)

 


 

[ 대응 방안 ]

*WAF는 정적(알려진) 데이터 기반으로 가능

 

1. Command Injection

*파라미터 변조 공격과 같이 보기!

- 가장 쉬운 대응은 ' ; ', ' | ', ' || ', ' && ' 문자열을 치환 (시큐어 코딩)

- WAF에서 문자열을 탐지하도록 룰 설정

 

2. File Inclusion

- 가장 쉬운 대응은 ' ../ ', ' file:/// ', ' http:// ', ' https:// ' 문자열을 치환

- WAF에서 문자열을 탐지하도록 룰 설정

ex) http://test.com/?abcd=https://attack.com 

⚠️탐지 영역을 REQUEST_URI 또는 REQUEST_BODY로 설정해야함

 

3. File Upload

- 화이트리스 기반 확장자 필터 설정(시큐어코딩)

- 업로드되는 경로에 실행 권한 제거

- WAF(웹 방화벽)에서 REQUEST_BODY에 포함된 문자열을 탐지

  • 악성파일에서 많이 사용되는 문자열 탐지 ex) shell, /bin/sh, /bin/bash, cmd 등

4. SQLi

- '(싱글쿼터)만 시큐어 코딩

- 웹서버 설정 변경(masic_quoter)

- WAF ' select, union, ' , --, # ' 사용할 수 없도록 문자열 필터링

  • REQUEST_Body, Header, ARGS 체크

5. XSS

- ' <(리다이렉션 시작) ' 문자열 시큐어 코딩 (tag 문자열도 필터링)

- WAF ' <, script, img, div ' 문자열 탐지

  • REQUEST_Body, Header, ARGS 체크

6. 헤더 변조 

- user_agent : curl, sqlmap, acunectix, owasp-zap 등

- WAF에서 REQUEST_HEADER에서 탐지하도록 룰 설정

 

제대로 탐지되면 나오는 결과 화면

 

⚠️파라미터 데이터를 자동화하여 대입하는 공격 유형들은 WAF로 대응 불가!

 

정규표현식을 지원하기 때문에 sqlmap >> s q l m a p과 같은 WAP 우회용 코드들도 탐지 가능

 

웹 취약점은 단순한 공격코드만 사용하는 게 아니라, WAF와 같은 보안 솔루션(시큐어 코딩까지)을 우회하기 위해 NULL 문자를 포함하기도 함!

 


 

[ WAF 로그 분석 ]

- /var/log/apache2에 저장

- error.log, modsec_audit.log 2개의 로그를 확인하면 됨

- Modsecurity log는 A~Z까지의 field로 구성됨 (6개 정도 사용)

  • modsec_audit.log가 필드로 구성됨

- error.log는 딱 한 개의 필드 탐지 내역만 저장해줌

 

error.log

[Tue Dec 12 02:22:19.710997 2023] [security2:error] [pid 114982] [client 127.0.0.1:33688] [client 127.0.0.1] ModSec
urity: Access denied with code 403 (phase 2). Operator GE matched 5 at TX:anomaly_score. [file "/usr/share/modsecur
ity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "94"] [id "949110"] [msg "Inbound Anomaly Score Exceeded
 (Total Score: 8)"] [severity "CRITICAL"] [ver "OWASP_CRS/3.3.5"] [tag "application-multi"] [tag "language-multi"] 
[tag "platform-multi"] [tag "attack-generic"] [hostname "127.0.0.1"] [uri "/dvwa/vulnerabilities/exec/"] [unique_id
 "ZXgKK2Mk9rYmZQLfo2dyiwAAAAI"], referer: http://127.0.0.1/dvwa/vulnerabilities/exec/

 

- [Tue Dec 12 02:22:19.710997 2023] : 시간 정보 

- [client 127.0.0.1:33688] : 원격지 정보

- [client 127.0.0.1] : 서버 IP

- [line "94"] : 탐지된 룰

 

modsec_audit.log                                          

--6aee0714-A--
[12/Dec/2023:02:41:45.653926 --0500] ZXgOuYH8vycC4Q8uZuyEhwAAAAE ::1 59172 ::1 80
--6aee0714-B--
POST /dvwa/vulnerabilities/xss_s/ HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 103
Origin: http://localhost
Connection: keep-alive
Referer: http://localhost/dvwa/vulnerabilities/xss_s/
Cookie: PHPSESSID=j5qms9qjut21k48jui6n9rbpp1; security=impossible
Upgrade-Insecure-Requests: 1
--6aee0714-C--
txtName=test&mtxMessage=%3Cscript%3E&btnSign=Sign+Guestbook&user_token=36b522e1d727fddc47d171f5cc0332be
--6aee0714-F--
HTTP/1.1 403 Forbidden
Content-Length: 274
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=iso-8859-1

--6aee0714-E--
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access this resource.</p>
<hr>
<address>Apache/2.4.57 (Debian) Server at localhost Port 80</address>
</body></html>

--6aee0714-H--
Message: Warning. detected XSS using libinjection. [file "/usr/share/modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf"] [line "56"] [id "941100"] [msg "XSS Attack Detected via libinjection"] [data "Matched Data: XSS data found within ARGS:mtxMessage: <script>"] [severity "CRITICAL"] [ver "OWASP_CRS/3.3.5"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-xss"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/242"]

 

1. A 필드 : 로그의 시작을 알림

2. B필드 : Request_header

3. I 필드 : 생략해도 무관

4. F 필드 : Respone header 정보

5. E 필드 : Respone Body (서버 반환 부분)

6. H 필드 : error.log에 남는 것과 같이 기록되는데 시간 정보는 A필드로 분리

ㄴ msg, id값, 어떤 룰에 의해 탐지됐고 어느 부분이 탐지됐는지 확인하기

7. J 필드 : 파일 사이즈, 업로드되는 데이터 파일 이름, 컨텐츠 타입 기록

8. Z 필드 : 로그의 끝을 알림 (동일한 hash 로그값 기준)

 

특정 공격에 대한 통계를 내고 싶다면!

 


 

[ 공격자(공격그룹) 공격프로세스 ]

1. 웹 (가장 많이 사용)

  • 접근성이 용이
  • 웹에서 식별되는 취약점은 거의 없음 but 사례) 2023년 1월 발생된 샤오치잉 공격 제외! >> 해킹당한 대상 기관에는 정보보호 조직이 없기 때문에 (= 사실상 방치된 웹 서버이기 때문)
  • 웹 취약점 중 권한을 넘겨주는 취약점은 SQLi, Command Injection, FileUpload, LFI/RFI 4개의 취약점이 대표적!

2. 시스템 취약점 : 설정상 오류 또는 패치누락 등으로 발생하는 취약점(Bof)

ex) MS17-010과 같이 SMB 프로토콜의 취약점을 통해 원격에서 타겟 시스템으로 바로 접속 가능

 

3. 알려진 CVE : Log4j, Apache Structure 등 (버전 정보 필요)

 

4. 이메일 : 첨부파일을 통한 악성코드 배포 (리버스쉘)

 

5. 물리(USB) : 악성코드 배포, 시스템 설정 변경 등

 

정보수집 -> 악성코드 제작 -> 배포 -> 시스템 권한 획득 -> 악용

ㄴ 정보수집 : 플랫폼(소셜미디어, 인터넷 등), 스캐닝 공격을 통해 실행중인 서비스 식별

ㄴ 악성코드 제작 : 타겟에 특화된 악성코드 제작 (소셜미디어를 통해 특화된 악성코드 제작이 가능, 관심사 반영)

ex) 교수의 관심사 : 논문, 학회 참석, 연구

A 교수가 xx일에 xxx학회를 다녀온 게시글 확인 > xxx학회에서 배포되는 문서로 약성코드를 삽입하여 제작

ㄴ 배포 : 이메일로 배포(가장 많이 활용됨)

 

ㄴ 악용 : 악용 단계에서 공격자는 동일 네트워크의 다른 시스템 접속을 시도함

 


 

[ HTTP Method 이해 ]

1. GET : 특정 페이지를 서버로 요청

2. POST : 데이터를 서버와 비교 또는 서버에 반영

3. PUT : 서버로 데이터를 업로드 >> FileUpload 취약점이랑 같이 기억하기!

4. DELETE : 서버에 저장된 데이터(리소스)를 삭제

5. OPTIONS : 어떤 유형의 Method가 Allow(허용) 되어 있는지 확인

 


 

[ SecRule ]

LFI 파일 SecRule 살펴보기

1. SecRule : 접두어 (무조건 사용)

2. URI_RAW : URI 값을 Raw값으로 확인 (바이너리 또는 Hex 값으로 체크)

ㄴ 왜 raw? 인코딩 때문

3. ARGS : 변수 체크 (파라미터)

4. REQUEST_HEADER : 사용자 요청 헤더 필드 검사

5. !REQUEST_HEADERS:Referer : Referer 필드 체크 x

ㄴ ' ! ' : not을 의미하므로, 해당 필드는 체크하지 않겠다

6. XML:/* : XML 필드 체크

7. "@rx (?i)(?:\x5c|(?:%(?:c(?:0%(?:[2aq]f|5c|9v)|1%(?:[19p]c|8s|af))|2(?:5(?:c(?:0%25af|1%259c)|2f|5c)|%46|f)|(?:(?:f(?:8%8)?0%8|e)0%80%a|bg%q)f|%3(?:2(?:%(?:%6|4)6|F)|5%%63)|u(?:221[56]|002f|EFC8|F025)|1u|5c)|0x(?:2f|5c)|\/))(?:%(?:(?:f(?:(?:c%80|8)%8)?0%8|e)0%80%ae|2(?:(?:5(?:c0%25a|2))?e|%45)|u(?:(?:002|ff0)e|2024)|%32(?:%(?:%6|4)5|E)|c0(?:%[256aef]e|\.))|\.(?:%0[01]|\?)?|\?\.?|0x2e){2}(?:\x5c|(?:%(?:c(?:0%(?:[2aq]f|5c|9v)|1%(?:[19p]c|8s|af))|2(?:5(?:c(?:0%25af|1%259c)|2f|5c)|%46|f)|(?:(?:f(?:8%8)?0%8|e)0%80%a|bg%q)f|%3(?:2(?:%(?:%6|4)6|F)|5%%63)|u(?:221[56]|002f|EFC8|F025)|1u|5c)|0x(?:2f|5c)|\/))" : 탐지하고자 하는 문자열 (텍스트, 정규표현식 모두 사용 가능) >> 이 예제는 정규 표현식을 썼으며 '룰셋'

ㄴ @rx : 해당 문자열로 시작을 의미

ㄴ () : 각각의 or 조건

ㄴ ? : 특정 문자열이 상관 없다는 것을 의미

ㄴ ex) .%5c/.%5c/.%5c/.%5c : 룰셋은 보통 이렇게 or 조건으로 특정 룰 작성할 때 나올 수 있는 경우의 수 판단해서 static하게 넣거나 정규표현식을 통해 해당 문자열이 들어갈 것 같다는 추측으로도 룰을 작성

 

* modsecurity에는 이미 작성된 룰이 공유되고 있어서 내가 만들 필요는 x

 

* LFI 취약점 있는지 확인할 때 대부분 '../../../../'나 'file:///'

 

'액션 필드' (룰에 의해 탐지 되었을 때 취할 행동)

- id : 탐지되었을 때 룰에 대한 고유한 식별 값

- phase : 1번부터 5번까지 존재

ㄴ 1 : REQUEST_Header 체크

ㄴ 2 : 1 + REQUEST_Body 체크

ㄴ 3 : RESPONE_HEADER 체크 (= 서버로부터 응답되는 데이터 체크)

ㄴ 4 : RESPONE _Body 체크

ㄴ 5 : all (전체) 체크

>> 지정해도 되고 안 해도 되는 선택 사항, 생략 가능(두 번째 필드에서 지정 가능)

- block : 차단 옵션(실행 안 되게끔 완전히 방어), deny는 거부 옵션(실행은 되지만 사용자에게 실행된 결과 반환 x)

- capture : 패킷이나 로그를 기록, 생략 가능

- t : none값은 default값이며 t 옵션 지시자에는 대소문자 구분 옵션, 인코딩, 디코딩 탐지 옵션 존재, 생략 가능

룰을 작성할 때 대소문자, 인코딩 데이터 등 고려하여 룰 작성

ㄴ t 옵션 지시자는 modsecurity.conf 파일 참고하기

- msg : 탐지되었을 때 로그에 남길 메시지

- logdata : 날짜, 생략 가능

- tag : 식별 필드, 그룹핑, 생략 가능