MASTG-TECH-0100: Registro de Dados Sensíveis do Tráfego de Rede
mitmproxy pode ser usado para interceptar o tráfego de rede de aplicativos Android. Esta técnica é útil para identificar dados sensíveis que são enviados pela rede, bem como para identificar possíveis vulnerabilidades de segurança.
Com o mitmproxy instalado e seu dispositivo configurado para usá-lo, você pode criar um script em Python para filtrar o tráfego e extrair os dados sensíveis. Por exemplo, o seguinte script extrairá todos os dados enviados nas requisições e respostas apenas se os dados forem considerados sensíveis. Para este exemplo, consideramos dados sensíveis qualquer informação que contenha as strings "dummyPassword" ou "sampleUser", então as incluímos na lista SENSITIVE_STRINGS.
# mitm_sensitive_logger.py
from mitmproxy import http
# Esses dados viriam de outro arquivo e devem ser definidos após identificar o que é considerado sensível para este aplicativo.
# Por exemplo, usando a seção de Segurança de Dados da Google Play Store.
SENSITIVE_DATA = {
"precise_location_latitude": "37.7749",
"precise_location_longitude": "-122.4194",
"name": "John Doe",
"email_address": "john.doe@example.com",
"phone_number": "+11234567890",
"credit_card_number": "1234 5678 9012 3456"
}
SENSITIVE_STRINGS = SENSITIVE_DATA.values()
def contains_sensitive_data(string):
return any(sensitive in string for sensitive in SENSITIVE_STRINGS)
def process_flow(flow):
url = flow.request.pretty_url
request_headers = flow.request.headers
request_body = flow.request.text
response_headers = flow.response.headers if flow.response else "No response"
response_body = flow.response.text if flow.response else "No response"
if (contains_sensitive_data(url) or
contains_sensitive_data(request_body) or
contains_sensitive_data(response_body)):
with open("sensitive_data.log", "a") as file:
if flow.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")
def request(flow: http.HTTPFlow):
process_flow(flow)
def response(flow: http.HTTPFlow):
process_flow(flow)
Agora você pode executar o mitmproxy com o script:
mitmdump -s mitm_sensitive_logger.py
Nosso aplicativo de exemplo possui este código:
fun testPostRequest() {
val thread = Thread {
try {
val url = URL("https://httpbin.org/post")
val httpURLConnection = url.openConnection() as HttpURLConnection
httpURLConnection.requestMethod = "POST"
httpURLConnection.doOutput = true
httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")
val user = "sampleUser"
val password = "dummyPassword"
val postData = "username=$user&password=$password"
val outputStream = BufferedOutputStream(httpURLConnection.outputStream)
val bufferedWriter = BufferedWriter(OutputStreamWriter(outputStream, "UTF-8"))
bufferedWriter.write(postData)
bufferedWriter.flush()
bufferedWriter.close()
outputStream.close()
val responseCode = httpURLConnection.responseCode
if (responseCode == HttpURLConnection.HTTP_OK) {
Log.d("HTTP_SUCCESS", "Successfully authenticated.")
} else {
Log.e("HTTP_ERROR", "Failed to authenticate. Response code: $responseCode")
}
} catch (e: Exception) {
e.printStackTrace()
}
}
thread.start()
}
O aplicativo envia uma requisição POST para https://httpbin.org/post com o corpo username=sampleUser&password=dummyPassword. httpbin.org é um site que retorna os dados da requisição no corpo da resposta, então podemos ver os dados que foram enviados na requisição.
Execute o aplicativo e use-o normalmente. O script registrará quaisquer dados sensíveis enviados pela rede no arquivo sensitive_data.log.
Exemplo de saída no console:
[10:07:59.348] Loading script mitm_sensitive_logger.py
[10:07:59.351] HTTP(S) proxy listening at *:8080.
[10:08:08.188][127.0.0.1:64701] server connect httpbin.org:443 (52.206.94.89:443)
[10:08:08.192][127.0.0.1:64709] server connect mas.owasp.org:443 (104.22.27.77:443)
[10:08:08.245][127.0.0.1:64709] Client TLS handshake failed. The client does not trust the proxy's certificate for mas.owasp.org (OpenSSL Error([('SSL routines', '', 'ssl/tls alert certificate unknown')]))
[10:08:08.246][127.0.0.1:64709] client disconnect
[10:08:08.246][127.0.0.1:64709] server disconnect mas.owasp.org:443 (104.22.27.77:443)
127.0.0.1:64701: POST https://httpbin.org/post
<< 200 OK 548b
Exemplo de saída no sensitive_data.log:
REQUEST URL: https://httpbin.org/post
Request Headers: Headers[(b'Content-Type', b'application/x-www-form-urlencoded'), (b'User-Agent', b'Dalvik/2.1.0 (Linux; U; Android 13; sdk_gphone64_arm64 Build/TE1A.220922.021)'), (b'Host', b'httpbin.org'), (b'Connection', b'Keep-Alive'), (b'Accept-Encoding', b'gzip'), (b'Content-Length', b'42')]
Request Body: username=sampleUser&password=dummyPassword
RESPONSE URL: https://httpbin.org/post
Response Headers: Headers[(b'Date', b'Tue, 16 Jan 2024 09:08:08 GMT'), (b'Content-Type', b'application/json'), (b'Content-Length', b'548'), (b'Connection', b'keep-alive'), (b'Server', b'gunicorn/19.9.0'), (b'Access-Control-Allow-Origin', b'*'), (b'Access-Control-Allow-Credentials', b'true')]
Response Body: {
"args": {},
"data": "",
"files": {},
"form": {
"password": "dummyPassword",
"username": "sampleUser"
},
"headers": {
"Accept-Encoding": "gzip",
"Content-Length": "42",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "Dalvik/2.1.0 (Linux; U; Android 13; sdk_gphone64_arm64 Build/TE1A.220922.021)",
"X-Amzn-Trace-Id": "Root=1-65a64778-78495e9f5d742c9b0c7a75d8"
},
"json": null,
"origin": "148.141.65.87",
"url": "https://httpbin.org/post"
}