The snippet below shows sample code that sends sensitive data over the network using the HttpURLConnection class. The data is sent to https://httpbin.org/post which is a dummy endpoint that returns the data it receives.
packageorg.owasp.mastestappimportandroid.content.Contextimportandroid.util.Logimportjava.io.BufferedOutputStreamimportjava.io.BufferedWriterimportjava.io.OutputStreamWriterimportjava.net.HttpURLConnectionimportjava.net.URLimportjava.net.URLEncoderimportjava.util.logging.LoggerclassMastgTest(privatevalcontext:Context){funmastgTest():String{valSENSITIVE_DATA=mapOf("precise_location_latitude"to"37.7749","precise_location_longitude"to"-122.4194","name"to"John Doe","email_address"to"[email protected]","phone_number"to"+11234567890","credit_card_number"to"1234 5678 9012 3456")varresult=""valthread=Thread{try{valurl=URL("https://httpbin.org/post")valhttpURLConnection=url.openConnection()asHttpURLConnectionhttpURLConnection.requestMethod="POST"httpURLConnection.doOutput=truehttpURLConnection.setRequestProperty("Content-Type","application/x-www-form-urlencoded")// Creating POST data from the SENSITIVE_DATA mapvalpostData=SENSITIVE_DATA.map{(key,value)->"${URLEncoder.encode(key,"UTF-8")}=${URLEncoder.encode(value,"UTF-8")}"}.joinToString("&")valoutputStream=BufferedOutputStream(httpURLConnection.outputStream)valbufferedWriter=BufferedWriter(OutputStreamWriter(outputStream,"UTF-8"))bufferedWriter.write(postData)bufferedWriter.flush()bufferedWriter.close()outputStream.close()valresponseCode=httpURLConnection.responseCodevalresponseContent=httpURLConnection.inputStream.bufferedReader().readText()if(responseCode==HttpURLConnection.HTTP_OK){Log.d("HTTP_SUCCESS","Successfully authenticated.")}else{Log.e("HTTP_ERROR","Failed to authenticate. Response code: $responseCode")}result="$responseCode\n\n$responseContent"}catch(e:Exception){e.printStackTrace()}}thread.start()thread.join()returnresult}}
Run mitmproxy with the custom script for logging sensitive data and dump the relevant traffic to a file.
Note that the script is preconfigured with data that's already considered sensitive for this application. When running this test in a real-world scenario, you should determine what is considered sensitive data based on the app's privacy policy and relevant privacy regulations. One recommended way to do this is by checking the app's privacy policy and the App Store Privacy declarations.
frommitmproxyimporthttp# This data would come from another file and should be defined after identifying the data that is considered sensitive for this application.# For example by using the Google Play Store Data Safety section.SENSITIVE_DATA={"precise_location_latitude":"37.7749","precise_location_longitude":"-122.4194","name":"John Doe","email_address":"[email protected]","phone_number":"+11234567890","credit_card_number":"1234 5678 9012 3456"}SENSITIVE_STRINGS=SENSITIVE_DATA.values()defcontains_sensitive_data(string):returnany(sensitiveinstringforsensitiveinSENSITIVE_STRINGS)defprocess_flow(flow):url=flow.request.pretty_urlrequest_headers=flow.request.headersrequest_body=flow.request.textresponse_headers=flow.response.headersifflow.responseelse"No response"response_body=flow.response.textifflow.responseelse"No response"if(contains_sensitive_data(url)orcontains_sensitive_data(request_body)orcontains_sensitive_data(response_body)):withopen("sensitive_data.log","a")asfile:ifflow.response:file.write(f"RESPONSE URL: {url}\n")file.write(f"Response Headers: {response_headers}\n")file.write(f"Response Body: {response_body}\n\n")else:file.write(f"REQUEST URL: {url}\n")file.write(f"Request Headers: {request_headers}\n")file.write(f"Request Body: {request_body}\n\n")defrequest(flow:http.HTTPFlow):process_flow(flow)defresponse(flow:http.HTTPFlow):process_flow(flow)
run.sh
1
mitmdump-smitm_sensitive_logger.py
Launch the app from Android Studio and click the button which will send the sensitive data over the network. The script will capture the network traffic and log the sensitive data.
After reviewing the captured network traffic, we can conclude that the test fails because the sensitive data is sent over the network.
This is a dummy example, but in a real-world scenario, you should determine which of the reported instances are privacy-relevant and need to be addressed.
Note that both the request and the response are encrypted using TLS, so they can be considered secure. However, this might represent a privacy issue depending on the relevant privacy regulations and the app's privacy policy. You should now check the privacy policy and the App Store Privacy declarations to see if the app is allowed to send this data to a third-party.