[갤럭시 1-Day Case] SVE-2021-20716 / CVE-2021-25397

Posted by MrBIN on January 6, 2023

SVE-2021-20716 / CVE-2021-25397

1) APP info

* APP: TelephonyUI (com.samsung.android.app.telephonyui)
* REWARD: $4850
* DESCRIPTION: writing arbitrary files as UID 1001
* Occur: TelephonyUI > PhotoringReceiver

2) TelephonyUI (com.samsung.android.app.telephonyui)

  • TelephonyUI는 전화가 걸려오고 device 벨이 울릴 때 Android Phone 앱에 나타나는 사용자 인터페이스에 지정된 패키지(수신 전화 수락, 수신 전화 거부, 발신자 표시 등)

3) 취약점 설명

< AndroidManifest.xml >

img1 img2

  • TelephonyUI는 android.uid.phone 권한을 가지고 있음. > 페이로드에서 mmssms.db에 접근할 수 있음.
  • PhotoringReceiver는 exported=true로 설정되어있어 외부에서 접근이 가능한 브로드캐스트 리시버.
< PhotoringReceiver >

img3

  • 분기문으로 action 체크 정도만 함.
  • photoring_uri는 내 서버의 데이터 파일 https://{서버 주소}}/test.mp4
  • down_file은 overwrite 할 데이터를 인텐트로 설정해 줌. (요기선 telephony 프로바이더의 mmssms.db)
  • PhotoringReceiver는 onReceive 함수에서 인텐트의 photoring_uri와 down_file 파라미터를 받아오고 m3550a함수에 이를 전달.
< PhotorinMgr - m3550a >

img4

  • callMessageNetwork 객체는 PhotoringReceiver에서 null인지 체크하고 null이면 새로 할당.
  • m3550a 함수는 photoring_uri와 down_file 파라미터를 받아와 str, str2 파라미터에 저장.
  • m3685a 함수에 str(photoring_uri), str2(down_file) 전달.
< CallMessageNetwork - m3685a >

img5

  • m3671c 함수 같은 경우 현재 스레드가 돌고 있는지 안 돌고 있는지 체크하는 함수.
  • m3685a 또한 photoring_uri와 down_file 파라미터에 해당하는 str, str2를 f2952c라는 스레드 객체를 생성하는 C1949a 함수에 넘겨줌.
  • f2952c 스레드 객체를 start 메소드를 통해 run 메소드를 실행 시킴.
< CallMessageNetwork - C1949a >

img6

< HTTPRequestHelper >

img7

< CallMessageNetwork - m3668d >

img8

  • C1949a는 단순 photoring_uri와 download_file 파라미터에 해당하는 값을 각각 f2957a와 f2958b에 넣어 줌.
  • 그리고 앞서 봤던 start 메소드 호출로 인해 run 메소드가 호출됨. run 메소드는 StringBuilder 객체를 선언하고 처음으로 f2957a(photoring_uri) 값과 GET 변수 쿼리의 시작을 의미하는 ?를 append 함.
  • m3668d 같은 경우는 시스템 서비스 중 telephonymanager를 호출 해 getLine1Number라는 함수를 통해 현재 디바이스의 핸드폰 번호를 가져옴.
  • m3669c 함수를 통해 CTN=전화번호 값을 aes 암호화를 진행하고 stringbuilder 객체에 append 함.

    https://{공격자 서버 주소}}test.mp4?암호화{CTN=01012345678}

마지막으로 HTTPRequestHelper 클래스의 객체 생성
- CallMessageNetwork 객체에 대한 핸들러
- "DOWNLOAD_CONTENT" 플래그
- download_file에 해당하는 str2
- 현재 클래스 객체 this 스레드 파라미터
  • m3612b 함수의 파라미터로 stringBuilder 객체와 linkedhashmap 객체 넘김.
< HTTPRequestHelper - m3612b >

img9

< HTTPRequestHelper - m3614a >

img10

  • m3612b의 파라미터 str은 예시로 https://{공격자 서버 주소}/test.mp4?암호화{CTN=01012345678} 이런식으로 저장됨.
  • httpClient m3624a에는 http 프로토콜에 대한 기본 설정을 한 후 http 클라이언트를 생성 그리고 connection timeout과 소켓 timeout에 대한 파라미터를 설정함.
  • httpGet은 get 메서드와 URL을 설정. URL은 f2994a의 https://{공격자 서버 주소}}/test.mp4?암호화{CTN=01012345678}를 의미함.
  • execute 변수에 request한 리스폰스 값을 저장.
  • f2999f 변수는 thread 변수인데 HTTPRequestHelper 처음 호출 할 때 스레드 넘겨줘서 null 값은 아님.
  • 리스폰스에 해당되는 객체인 execute를 m3611b 함수에 전달.
< HTTPRequestHelper - m3611b >

img11

  • m3611b는 리스폰스에 대한 값을 가진 execute 객체를 httpResponse란 이름으로 전달 받음.
  • httpResponse 값이 null이 아니고 RequestType이 DOWNLOAD_CONTETN이면 hTTPResponseParser 객체를 생성하는데 파라미터로 f2997d를 넘기게됨. f2997d는 처음 인자로 전달한 download_file 파라미터를 의미함.
< HTTPResponseParser - m3605a >

img12

  • m3601e 호출
< HTTPResponseParser - m3601e >

img13

< HTTPResponseParser - m3600f >

img14

  • f3005a는 httpResponse에 대한 정보가 저장되어 있고 getEntity 메소드를 통해 entity 정보인 리스폰스 헤더와 바디 정보를 받아옴.
  • getContent메소드를 통해 리스폰스 바디 데이터를 저장.
  • f3013i는 download_file 파라미터를 가지고 있음.
  • 리스폰스 엔티티의 get 방식의 파라미터를 f3009e에 저장하고 이 변수가 video/나 image/ 문자열로 시작하는지 검사함.
  • 그리고 m3607a 메소드에 리스폰스 바디 데이터와 download_file 파라미터 전달함.
< HTTPResponseParser - m3607a>

img15

  • 결과적으로 inpustream은 https://redacted.s3.amazonaws.com/test.mp4 파일의 스트림 데이터이고 str 경로 파일에 overwrite함.

4) Payload

img16



Ref.

https://blog.oversecured.com/