안녕하세요! 이번시간 포스팅에선 Access Control Issues 에 관하여 Android DIVA 를 실습해보며 알아가는 과정을 보여드리겠습니다! 우선 Access Control Issues 라는 것은 무엇일까요?
※ Access Control Issues 란?
> 접근 제어 이슈라고도 하는 이 취약점은 제 기준으로는 웹 해킹으로 따지면 불충분한 인가 취약점에 가깝습니다. 예를들어 관리자 페이지로 이동하는 특정 동작이 있는데 이를 앱 외부에서 호출하여 관리자가 아니더라도 우회하여 접근할 수 있는경우 , PIN 번호를 입력해야 동작하는 것을 PIN번호 없이 동작시킬 수 있는 경우가 있습니다.
[실습]
1. Access Control Issues - Part 1
1. 우선 Access Control Issues - Part 1 문제로 접근해줍니다.
2. 문제 의도를 보니 앱을 실행시키지 않은상태에서 외부에서 이 API 키가 보이는 페이지를 동작시켜보라는 말이네요. 즉! 민감한 동작을 앱 외부에서 실행시키는 문제점에 관한 것 같습니다.
버튼 클릭 | API 에 대한 정보 |
3.일단 코드흐름을 살펴보기 위해 Jadx 로 디컴파일링 하여 소스코드를 확인해줍니다. AccessControl1Activity 의 코드를 살펴보았는데 Intent에 VIEW_CREDS 라는 액션을 실행시키는 것을 확인하실 수 있습니다. 이게 무슨 액션일까요??
4. 이번엔 AndroidManifest.xml 에 이 액션과 관련된 액티비티가 있는지 살펴보았습니다. 그러자 VIEW_CREDS 라는 액션이 APICredsActivity에서 실행되는것을 확인하였습니다(APICredsActivity는 API 정보를 출력해주는 액티비티 입니다). 문제는 intent-filter 를 사용하였으나 "exported="false" 설정을 빠뜨려서 이 action을 앱 외부에서도 동작시킬 수 있다는 문제점이 있습니다. (Intent Filter 사용시 아무런 설정을 안해주게 되면 기본적으로 exported="true" 로 설정이 되어 앱 외부에서도 실행이 가능합니다)
5. 그러면 cmd 창을 통해 앱 외부에서 해당 액션을 실행시켜보겠습니다! 다음과 같이 명령어를 작성합니다.
> nox_adb shell am start -a jakhar.aseem.diva.action.VIEW_CREDS
am > Acitivty Manager 의 약자로 액티비티를 실행합니다.
-a "action 이름" > 지정된 action 을 동작합니다.
>> VIEW_CREDS 의 Intent-Filter가 APICredsActivity 코드 내에 존재했으므로 이 액션을 동작시 APICredsActivity 켜질것입니다.
6. 그러자 성공적으로 APICredsActivity가 열린것을 확인하실 수 있습니다.
[대응방안]
> Intent-Filter 의 권한설정 미흡으로 발생한 문제입니다. 따라서 xml 파일에 다음과 같이 수정하여야 합니다.
<activity
android:label="@string/apic_label"
android:name="jakhar.aseem.diva.APICredsActivity"
android:exported="false"> <!-- 여기를 추가!! -->
<intent-filter>
<action android:name="jakhar.aseem.diva.action.VIEW_CREDS"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
2. Access Control Issues - Part 2
1. 일단 Access Control Issues - Part2 문제에 들어왔습니다. 문제 의도는 API 정보를 얻으려면 우선 Tveeter 이란곳에 가입을 한 후 , PIN 번호를 받아야 API 정보를 볼 수 있다고 합니다. 즉! 이 PIN번호가 없는상태로 외부에서 API 정보에 접근해라! 입니다. 일단 RadioButton 이 있으니 각각의 경우에 어떻게 나오는지 확인해보겠습니다.
2. Register Now 을 선택후 클릭하면 PIN 번호를 입력해야지 API에 접근가능한 페이지가 뜨고 , Already Registered 를 선택후 클릭하면 API 정보가 뜹니다. 아마 Already Registered 경우는 이런식으로 API 정보가 저장되어있다! 를 보여주고싶어서 넣어놓은것 같습니다. 저희는 첫번째 경우에 PIN 번호없이 어떻게 우회해서 API 정보에 접근할까를 고민해보면 될것같습니다.
Register Now 선택시 |
||
Already Reg 선택시 |
3. AccessControl2Activity 의 소스코드를 살펴보니 chk_pin이라는 boolean타입 변수에 따라 저희가 가입했는지 안했는지 유무가 저장되는 것 같습니다. 또한 VIEW_CREDS2 라는 액션을 동작시킨후 chk_pin 에 저장된 참/거짓을 putExtra를 사용해서 다음 이동될 액티비티에 전달하고 있습니다. 일단 VIEW_CREDS2 라는 액션이 어떤 액션인지 살펴봅시다.
AccessControl2Activity 소스코드 |
3. AndroidManifest.xml 에 접근하여 소스코드를 살펴보니 VIEW_CREDS를 동작하면 APICreds2Activity 라는 액티비티가 동작하는것 같습니다. 그러면 APICreds2Activity 는 어떻게 이루어져 있나 확인해보겠습니다.
AndroidManifest.xml 소스코드중 일부 |
4. 핀번호 틀릴때 뜨는 문구가 있는것을 보니 여기가 저희가 우회해야할 PIN번호 입력 액티비티 인것 같습니다. 보시면 아까 putExtra를 통해 전달해준 chk_pin 이라는 boolean 변수값을 Intent에서 가져와서 bcheck 에 넣습니다. 그리고 bcheck 가 true면 PIN번호가 틀렸다고 뜨고 , false 면 API정보를 반환하는것 같습니다. 즉 저희는 저 bheck를 false로 만들어야 하는겁니다!
참고로 getBooleanExtra( "Key 값", "해당 Key 값이 없다면 Default값") >> intent로 전달된 boolean값 가져오기
APICreds2Activity 의 소스코드중 일부 |
5. 넘어온 Intent 에서 key값이 getString(R.string.chk_pin) 인 boolean 타입의 변수를 가져와서 bcheck에 넣어주는것 같습니다. 만약 넘어온 값이 없다면 디폴트값은 true 라고 되어있습니다. 그러면 getString(R.string.chk_pin) 가 뭐라고 쓰여있는 문자열인지만 알면 그 값을 adb shell am 기능으로 조작할 수 있습니다. 참고로 adb shell am 기능은 액티비티를 실행할때 전달하는 변수값을 추가해줄수 있습니다.
APICreds2Activity 소스코드 중 일부 |
6. Jadx 에서 텍스트 검색을 키신후 chk_pin 이라고 검색해주세요. 여기서 검색창 밑에 정의 검색 부분을 전부 체크해주셔야 낱낱이 볼수 있습니다. res/values/strings.xml 에 chk_pin 에 대한 정의가 되어있는것 같으니 클릭합니다.
7. R.string.chk_pin 이라는 값은 사실 "check_pin" 이라는 문자열이였습니다.
※ 왜 굳이 이렇게 따로 정의해서 쓰냐면 나중에 프로젝트가 커졋을때 chk_pin 값을 바꿔야 하는 경우가 있다고 생각해봅시다. 그러면 액티비티 하나하나에 다 들어가서 일일이 다 바꿔주는것보단 저렇게 정의된 부분으로 가서 바꿔주면 훨씬 편하기 때문에 저런식으로 사용하게 됩니다.
8. 즉! 저희가 조작해줄 getBooleanExtra 소스코드는 아래 사진에 설명되었듯이 저런식으로 표현 되어있는것이나 마찬가지 입니다. 이제 key 값이 check_pin 인것도 알았으니 명령어 창으로 가서 bcheck 값을 우회해보겠습니다.
9. 명령어 창에서 다음과 같은 명령어를 작성해주세요.
> nox_adb shell am start -n jakhar.aseem.diva/.APICreds2Activity -a jakhar.aseem.diva.action.VIEW_CREDS2 --ez check_pin false
-n > jakhar.aseem.diva 라는 패키지에 있는 APICreds2Activity 라는 액티비티를 실행한다
-a > jakhar.aseem.diva.action.VIEW_CREDS2 라는 액션을 동작시킨다
--ez > 열릴 액티비티에 key 값이 check_pin 이고 value가 false인 변수를 전달해준다.
10. 명령어를 입력하자 API 정보가 나오도록 if 문을 우회한것을 확인할 수 있습니다.
[대응방안]
1. 우선 Part 1 문제와 똑같이 AndroidManifest.xml 파일에서 Intent-filter 부분 권한설정이 미흡합니다. 외부에서 View_Creds2 라는 액션을 동작시킬수 있으므로 android:exported="false" 옵션을 추가하여야 합니다.
2. 인증과정을 공격자가 조작할 수 있는 변수에 의존한다는 것이 문제입니다. API 정보같이 민감한 정보는 서버에서 저장 및 제공해야 하며 , 인증절차 또한 입력한 PIN번호를 Hash 암호화를 하여 서버에 저장된 PIN번호와 대조하여 인증절차를 거치는 방식으로 변경하여야 안전합니다.
3. Access Control Issues - Part 3
1. Part3 문제에 들어와보면 " 단 한번만 PIN번호를 만들어서 저만의 마이페이지를 만들수 있고 , 그 PIN번호로만 만든 마이페이지에 들어올수 있습니다. PIN번호를 만든후 앱 외부에서 PIN번호를 모른다 가정하고 마이페이지에 접근해보세요" 라고합니다.
2. 핀번호를 4251로 지정하고 일단 PIN번호를 만들어주었습니다. 이후 GO TO PRIVATE NOTES 로 들어가서 4251을 눌러주었더니 개인정보가 뜨는 방식이였습니다. 일단 얼추 동작은 이해했으니 이제 이 PIN번호를 모른다 가정하고 저 개인정보를 얻기위해 Jadx로 코드를 분석해보겠습니다.
3. 보시면 addPin 이라는 함수인것으로 보아 여기가 비밀번호 생성 부분인것 같습니다. 저장된 비밀번호를 SharedPreferences 에 저장하는 것으로 보이고 , 이후 버튼을 눌러서 AccessControl3NotesActivity 로 이동하는것을 확인하실 수 있습니다. 그러면 일단 AccessControl3NotesActivity는 어떻게 동작하는지 확인해보겠습니다.
AccessControl3Activity 소스코드중 일부 |
4. AccessControl3NotesActivity 의 소스코드를 보니 Sharedpreference에 저장한 값과 저희가 입력한 값을 equals 함수를 이용하여 비교하는 방식으로 인증절차를 거치고 있습니다. 여기서 눈여겨 봐야할 부분은 getContentResolver 라는 기능을 사용하고 있다는 것입니다. NotesProvider 라는 곳에서 Content URI 를 통해 컬럼이 id , title , note 인 내용을 가져오는것 같으니 소스코드에서 NotesProvider라는 클래스를 확인해봅시다.
AccessControl3NotesActivity 소스코드중 일부 |
getContentResolver 가 뭔데?
ContentProvider 과 상호작용할 수 있게 만드는 도구라고 생각하시면 됩니다.
그러면 ContentProvider란 뭐지? 라는 의문이 들것입니다.
ContentProvider란 기본적인 CRUD 기능을 가진 클래스입니다.
ContentProvider에 DB를 연결하면 앱 내부나 외부에서도 이 DB에 CRUD 기능을 사용할 수 있습니다.
이때 DB에 접근을 URI 를 통해 접근이 가능합니다.
아래 사진과 같은 방식으로 content:// 형식의 URI 를 통해 외부에서 DB에 접근이 가능합니다.
5. NotesProvider 의 코드를 보면 ContentProivder의 URI 가 "content://jakhar.aseem.diva.provider.notesprovider/notes" 라고 지정되어있습니다. DB의 테이블 명이 notes 인것으로 보아 저 URI 를 통해서 외부에서 notes 라는 테이블의 CRUD 기능을 사용할 수 있을것으로 보입니다.
NotesProvider 코드중 일부 |
6. 또한 AndroidManifest.xml 파일을 보시면 android:exported="true" 라는 설정이 되어있습니다. 이를통해 외부 앱에서 NoteProvider 클래스 내용에 접근이 가능해집니다. 내부 컴포넌트 뿐만 아니라 외부 앱에서도 NoteProvider 클래스에서 URI 를 사용하여 DB에 접근이 가능해지는것이죠!
7. 그러면 CMD 명령어창을 통해 content 명령어를 사용하여 ContentProvider 기능을 사용할 수 있습니다. ADB Shell의 content 명령어는 사실상 ContentProvider의 인터페이스를 활용하여 데이터를 읽고 쓸 수 있게 해주는 도구입니다. 주요기능으로는 query(조회) , update(수정) , delete(삭제) , create(생성) 이 있습니다. 따라서 외부 cmd창에서 NoteProvider의 기능을 사용하여 DB를 조회해볼것입니다. 다음의 명령어를 따라해주세요!
아래 사진을 보시면 contentProvider 를 통해 개인정보가 담겨있던 DB에 접근하여 내용을 조회한것을 확인하실 수 있습니다!
> nox_adb shell content query --uri content://jakhar.aseem.diva.provider.notesprovider/notes
[대응방안]
1. "exported = false" 설정
> 만약에 앱 내부데이터 끼리만 사용하는거라면 false 로 설정을 해두어 사고를 방지하자
2. 커스텀 권한 설정
> xml 파일에 추가적으로 요구하는 권한을 설정하여 , 이 권한을 가진 어플만 접근할 수 있도록 합니다. 특히 protectionLevel 옵션을 dangerous 로 설정하게 되면 사용자에게 퍼미션을 승인할 건지 요구하는 과정이 추가되기 때문에 보다 더 안전하게 ContentProvider 를 사용할 수 있습니다.
※코드 예시
<!-- AndroidMenifest.xml 파일에 추가 -->
<permission
android:name="jakhar.aseem.diva.permission.MY_PERMISSION"
android:protectionLevel="dangerous" />
<provider
android:name="jakhar.aseem.diva.NotesProvider"
android:enabled="true"
android:exported="true"
android:authorities="jakhar.aseem.diva.provider.notesprovider"
android:permission="jakhar.aseem.diva.permission.MY_PERMISSION" />
긴 글 읽어주셔서 감사합니다!
'모바일 앱해킹(Android) > Android DIVA' 카테고리의 다른 글
[Android DIVA] 설치법 부터 취약점 진단까지 모아보기! (0) | 2024.12.16 |
---|---|
[Android DIVA] Input Validation Issues 취약점 (0) | 2024.11.03 |
[Android DIVA] Insecure Data Storage 취약점 (0) | 2024.11.02 |
[Android DIVA] Hardcoding Issues 취약점 (0) | 2024.10.30 |
[Android DIVA] '취약한 로깅' 취약점 (0) | 2024.10.28 |