안녕하세요! 이번 포스팅에선 Input Validation Issues 취약점에 대하여 DIVA 문제를 실습해보며 익히는 내용을 포스팅하겠습니다! 우선 Input Validation Issues 란 무엇일까요??
Input Validation Issues 란?
> 사용자의 입력값을 받는 과정에서 특별한 필터링이나 제한을 두지않아 예기치 못한 동작을 일으키는 경우를 말합니다. 예를들어 SQL Injection 인 경우 입력값에 대한 필터링이 충분히 되어있질 않아서 DB에 접근할 수 있게되는데 이런 경우도 Input Validation Issues 이라고 할 수 있습니다!
[실습]
1. Input Validation Issues - Part 1
1. 우선 INPUT VALIDATION ISSUES -PART 1 문제를 클릭하여 들어갑니다.
2. user name을 검색할 수 있는 페이지인것 같습니다. 문제에선 "user name 을 모르는 상태에서 모든 user data 에 접근해라. 3개의 고정된 user data 가 있는데 검색창을 이용해서 3명 모두의 정보를 얻어내라" 인것같습니다. 일단 당장은 뭘 검색해야 할 지 모르겠으니, 이 페이지가 어떻게 동작하는지 알아보기 위해 Jadx로 디컴파일링 하여 코드를 확인해봅시다.
3. 디컴파일링 된 소스코드중 SQLInejectionActivity 라는 액티비티에 들어가보면 SQLite를 이용하여 유저 데이터를 만드는것을 보실수있습니다. 또한 srchtxt 라는 변수에 저희가 입력한 값이 들어가게 되고 , 이후 별 다른 필터링없이 저희가 입력한 값을 SQL query 문에 포함하여 Select 문을 실행시키는것을 보실 수 있습니다. (만약 사진이 깨져서 잘 안보인다 하시면 사진을 클릭하시면 깨끗한 이미지로 확인가능합니다!)
4. 그러면 내용을 토대로 SQL Injection 구문을 삽입하여 Search 버튼을 눌러보겠습니다.
5. 앱 내부 저장소 DB에 저장되어 있던 USER 정보가 전부 뜨는것을 확인하실 수 있습니다!!
[대응방안]
1. Prepared Statement 사용
> Prepared Statement를 사용하면 쿼리문을 미리 컴파일 해놓고 사용자의 입력값은 나중에 따로 문자열로 처리하여 쿼리를 실행하기 때문에 ' " or and 등 사용자의 입력값이 SQL 쿼리문에 영향을 끼칠 수 없게 됩니다.
2. 블랙리스트 필터링 방식
> Prepared Statement 를 쓴다하여도 order by 절이나 컬럼명,테이블명을 적는 부분에는 여전히 사용자의 입력값이 쿼리문에 영향을 끼칠수 있기때문에 다음과 같은 단어들은 필터링 하시는것이 좋습니다.
특수문자 | 특정구문 |
" , ' , % , -- , # | select , update , delete , union , information_schema |
2. Input Validation Issues - Part 2
1. 두번째 문제는 Web View 를 이용하여 민감한 정보에 접근하라는게 목표인것 같네요!
2. 일단 동작체크를 위해 입력값에 naver에 주소를 적자 네이버 페이지가 nox 에 뜨는것을 확인하였습니다. 일단 어떤 동작을 하는진 알았으니 좀더 자세히 확인해보기 위해 디컴파일링 하여 소스코드를 확인해보겠습니다!
입력값 : www.naver.com | 네이버 페이지 |
3. 소스코드를 보니 loadUrl 을 통해 저희가 입력한 Url을 web view로 열어주고 있습니다만.. 이상하게도 web view 에 대한 권한설정이 찾아도 보이질 않습니다?... 이러면 web view를 통해 앱 내부저장소에 있는 파일들을 확인할 수 있습니다. 더군다나 지금 이 앱은 외부파일에 접근권한을 허용하고 있는상태라 앱 외부의 파일까지 접근할 수 있는 위험성이 있습니다!!...
취약한 loadUrl 코드 부분 |
AndroidManifest.xml 에서 선언된 외부파일에 접근권한 허용 부분 |
4. 그리하여 file:///data/data/jakhar.aseem.diva/shared_prefs/jakhar.aseem.diva_preferences.xml 라는 url 을 입력하여 앱 내부의 평문저장된 계정정보를 흭득한 것을 확인하실 수 있습니다.
※ 참고로 files///: 라고 하는 형식은 데스크톱(크롬) 에서 files///:C\ 라고 하게되면 로컬컴퓨터의 파일이 뜰것이고, Android 에서 하게되면 앱의 로컬파일들이 뜨게 됩니다. 여기서 files///: 랑 files//: 의 차이가 존재합니다.
files//: >> 상대경로로써 현재 자신이 위치한 폴더가 기준점이됨.
files///: >> 절대경로로써 기준이 잡힌게 아닌 경로 전체를 적어줘야함
그래서 위에 web view에 url 을 적을때 현재 위치한 디렉토리가 어디인지 기준을 모르기 때문에 절대경로로 넣어주었습니다!
[대응방안]
액티비티의 파일권한 설정을 해주면 됩니다. 현재 액티비티에서 WEB VIEW를 통한 파일접근 권한설정을 해주게 되면 url 을 통해서 내부 저장파일에 접근할 수 없게 됩니다! 또한 입력값 검증을통해 file:// 같이 디렉토리에 접근할 수 있는 문구들을 블랙리스트 필터링 해주어야 합니다. 그리고 애초에 Web view로 연결되는 url 을 입력하게 해선 안됩니다!..
아래는 접근 권한 설정을 해주어 다시 작성한 코드입니다.
[해당 내용을 반영하여 다시 작성한 코드]
package jakhar.aseem.diva;
/* import 에 대한 내용*/
public class InputValidation2URISchemeActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_input_validation2_urischeme);
WebView wview = (WebView) findViewById(R.id.ivi2wview);
WebSettings wset = wview.getSettings();
// JavaScript 활성화
wset.setJavaScriptEnabled(true);
// 보안을 강화하기 위해 파일 접근 및 콘텐츠 접근 비활성화
wset.setAllowFileAccess(false);
wset.setAllowContentAccess(false);
}
public void get(View view) {
EditText uriText = (EditText) findViewById(R.id.ivi2uri);
WebView wview = (WebView) findViewById(R.id.ivi2wview);
String url = uriText.getText().toString();
// file://로 시작하는 URL을 제외하고 다른 URL만 로드
if (!url.startsWith("file://")) {
wview.loadUrl(url);
}
}
}
3. Input Validation Issues - Part 3
1. 문제를 읽어보면 앱을 충돌나게 하는것이 목표인 문제인것 같습니다..아무 번호나 입력하니깐 역시나 접근 제한이 되었다는 문구가 뜹니다. 그러면 어떻게 이루어져 있는지 소스코드를 한번 보죠!
Input Validation Issues 페이지 | 접근 제한되는 모습 |
2. InputValidation3Activity 에 들어와 보면 이런 소스코드가 적혀있습니다. DivaJni 에 정의되어 있는 initiateLaunchSequence 라는 함수를 통해 입력값과 코드가 일치하면 미사일 버튼이 동작되는 방식인 것 같습니다. 그러면 DivaJni 가 어떻게 정의되어 있는지 한번 확인해보겠습니다.
3. DivaJni 클래스파일에 왔지만 함수가 어떻게 정의되어 있는지는 divajni 라는 라이브러리에 정의되어있는것 같습니다.. 라이브러리 파일은 바이너리 파일로써 Jadx 로는 디컴파일이 불가능하니 리버싱 툴인 Ghidra 를 이용하여 어셈블리어로 변환시켜주겠습니다. 참고로 divajni 라이브러리 파일은 리소스>lib에 가시면 있습니다!
InputValidation2의 액티비티 |
libdivajni.so 라는 라이브러리 파일 |
4. Ghira를 실행하여 저희가 확인해볼 라이브러리 파일을 리버싱 해주겠습니다.
5. 우선 왼쪽 바에 Symbol Tree 에다가 initiateLaunchSequence 라고 적어줘서 저희가 찾는 함수의 내용의 위치를 찾아줍니다. 이후 확인해 보니 CMPSB 라는 문자열 비교 연산자를 사용하고 있습니다. 아마 저 부분에서 저희가 입력한 값과 비밀코드를 비교하여 승인이 결정나는 부분인 것 같습니다. 그리고 옆에 주석을보니 비교되는 비밀코드는 " .dotdot " 이라는 문자열인것 같습니다.
6. 이로써 비밀코드는 찾았지만... 문제의도인 앱을 충돌나게 하라는 부분은 아직 못찾았습니다. 하지만 코드를 살펴보니 이 함수에서 strcpy 라는 함수를 사용하고 있습니다. 저희가 입력한 값은 pcVar1 이라는 변수에 들어가고 그 변수를 local_20[16] 이라는 사이즈 16 짜리 문자배열에 strcpy 를 사용하여 저장합니다.
여기서 중요한 점은 C언어를 공부해보신 분들은 아시겠지만 strcpy 는 문자가 입력되는 size를 지정할수가 없습니다. 즉! 저희가 16글자보다 더 많은 값을 입력해버리면 버퍼 오버플로우가 발생하여 앱의 문제가 생기도록 유도할 수가 있습니다!! 이런이유로 실제로 strcpy 보단 strcpy_s , strncpy 라는 버퍼오버플로우를 방지하는 함수를 사용합니다.
7. 그러면 문제로 돌아와서 16글자보다 훨씬 많은글자를 넣어주겠습니다. 저는 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 라는 글자를 넣어보았습니다. 그러자 문제 의도대로 버퍼오버플로우가 발생하여 Diva앱이 충돌난것을 확인하실 수 있습니다.
긴 문자열 입력 | Diva 앱이 충돌 |
8. 그러면 충돌도 일으켰으니 아까 저희가 찾아냈던 비밀코드를 집어넣어 이번에는 미사일 버튼을 발사해보겠습니다! .dotdot 이라는 문자열을 삽입하고 실행시키자 Launching T -10 ... 라는 문구가 뜨는것을 확인하실 수 있습니다!!
.dotdot 이라는 문구 삽입 | Launching T -10 .... 이라는 문구 확인 |
[대응방안]
> 버퍼오버플로우
: 입력값이 들어갈 메모리 외에 다른 메모리까지 침범하여 악용할 수 있으니 strcpy 라는 함수말고 strncpy 혹은 strcpy_s 를 사용하여 버퍼오버플로우 취약점을 막을 수 있다. 또한 입력을 할수있는 글자개수의 제한을 두어 막을수 있다.
> 하드코딩 이슈
: 이 문제에선 사실 비밀코드가 Ghidra 를 통해 노출되는 것 또한 문제였다. 이를 위해서 문자열을 비교할때도 저장되는 비밀코드에 Hash 암호화 과정을 추가하여 디컴파일링을 하더라도 어떤 문자인지 알아낼수 없게 만들어야 한다. 그리고 미사일 버튼인데 .dotdot 같은 문자열은 Hash 암호화를 한들 복호화 하기 상대적으로 쉬운 암호이다. 그러므로 좀더 복잡한 비밀번호를 사용하는 것이 권장된다.
긴 글 읽어주셔서 감사합니다!
'모바일 앱해킹(Android) > Android DIVA' 카테고리의 다른 글
[Android DIVA] 설치법 부터 취약점 진단까지 모아보기! (0) | 2024.12.16 |
---|---|
[Android DIVA] Access Control Issues 취약점 (0) | 2024.11.06 |
[Android DIVA] Insecure Data Storage 취약점 (0) | 2024.11.02 |
[Android DIVA] Hardcoding Issues 취약점 (0) | 2024.10.30 |
[Android DIVA] '취약한 로깅' 취약점 (0) | 2024.10.28 |