Analysis
기기에서 Burp Proxy 설정 이후 HTTP, HTTPS 버튼을 누르면 다음과 같이 Burp Suite에서 두 버튼 활성화로 인한 패킷을 확인할 수 있지만 마지막 CERTIFICATE PINNING으로는 패킷이 잡히지 않는 것을 확인할 수 있다. (Burp Proxy 설정)
Code
http
final class TrafficActivity$onCreate$1 implements View.OnClickListener {
final /* synthetic */ TrafficActivity this$0;
TrafficActivity$onCreate$1(TrafficActivity trafficActivity) {
this.this$0 = trafficActivity;
}
public final void onClick(View it) {
TrafficActivity trafficActivity = this.this$0;
trafficActivity.run(trafficActivity.getHttpurl());
}
}
public final String getHttpurl() {
return this.httpurl; // "http://demo.testfire.net"
}
HTTP버튼을 누르면 run() 함수에 getHttpurl() 반환 값("http://demo.testfire.net")을 넘겨주게 된다. (HTTPS버튼의 경우도 넘겨지는 url만 다르지 나머지는 동일하다)
run
public final void run(String url) {
Intrinsics.checkParameterIsNotNull(url, "url");
try {
Request request = new Request.Builder().url(url).build();
Toast.makeText(this, "Request sent to " + url + " Please intercept using Proxy", 1).show();
this.client.newCall(request).enqueue(new TrafficActivity$run$1());
} catch (Exception e) {
e.printStackTrace();
}
}
run() 함수에서는 이전 함수에서 넘어온 url을 Request.Builder를 이용하여 GET 방식의 요청을 발생하게 된다.
doPinning
final class TrafficActivity$doPinning$1 extends Lambda implements Function1<AnkoAsyncContext<TrafficActivity>, Unit> {
public static final TrafficActivity$doPinning$1 INSTANCE = new TrafficActivity$doPinning$1();
TrafficActivity$doPinning$1() {
super(1);
}
public /* bridge */ /* synthetic */ Object invoke(Object obj) {
invoke((AnkoAsyncContext<TrafficActivity>) (AnkoAsyncContext) obj);
return Unit.INSTANCE;
}
public final void invoke(AnkoAsyncContext<TrafficActivity> $this$doAsync) {
Intrinsics.checkParameterIsNotNull($this$doAsync, "$receiver");
try {
OkHttpClient client = new OkHttpClient.Builder().certificatePinner(new CertificatePinner.Builder().add("owasp.org", "sha256/gdU/UHClHJBFbIdeKuyHm/Lq/aQvMLyuTtcvTEE/1JQ=").add("owasp.org", "sha256/YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg=").add("owasp.org", "sha256/Vjs8r4z+80wjNcr1YKepWQboSIRi63WsWXhIMN+eWys=").build()).build();
Request.Builder builder = new Request.Builder();
ResponseBody body = client.newCall(builder.url("https://" + "owasp.org").build()).execute().body();
Log.v("Response", body != null ? body.string() : null);
} catch (Exception e) {
e.printStackTrace();
}
}
}
CERTIFICATE PINNING버튼을 누를 경우 certificatePinner를 이용하여 인증서를 고정한 후 "https://owasp.org" 요청을 보내는 것을 확인할 수 있다.
Exploit
Frida
코드에 고정된 인증서를 우회하기 위해서는 인증서 고정을 위해 사용하는 CertificatePinner클래스의 검증 로직을 후킹 하면 쉽게 우회할 수 있다.
후킹은 다음과 같이 check 함수를 후킹하여 진행한다.
console.log("Script loaded successfully");
Java.perform(function x() {
console.log("java perform function");
var CertificatePinner = Java.use('okhttp3.CertificatePinner');
CertificatePinner.check.overload('java.lang.String','java.util.List').implementation = function (p0, p1) {
console.log('! Intercepted okhttp3: ' + p0);
return;
};
});
코드를 실행한 후 CERTIFICATE PINNING버튼을 누르면 다음과 같이 로그와 Burp Suite에서 패킷이 잡히는 것을 확인할 수 있다.
Reference
'Android > Androgoat' 카테고리의 다른 글
Binary Patching (0) | 2021.09.20 |
---|---|
Emulator Detection (0) | 2021.09.20 |
Root Detection (0) | 2021.09.20 |