OWASP 카테고리: MASVS-STORAGE: 저장소
개요
이 문서에서는 유사한 완화 조치를 공유하는 파일 포함과 관련된 여러 문제를 다룹니다. 이러한 문제는 WebView 내 파일 액세스로부터 발생하는 취약점에 중점을 두며 파일 액세스를 허용하거나 JavaScript를 사용 설정하는 위험한 WebSettings
부터 파일 선택 요청을 만드는 WebKit 메서드에 이르기까지 다양합니다. 이 문서는 file://
스키마 사용, 로컬 파일에 대한 무제한 액세스, 교차 사이트 스크립팅으로 인해 WebView 내에서 발생하는 문제의 해결에 관한 안내를 찾는 경우에 유용합니다.
구체적으로 이 문서에서는 다음 주제를 다룹니다.
WebSettings
는 WebView의 설정 상태를 관리하는 메서드가 포함된 클래스입니다. 이러한 메서드는 나중에 설명할 다양한 공격에 WebView를 노출할 수 있습니다. 이 문서에서는 파일 액세스 방법과 JavaScript 실행을 허용하는 설정에 관해 설명합니다.setAllowFileAccess
,setAllowFileAccessFromFileURLs
,setAllowUniversalAccessFromFileURLs
메서드를 사용하면 파일 스키마 URL(file://
)을 사용하여 로컬 파일에 대한 액세스 권한을 부여할 수 있습니다. 하지만 악성 스크립트가 이를 악용하여 애플리케이션이 액세스할 수 있는 임의의 로컬 파일(예: 자체/data/
폴더)에 액세스할 수 있습니다. 이러한 이유로 이러한 메서드는 안전하지 않은 것으로 표시되었으며 API 30에서 더 안전한 대안(예:WebViewAssetLoader
)을 선호하여 지원 중단되었습니다.setJavascriptEnabled
메서드를 사용하여 WebView 내에서 JavaScript 실행을 사용 설정할 수 있습니다. 이로 인해 애플리케이션이 파일 기반 XSS에 취약해집니다. 특히 실행 가능한 코드가 포함될 수 있는 로컬 파일이나 신뢰할 수 없는 웹 콘텐츠를 로드하도록 구성되거나, 외부 소스에서 생성하거나 변경할 수 있는 파일에 액세스하도록 구성되거나, WebView가 JavaScript를 실행하도록 허용된 경우 사용자 및 데이터가 위험에 처하게 됩니다.WebChromeClient.onShowFileChooser
은 웹 탐색 도구를 제공하는android.webkit
패키지에 속한 메서드입니다. 이 메서드는 사용자가 WebView 내에서 파일을 선택하도록 허용하는 데 사용할 수 있습니다. 하지만 WebView는 선택된 파일에 대한 제한을 적용하지 않으므로 이 기능이 악용될 수 있습니다.
영향
파일 포함의 영향은 WebView에 구성된 WebSettings에 따라 달라질 수 있습니다. 파일 권한이 너무 광범위하면 공격자가 로컬 파일에 액세스하여 민감한 정보, PII (개인 식별 정보) 또는 비공개 앱 데이터를 도용할 수 있습니다. JavaScript 실행을 사용 설정하면 공격자가 WebView 내에서 또는 사용자 기기에서 JavaScript를 실행할 수 있습니다. onShowFileChooser
메서드를 사용하여 선택한 파일은 메서드나 WebView에서 파일 소스가 신뢰할 수 있는지 확인할 방법이 없으므로 사용자 보안을 위협할 수 있습니다.
위험: file://을 통한 파일에 대한 위험한 액세스
setAllowFileAccess
, setAllowFileAccessFromFileURLs
, setAllowUniversalAccessFromFileURLs
를 사용 설정하면 file://
컨텍스트가 있는 악성 인텐트와 WebView 요청이 WebView 쿠키와 앱 비공개 데이터를 비롯한 임의의 로컬 파일에 액세스할 수 있습니다. 또한 onShowFileChooser
메서드를 사용하면 사용자가 신뢰할 수 없는 출처에서 파일을 선택하고 다운로드할 수 있습니다.
이러한 방법은 모두 애플리케이션 구성에 따라 개인 식별 정보, 로그인 사용자 인증 정보 또는 기타 민감한 정보의 유출로 이어질 수 있습니다.
완화 조치
파일 URL 확인
앱에서 file://
URL을 통해 파일에 액세스해야 하는 경우 일반적인 실수를 피하고 합법적인 것으로 알려진 특정 URL만 허용 목록에 추가하는 것이 중요합니다.
WebViewAssetLoader 사용
언급된 메서드 대신 WebViewAssetLoader
를 사용하세요. 이 메서드는 file://
스키마 대신 http(s)//:
스키마를 사용하여 로컬 파일 시스템 애셋에 액세스하므로 설명된 공격에 취약하지 않습니다.
Kotlin
val assetLoader: WebViewAssetLoader = Builder()
.addPathHandler("/assets/", AssetsPathHandler(this))
.build()
webView.setWebViewClient(object : WebViewClientCompat() {
@RequiresApi(21)
override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest): WebResourceResponse {
return assetLoader.shouldInterceptRequest(request.url)
}
@Suppress("deprecation") // for API < 21
override fun shouldInterceptRequest(view: WebView?, url: String?): WebResourceResponse {
return assetLoader.shouldInterceptRequest(Uri.parse(url))
}
})
val webViewSettings: WebSettings = webView.getSettings()
// Setting this off for security. Off by default for SDK versions >= 16.
webViewSettings.allowFileAccessFromFileURLs = false
// Off by default, deprecated for SDK versions >= 30.
webViewSettings.allowUniversalAccessFromFileURLs = false
// Keeping these off is less critical but still a good idea, especially if your app is not
// using file:// or content:// URLs.
webViewSettings.allowFileAccess = false
webViewSettings.allowContentAccess = false
// Assets are hosted under http(s)://appassets.androidplatform.net/assets/... .
// If the application's assets are in the "main/assets" folder this will read the file
// from "main/assets/www/index.html" and load it as if it were hosted on:
// https://appassets.androidplatform.net/assets/www/index.html
webView.loadUrl("https://appassets.androidplatform.net/assets/www/index.html")
자바
final WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder()
.addPathHandler("/assets/", new AssetsPathHandler(this))
.build();
webView.setWebViewClient(new WebViewClientCompat() {
@Override
@RequiresApi(21)
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
return assetLoader.shouldInterceptRequest(request.getUrl());
}
@Override
@SuppressWarnings("deprecation") // for API < 21
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
return assetLoader.shouldInterceptRequest(Uri.parse(url));
}
});
WebSettings webViewSettings = webView.getSettings();
// Setting this off for security. Off by default for SDK versions >= 16.
webViewSettings.setAllowFileAccessFromFileURLs(false);
// Off by default, deprecated for SDK versions >= 30.
webViewSettings.setAllowUniversalAccessFromFileURLs(false);
// Keeping these off is less critical but still a good idea, especially if your app is not
// using file:// or content:// URLs.
webViewSettings.setAllowFileAccess(false);
webViewSettings.setAllowContentAccess(false);
// Assets are hosted under http(s)://appassets.androidplatform.net/assets/... .
// If the application's assets are in the "main/assets" folder this will read the file
// from "main/assets/www/index.html" and load it as if it were hosted on:
// https://appassets.androidplatform.net/assets/www/index.html
webview.loadUrl("https://appassets.androidplatform.net/assets/www/index.html");
위험한 WebSettings 메서드 사용 중지
setAllowFileAccess()
, setAllowFileAccessFromFileURLs()
, setAllowUniversalAccessFromFileURLs()
메서드의 값은 기본적으로 API 수준 29 이하에서는 TRUE
로, API 수준 30 이상에서는 FALSE
로 설정됩니다.
다른 WebSettings
를 구성해야 하는 경우 특히 API 수준 29 이하를 타겟팅하는 앱의 경우 이러한 메서드를 명시적으로 사용 중지하는 것이 좋습니다.
위험: 파일 기반 XSS
setJavacriptEnabled
메서드를 TRUE
로 설정하면 WebView 내에서 JavaScript를 실행할 수 있으며, 앞에서 설명한 대로 파일 액세스가 사용 설정된 상태에서 임의 파일 내의 코드 실행이나 WebView 내에서 열린 악성 웹사이트를 통해 파일 기반 XSS가 가능합니다.
완화 조치
WebView에서 로컬 파일을 로드하지 못하도록 방지
이전 위험과 마찬가지로 setAllowFileAccess()
, setAllowFileAccessFromFileURLs()
, setAllowUniversalAccessFromFileURLs()
이 FALSE
로 설정된 경우 파일 기반 XSS를 방지할 수 있습니다.
WebView에서 JavaScript 실행 방지
JavaScript가 WebView 내에서 실행되지 않도록 setJavascriptEnabled
메서드를 FALSE
로 설정합니다.
WebView가 신뢰할 수 없는 콘텐츠를 로드하지 않도록 방지
WebView 내에서 이러한 설정을 사용 설정해야 하는 경우가 있습니다. 이 경우 신뢰할 수 있는 콘텐츠만 로드되도록 하는 것이 중요합니다. JavaScript 실행을 제어하는 JavaScript로만 제한하고 임의의 JavaScript를 허용하지 않는 것이 콘텐츠를 신뢰할 수 있도록 하는 좋은 방법입니다. 그렇지 않으면 일반 텍스트 트래픽이 로드되지 않도록 방지하여 위험한 설정이 있는 WebView에서 HTTP URL을 로드할 수 없도록 합니다. 이는 매니페스트를 통해 android:usesCleartextTraffic
을 False
로 설정하거나 HTTP 트래픽을 허용하지 않는 Network Security Config
을 설정하여 실행할 수 있습니다.
리소스
- setAllowUniversalAccessFromFileURLs API 참조 페이지
- setAllowFileAccessFromFileURLs API 참조 페이지
- WebViewAssetLoader API 참조 페이지
- CodeQL 문서
- 과도한 보안 블로그
- onShowFileChooser 참조 페이지