From f023a0f629f8651488dea01c1803687b8503bf52 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Fri, 8 Sep 2023 13:40:31 +0100 Subject: [PATCH] Use a random path to prevent other apps from accessing content. The path is the Base64 encoding of 128 bits from SecureRandom. This prevents anyone who doesn't know the path (eg untrusted apps running on localhost) from accessing the content. The root URL now returns a 404 page. --- app/src/main/assets/templates/send.html | 2 +- .../org/onionshare/android/ShareManager.kt | 2 +- .../android/server/WebserverManager.kt | 21 +++++++++++-------- .../android/ui/share/ShareBottomSheet.kt | 2 +- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/app/src/main/assets/templates/send.html b/app/src/main/assets/templates/send.html index 7e8794aa..0a58e358 100644 --- a/app/src/main/assets/templates/send.html +++ b/app/src/main/assets/templates/send.html @@ -23,7 +23,7 @@

{% if title %}{{ title }}{% else %}OnionShare{% endif %}

Total size: {{ filesize_human }} {% if is_zipped %} (compressed){% endif %}
- Download Files + Download Files diff --git a/app/src/main/java/org/onionshare/android/ShareManager.kt b/app/src/main/java/org/onionshare/android/ShareManager.kt index 38e1b593..3693539b 100644 --- a/app/src/main/java/org/onionshare/android/ShareManager.kt +++ b/app/src/main/java/org/onionshare/android/ShareManager.kt @@ -148,7 +148,7 @@ class ShareManager @Inject constructor( // We only create the hidden service after files have been zipped and webserver was started, // so we are in sharing state once the first HS descriptor has been published. notificationManager.onSharing() - ShareUiState.Sharing("http://${torState.onion}.onion") + ShareUiState.Sharing("http://${torState.onion}.onion/${webserverManager.contentPath}") } TorState.FailedToConnect -> { diff --git a/app/src/main/java/org/onionshare/android/server/WebserverManager.kt b/app/src/main/java/org/onionshare/android/server/WebserverManager.kt index d787c188..147fa11e 100644 --- a/app/src/main/java/org/onionshare/android/server/WebserverManager.kt +++ b/app/src/main/java/org/onionshare/android/server/WebserverManager.kt @@ -53,11 +53,12 @@ class WebserverManager @Inject constructor() { private var server: ApplicationEngine? = null private val _state = MutableStateFlow(WebServerState.Stopped(false)) val state = _state.asStateFlow() + val contentPath = getRandomPath() suspend fun start(sendPage: SendPage): Int { _state.value = WebServerState.Starting val staticPath = getStaticPath() - val staticPathMap = mapOf("static_url_path" to staticPath) + val pathMap = mapOf("static_url_path" to staticPath, "content_path" to contentPath) TrafficStats.setThreadStatsTag(0x42) val server = embeddedServer( factory = Netty, @@ -72,11 +73,11 @@ class WebserverManager @Inject constructor() { install(Pebble) { loader(ClasspathLoader().apply { prefix = "assets/templates" }) } - installStatusPages(staticPathMap) + installStatusPages(pathMap) addListener() routing { defaultRoutes(staticPath) - sendRoutes(sendPage, staticPathMap) + sendRoutes(sendPage, pathMap) } }.also { it.start() } this.server = server @@ -98,11 +99,13 @@ class WebserverManager @Inject constructor() { } } + private fun getRandomPath(): String { + val randomBytes = ByteArray(16).apply { secureRandom.nextBytes(this) } + return Base64.encodeToString(randomBytes, NO_PADDING or URL_SAFE).trimEnd() + } + private fun getStaticPath(): String { - val staticSuffixBytes = ByteArray(16).apply { secureRandom.nextBytes(this) } - val staticSuffix = - Base64.encodeToString(staticSuffixBytes, NO_PADDING or URL_SAFE).trimEnd() - return "/static_$staticSuffix" + return "/static_${getRandomPath()}" } private fun Application.addListener() { @@ -142,11 +145,11 @@ class WebserverManager @Inject constructor() { } private fun Route.sendRoutes(sendPage: SendPage, staticPathMap: Map) { - get("/") { + get("/$contentPath") { val model = sendPage.model + staticPathMap call.respond(PebbleContent("send.html", model)) } - get("/download") { + get("/$contentPath/download") { call.response.header( ContentDisposition, Attachment.withParameter(FileName, sendPage.fileName).toString() diff --git a/app/src/main/java/org/onionshare/android/ui/share/ShareBottomSheet.kt b/app/src/main/java/org/onionshare/android/ui/share/ShareBottomSheet.kt index 88144a1d..1c155065 100644 --- a/app/src/main/java/org/onionshare/android/ui/share/ShareBottomSheet.kt +++ b/app/src/main/java/org/onionshare/android/ui/share/ShareBottomSheet.kt @@ -257,7 +257,7 @@ fun ShareBottomSheetSharingPreview() { Surface(color = MaterialTheme.colors.background) { BottomSheet( state = ShareUiState.Sharing( - "http://openpravyvc6spbd4flzn4g2iqu4sxzsizbtb5aqec25t76dnoo5w7yd.onion/", + "http://openpravyvc6spbd4flzn4g2iqu4sxzsizbtb5aqec25t76dnoo5w7yd.onion/eW91IGFyZSBhIG5lcmQ7KQ", ), onSheetButtonClicked = {}, )