mirror of
https://github.com/github/codeql.git
synced 2025-12-18 09:43:15 +01:00
243 lines
9.9 KiB
Java
243 lines
9.9 KiB
Java
package com.example.app;
|
|
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.InputStream;
|
|
import java.io.IOException;
|
|
import java.util.Locale;
|
|
|
|
import android.app.Activity;
|
|
import android.content.Intent;
|
|
import android.net.Uri;
|
|
import android.os.Bundle;
|
|
|
|
import android.webkit.MimeTypeMap;
|
|
import android.webkit.WebResourceRequest;
|
|
import android.webkit.WebView;
|
|
import androidx.webkit.WebViewAssetLoader;
|
|
import androidx.webkit.WebViewAssetLoader.AssetsPathHandler;
|
|
import android.webkit.WebViewClient;
|
|
import android.webkit.WebResourceResponse;
|
|
|
|
/** Insecure activity with its subclassed webviewclient implementation. */
|
|
public class InsecureWebResourceResponse extends Activity {
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
setContentView(-1);
|
|
|
|
String inputUrl = getIntent().getStringExtra("inputUrl");
|
|
|
|
getBadResponse1(inputUrl);
|
|
|
|
getBadResponse2(inputUrl);
|
|
|
|
getBadResponse3(inputUrl);
|
|
|
|
getGoodResponse4(inputUrl);
|
|
|
|
getGoodResponse5(inputUrl);
|
|
|
|
getBadResponse6(inputUrl);
|
|
|
|
getBadResponse7(inputUrl);
|
|
|
|
getGoodResponse8(inputUrl);
|
|
}
|
|
|
|
public static String getMimeTypeFromPath(String path) {
|
|
String extension = path;
|
|
int lastDot = extension.lastIndexOf('.');
|
|
if (lastDot != -1) {
|
|
extension = extension.substring(lastDot + 1);
|
|
}
|
|
|
|
extension = extension.toLowerCase(Locale.getDefault());
|
|
return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
|
|
}
|
|
|
|
// BAD: Return file of input path in annonyous WebViewClient without validation
|
|
private void getBadResponse1(String url) {
|
|
WebView wv = (WebView) findViewById(-1);
|
|
wv.setWebViewClient(new WebViewClient() {
|
|
@Override
|
|
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
|
|
try {
|
|
Uri uri = Uri.parse(url);
|
|
FileInputStream inputStream = new FileInputStream(uri.getPath());
|
|
String mimeType = getMimeTypeFromPath(uri.getPath());
|
|
return new WebResourceResponse(mimeType, "UTF-8", inputStream);
|
|
} catch (IOException ie) {
|
|
return new WebResourceResponse("text/plain", "UTF-8", null);
|
|
}
|
|
}
|
|
});
|
|
|
|
wv.loadUrl(url);
|
|
}
|
|
|
|
// BAD: Return file of input path in annonyous WebViewClient with insufficient validation
|
|
// A malicious input such as https://any.domain/local_cache/..%2Fshared_prefs/auth.xml can bypass the validation
|
|
private void getBadResponse2(String url) {
|
|
WebView wv = (WebView) findViewById(-1);
|
|
wv.setWebViewClient(new WebViewClient() {
|
|
@Override
|
|
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
|
|
try {
|
|
Uri uri = Uri.parse(url);
|
|
if (uri.getPath().startsWith("/local_cache/")) {
|
|
File cacheFile = new File(getCacheDir(), uri.getLastPathSegment());
|
|
FileInputStream inputStream = new FileInputStream(cacheFile);
|
|
String mimeType = getMimeTypeFromPath(uri.getPath());
|
|
return new WebResourceResponse(mimeType, "UTF-8", inputStream);
|
|
} else {
|
|
return new WebResourceResponse("text/plain", "UTF-8", null);
|
|
}
|
|
} catch (IOException ie) {
|
|
return new WebResourceResponse("text/plain", "UTF-8", null);
|
|
}
|
|
}
|
|
});
|
|
|
|
wv.loadUrl(url);
|
|
}
|
|
|
|
// BAD: Return file of input path in annonyous WebViewClient with insufficient validation
|
|
// A malicious input such as https://any.domain/files/..%2Fshared_prefs/auth.xml can bypass the validation
|
|
private void getBadResponse3(String url) {
|
|
WebView wv = (WebView) findViewById(-1);
|
|
wv.setWebViewClient(new WebViewClient() {
|
|
@Override
|
|
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
|
|
try {
|
|
Uri uri = Uri.parse(url);
|
|
String path = uri.getPath().substring(1);
|
|
if (path.startsWith("files/")) {
|
|
FileInputStream inputStream = new FileInputStream(path.substring("files/".length()));
|
|
String mimeType = getMimeTypeFromPath(uri.getPath());
|
|
return new WebResourceResponse(mimeType, "UTF-8", inputStream);
|
|
} else {
|
|
return new WebResourceResponse("text/plain", "UTF-8", null);
|
|
}
|
|
} catch (IOException ie) {
|
|
return new WebResourceResponse("text/plain", "UTF-8", null);
|
|
}
|
|
}
|
|
});
|
|
|
|
wv.loadUrl(url);
|
|
}
|
|
|
|
// GOOD: Return file of input path in annonyous WebViewClient with sufficient validation
|
|
private void getGoodResponse4(String url) {
|
|
WebView wv = (WebView) findViewById(-1);
|
|
wv.setWebViewClient(new WebViewClient() {
|
|
@Override
|
|
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
|
|
try {
|
|
Uri uri = Uri.parse(url);
|
|
if (uri.getPath().startsWith("/local_cache/") && !uri.getPath().contains("..")) {
|
|
File cacheFile = new File(getCacheDir(), uri.getLastPathSegment());
|
|
FileInputStream inputStream = new FileInputStream(cacheFile);
|
|
String mimeType = getMimeTypeFromPath(uri.getPath());
|
|
return new WebResourceResponse(mimeType, "UTF-8", inputStream);
|
|
} else {
|
|
return new WebResourceResponse("text/plain", "UTF-8", null);
|
|
}
|
|
} catch (IOException ie) {
|
|
return new WebResourceResponse("text/plain", "UTF-8", null);
|
|
}
|
|
}
|
|
});
|
|
|
|
wv.loadUrl(url);
|
|
}
|
|
|
|
// GOOD: Return file of input path in annonyous WebViewClient with sufficient validation
|
|
private void getGoodResponse5(String url) {
|
|
WebView wv = (WebView) findViewById(-1);
|
|
wv.setWebViewClient(new WebViewClient() {
|
|
@Override
|
|
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
|
|
try {
|
|
Uri uri = Uri.parse(url);
|
|
String path = uri.getPath().substring(1);
|
|
if (path.startsWith("files/") && !path.contains("..")) {
|
|
FileInputStream inputStream = new FileInputStream(path.substring("files/".length()));
|
|
String mimeType = getMimeTypeFromPath(uri.getPath());
|
|
return new WebResourceResponse(mimeType, "UTF-8", inputStream);
|
|
} else {
|
|
return new WebResourceResponse("text/plain", "UTF-8", null);
|
|
}
|
|
} catch (IOException ie) {
|
|
return new WebResourceResponse("text/plain", "UTF-8", null);
|
|
}
|
|
}
|
|
});
|
|
|
|
wv.loadUrl(url);
|
|
}
|
|
|
|
// BAD: Return file of input path in standalone WebViewClient without validation
|
|
private void getBadResponse6(String url) {
|
|
WebView wv = (WebView) findViewById(-1);
|
|
wv.setWebViewClient(new VulnerableWebViewClient());
|
|
wv.loadUrl(url);
|
|
}
|
|
|
|
// BAD: Return file of input path in annonyous WebViewClient with insufficient validation using WebResourceRequest object
|
|
private void getBadResponse7(String url) {
|
|
WebView wv = (WebView) findViewById(-1);
|
|
wv.setWebViewClient(new WebViewClient() {
|
|
@Override
|
|
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
|
|
try {
|
|
Uri uri = request.getUrl();
|
|
if (uri.getPath().startsWith("/local_cache/")) {
|
|
File cacheFile = new File(getCacheDir(), uri.getLastPathSegment());
|
|
FileInputStream inputStream = new FileInputStream(cacheFile);
|
|
String mimeType = getMimeTypeFromPath(uri.getPath());
|
|
return new WebResourceResponse(mimeType, "UTF-8", inputStream);
|
|
} else {
|
|
return new WebResourceResponse("text/plain", "UTF-8", null);
|
|
}
|
|
} catch (IOException ie) {
|
|
return new WebResourceResponse("text/plain", "UTF-8", null);
|
|
}
|
|
}
|
|
});
|
|
|
|
wv.loadUrl(url);
|
|
}
|
|
|
|
final WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder()
|
|
.addPathHandler("/assets/", new AssetsPathHandler(this))
|
|
.build();
|
|
|
|
// GOOD: Return file of input path in annonyous WebViewClient with WebViewAssetLoader
|
|
private void getGoodResponse8(String url) {
|
|
WebView wv = (WebView) findViewById(-1);
|
|
wv.setWebViewClient(new WebViewClient() {
|
|
@Override
|
|
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
|
|
return assetLoader.shouldInterceptRequest(request.getUrl());
|
|
}
|
|
});
|
|
|
|
wv.loadUrl(url);
|
|
}
|
|
}
|
|
|
|
class VulnerableWebViewClient extends WebViewClient {
|
|
@Override
|
|
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
|
|
try {
|
|
Uri uri = Uri.parse(url);
|
|
FileInputStream inputStream = new FileInputStream(uri.getPath());
|
|
String mimeType = InsecureWebResourceResponse.getMimeTypeFromPath(uri.getPath());
|
|
return new WebResourceResponse(mimeType, "UTF-8", inputStream);
|
|
} catch (IOException ie) {
|
|
return new WebResourceResponse("text/plain", "UTF-8", null);
|
|
}
|
|
}
|
|
}
|