본문 바로가기

모바일 해킹/안드로이드

취약한 콘텐츠 프로바이더 접근

안녕하세요 이번에는 취약한 콘텐츠 프로바이더 접근에 대해 실습을 해보겠습니다.

 

adb와 drozer을 이용할 테니 nox 키시고 adb 연결하시고 drozer서버 키고 drozer 연결하시고

insecurebank 서버 키시면 됩니다.

 

 

-콘텐츠 프로바이더(Content Provider)?

 

콘텐츠 프로바이더는 다른 앱에서 DB나 파일에 접근 가능하게 해주는 인터페이스 제공합니다.

콘텐츠 프로바이더에 접근하기 위해 URI와 ContentResolver 필요합니다.

앱은 ContentResolver를 이용해 콘텐츠 프로바이더에 접근 가능하며 URI를 이용합니다.

만약 콘텐츠 프로바이더가 노출된 경우 외부에서 접근해 데이터를 조회해 번경이 가능합니다.

 

한 마디로 연동되는 다른 앱의 DB나 파일와 연결시켜주는 거라고 보시면 됩니다.

이걸 이용해 저희는 외부에서 데이터를 조회하고 변경까지 하는 겁니다.

 

 

-콘텐츠 프로바이더 확인

 

앱에서 콘텐츠 프로바이더는 manifest 파일에서 <provider> 요소에 정의합니다.

콘텐츠 프로바이더의 주소인 URI는 "content://authority/path"와 같은 형식으로 구성되어 있습니다.

 

그래서 소스 코드에서 content:// 으로 시작하는 것을 찾아서 보면 어느 것이 정의 되어 있는지 볼 수 있는 겁니다.

 

 

Authority는 콘텐츠 프로바이더의 주소(path) 데이터 위치에 대한 정보를 의미합니다.

다음 예시는 insecurebankv2에서 가져왔습니다.

<provider 
android:name="com.android.insecurebankv2.TrackUserContentProvider"
android:exported="true"
android:authorities="com.android.insecurebankv2.TrackUserContentProvider"
/>

보통 콘텐츠 프로바이더는 이렇게 정의 되어 있습니다.

 

name은 ContentProvider를 구현하는 클래스입니다.

 

권한(authorities)은 시스템 내에서 제공자 전체를 식별하는 상징적 이름입니다.

이게 어느 데이터를 호출하는지 확인할 수 있는 주소입니다. 그래서 이 경로로 가서 확인할 필요가 있습니다.

 

시작 및 제어 특성(exported) : 다른 앱이 제공자를 사용해줄 수 있게 해주는 플래그로 true로 설정되면 외부로 노출됩니다.

 

 

 

 

전 포스팅과 마찬가지로 exported가 true이면 저희가 외부로 접근을 해서 데이터 조작하고 보는 겁니다.

.

.

.

.

.

실습 해보죠.

 

1. jadx와 adb 이용해서 콘텐츠 프로바이더 확인하기

일단 JADX을 열고 insecurebankv2.apk을 디컴파일을 합니다.

JADX에 apk 드래그해서 올리기만 하면 됩니다.

 

뭔가 많죠

 

그다음에 jadx의 자랑인 검색 기능 이용해서 content:// 검색하겠습니다.

 

여기서 가운데 핑크색 왼쪽에 있는 걸 누르시면 돕니다.

코드까지 체크하고 찾겠습니다.

있네요

 

맨 첫 줄을 더블 클릭하면 그 코드가 있는 위치로 가집니다.

 

TrackUserContentProvider 클래스에 있네요

 

윗 줄 코드들을 보면 mydb을 이용하고 있고 CREATE.. 문은 아마 이 db와 연관 있는 거겠죠.

그럼 URI을 찾았으니 한 번 adb 이용해 이 URI를 호출해보겠습니다.

 

명령어는 

 

adb shell content query --uri [보려는 URI] 

 

터미널 여셔서

adb shell content query --uri content://com.android.insecurebankv2.TrackUserContentProvider/trackerusers

 

입력합니다.

 

 

그럼 이 URI 안에 있는 DB 내용을 볼 수 있게 됩니다.

한 번 mydb 파일을 가져와서 봐보겠습니다.

 

adb shell으로 연결한 터미널에 insecurebankv2의 데이터베이스가 있는 파일로 가겠습니다.

 

cd /data/data/com.android.insecurebankv2/databases

 

이 mydb 추출하는 건 전에 포스팅에 알려줬습니다.

이 mydb를 가져오고 mydb 도구 이용해 보겠습니다.

 

pull

 

도구로 mybd를 보면

 

이렇게

 

방금 URI 통해 본 DB 내용과 같다는 걸 알 수 있습니다.

 

 

 

 

 

 

2. drozer 이용해서 콘텐츠 프로바이더 확인하기

 

이번엔 drozer을 이용해 보겠습니다.

drozer console connect 통해 연결합니다.

 

이제보니 저 그림 뭔가 징그럽네요

 

우선 exported true 관련 취약점이 있는지 확인해봅니다.

 

run app.package.attacksurface [패키지 명]

 

run app.package.attacksurface com.android.insecurebankv2

 

아하..

 

액티비티에 5개의 true랑 broadcast에도 true이 있다는 데 다음 포스팅에 다룰게요

그리고 content에 1개 있다고 알 수 있습니다.

 

그럼 URI를 찾아보겠습니다.

 

list.provider 치면 provider 관련 명령어들이 나옵니다.

 

꽤나 많죠

 

여기서 info을 사용하면 provider의 정보를 알려줍니다.

 

명령어는

 

run app.provider.info -a [패키지 명]

 

run app.provider.info -a com.android.insecurebankv2

 

아하

 

Authority는  com.android.insecurebankv2.TrackUserContentProvider 이고

Content Provider은 com.android.insecurebankv2.TrackUserContentProvider 인 것을 바로 알 수 있습니다.

 

참고로 Permission이 null인건 권한을 따로 설정하지 않은 걸 뜻합니다. 저것도 문제입니다.

 

어쨌든 이번엔 URI을 찾아야 되겠죠?

 

명령어는

 

run scanner.provider.finduris -a [패키지 명]

 

run scanner.provider.finduris -a com.android.insecurebankv2

 

이렇게

 

알아서 잘 찾아줍니다.

 

Unable은 불가능한 거니 넘어가고 able만 보면 되겠죠.

근데 2개가 나왔는데 차이점은 없죠? / 하나 차이 나는데 별 문제없을 겁니다.

 

이렇게 URI를 찾을 수 있습니다.

 

이제 URI 안에 있는 내용을 보겠습니다.

 

명령어는 

 

run app.provider.query [URI]

 

run app.provider.query content://com.android.insecurebankv2.TrackUserContentProvider/trackerusers/

 

 

이렇게 저희가 앞서 확인한 DB처럼 내용을 확인할 수 있었습니다.

 

 

 

그럼 SQL injection 공격도 해보겠습니다. 웹에서 하신 거랑 똑같습니다.

 

맨 뒤에 --projection 입력한 후 뒤에 쿼리문 작성하시면 됩니다.

 

run app.provider.query [URI] --projection "[공격할 쿼리문]"

 

run app.provider.query content://com.android.insecurebankv2.TrackUserContentProvider/trackerusers/

--projection "'" 

 

한 번 싱글 쿼터만 보내 보겠습니다.

 

에러문 통해서 문법을 알 수 있네요

 

에러문에 SQL문이 노출되는 걸 보고 이 문법에 맞춰서 공격을 행하면 되겠죠!

 

run app.provider.query content://com.android.insecurebankv2.TrackUserContentProvider/trackerusers/

--projection "* from SQLITE_MASTER where type='table';--" 

 

이러면 모든 테이블 정보가 나오게 됩니다.

 

이렇게

 

만약 names에 있는 정보만 보고 싶으면?

 

* from names;-- 입력하시면 되겠죠.

 

이렇게

 

다른 테이블의 정보를 볼 수 있습니다.

 

근데 insert와 delete는 되도록이면 안 사용하시는 게 좋아요. 실제 서비스에 영향이 미치는 건 피하는 게 좋습니다.

 

명령어 정리하겠습니다.

 

run app.package.attacksurface [패키지 명] : exported true인 취약점 찾기

run app.provider.info -a [패키지 명] : 패키지에 있는 provider 정보 찾기

run scanner.provider.finduris -a [패키지 명] : 패키지에 있는 provider의 URI문 찾기

run app.provider.query [URI] : 해당 URI에 있는 DB 데이터 확인하기

run app.provider.query [URI] --projection "[공격할 쿼리문]" : 해당 URL 이용해 SQL injection 공격하기

 

.

.

.

.

.

.

.

.

-대응방안

 

간단합니다!

 

exported를 false로 바꾸기만 하면 됩니다.

정확힌 Androidmanifest.xml에 선언된 android:exported 속성을 false로 설정하면 됩니다.

 

그럼 Permission Denial이 출력되면서 공격이 안됩니다.