짱짱해커가 되고 싶은 나

[안드로이드 취약점 진단] 3-1. 브로드캐스트 리시버 결함 본문

모바일

[안드로이드 취약점 진단] 3-1. 브로드캐스트 리시버 결함

동로시 2022. 6. 11. 00:35

브로드캐스트 리시버

안드로이드는 이벤트 발생 시 브로드캐스트 신호 발행, 브로드캐스트 리시버는 이 신호를 받아서 처리하는 역할

(리시버를 설정해야 사용 가능)

AndroidMainfest.xml <receiver></receiver>에 선언

선언한 액션이 호출되면 리시버가 해당 액션을 인지해 작업 수행 (브로드캐스트 리시버를 상속 받은 메서드에서 처리)

-> 브로드캐스트가 정상이면 시스템 이벤트와 다른 애플리케이션에서 발생하는 경우가 있다 ?

-> 비정상이면 악의적인 애플리케이션에서 발생하거나 공격자에 의해 임의로 생성할 수 있다.
   ex. 사용자가 받는 알림을 중간에서 가로채거나 특정 상황에서만 발생하는 작업을 우회해 수행하도록 조작

 

인시큐어뱅크 - Flawed Broadcast Receivers

AndroidMainfest.xml

먼저 AndriodMainfest.xml을 확인해보자.

receiver에 broadcast receiver가 2개 설정되어 있는 것을 확인할 수 있다.

-> 브로드캐스트 이름은 theBroadcast

-> 브로드캐스트 신호를 받으면 MyBoardCastReceiver에서 작업 수행

-> exported = true : 외부 애플리케이션으로부터 intent를 받을 수 있음

-> 얘는 exported=false다.

 

MyBroadCastReceiver

클래스 코드를 보면 브로드캐스트리시버를 사용하기 위해 extends BroadcstReceiver로 해당 객체를 상속 받고 있다.

BroadcastReceiver 객체는 onReceive()를 통해 발생된 브로드캐스트를 처리한다. 이 때 intent로 들어온 정보 중 phonenumber와 newpass에 해당하는 스트링을 해당 클래스에 저장한다.

phonenumber가 null이 아니라면 getSharedPreferences를 통해 data/data/패키지/shared_prefs/[.xml] 에서 mySharedPreferences 객체를 받아온다. 그리고 EncreyptedUsername을 받아와서 base64로 디코드한 평문 이름을 내부 스트링으로 저장한다. 비밀번호도 마찬가지로 superSecurePassword에서 가져온다. wow 명칭이 엄청나다.

간단하게 SharePreferences를 설명하면 xml 파일에 필요한 데이터를 저장해서 쉽게 읽고 쓰게 하는 것으로 앱이 종료되도 값을 저장해 유지할 수 있다. 즉, mySharePreferences.xml 파일이 shared_prefs에 생성된다고 생각하면 된다. 두 번째 인자는 mode로 1이면 MODE_WORLD_READABLE로 다른 앱에서 읽을 수 있는 것이다. (참고로 0은 private으로 다른 앱에서 접근 불가능하다.)

핸드폰번호, 기존 패스워드, 새로운 패스워드를 출력하고 sms에 비밀번호 변경 메시지를 보낸다. phonenumber가 null이라면 'phone humber is null'을 프린트하고 끝난다.

엥? 싶다. 일단 기존 비밀번호를 굳이 복호화해서 보여주고 비밀번호를 업데이트하는 과정은 없다!  🤔

 

=> 애플리케이션이 사용자 정의 브로드캐스트 리시버를 사용하거나 intent-filter에 특정 권한을 명시하지 않는다면 다른 애플리케이션에 의해 브로드캐스트 리시버가 오남용될 수 있다.

 

adb로 broacast 생성

theBroadcast 라는 브로드캐스트를 생성해보자.

명령어는 am broadcast -a "브로드캐스트명" -n "패키지명/서비스 경로명"

-> 아까 Mainfest에서 봤듯이 브로드캐스트명 = theBroadcast, 패키지명=com.android.insecurebankv2, 서비스 경로명=.MyBroadCastReceiver

로그캣으로 확인하면 다음과 같이 phone humber is null이 프린트 된걸 확인할 수 있다.

그러면 phone number랑 newpass 값을 넣어서 생성해보자.

--es 옵션을 주면 변수랑 값을 추가할 수 있다. (--es 변수명 값) 형식이다.

-> 여기서 문제점!

로그를 보면 기존 비밀번호인 Jack@123$이 평문으로 출력된다. 비밀번호가 바뀌는 것도 아니고~

 

그리고 로그아웃하고 저걸 날리면 어떻게 되지? 싶어서 해봤는데

띠용쓰 하게도 Jack 친구꺼를 보여준다. ㅖ 선생님? 저 로그인안했는데요..

데니시로 로그인한다음에 로그아웃한 상태로 다시 시도했더니 데니시로 뜬다.

아니 선생님, 로그아웃했는데 처리가 왜이래요..

우선 유저 정보를 shared_prefs에서 가져오니까 뭐가 들어있나 열어봅시다.

아하 한 번 로그인을 할 때마다 mySharedPreferences.xml 파일에 값이 새롭게 저장되고 이게 로그아웃할 때도 그대로 유지되서 문제인 것 같다.. 취약점 투성이..

-> 앗! 하지만 이 부분은 뒤에 로컬 암호화 취약점에서 집중적으로 다룬다고 하니까 여기서는 이만하도록 하겠다 ^^7

 

브로드캐스트 리시버 오남용 대응방안

자! 🧐

어쨌든 예시를 통해 adb에서 브로드캐스트를 생성해서 로그 정보로 비밀번호의 평문을 알아낼 수 있다는 것을 확인했다.

그렇다면 대응 방법은 ? ?

 

방법 1. android:exported=false

false일 때는 외부 애플리케이션에서 발생하는 인텐트에 영향을 받지 않게 되서 브로드캐스트 리시버도 임의의 브로드캐스트에 영향을 받지 않게 된다. (intent-filter에 값이 있을 경우 default는 true니까 주의하자!)

 

방법 2. 리시버에 permission 주기

ㅌ각 요소에 사용자가 임의의 권한을 부여해서 해당 권한을 같이 넣어서 요청할 때만 받을 수 있게 하는 것이다.

 

보안초보스터디 - Vul_BroadcastReceiver.apk

(추후 추가 예정)

Comments