Android-operativsystemet har många inbyggda säkerhetsfunktioner, till exempel applikationssandboxning, skydd mot buffert- och integerflödesangrepp och segregerade minnesområden för programinstruktioner och data. Som ett resultat kan enkla Android-appar som inte utför något filsystem eller nätverksoperationer ofta betraktas som säkra som standard.
Om du utvecklar en mer komplex app är det dock ditt ansvar att göra det säkert och skydda användarnas privatliv. I den här artikeln kommer jag att lista några av de bästa metoderna du kan följa för att bygga en säker Android-app som inte läcker data eller behörigheter, och är generellt mindre sårbar för skadliga appar som kan installeras på användarens enhet.
Varje Android-app har en intern lagringskatalog associerad med den vars sökväg är baserad på appens paketnamn. Filer i den här katalogen är mycket säkra eftersom de använder MODE_PRIVATE
standard för filskapande. Det betyder att filerna inte kan nås av någon annan app på enheten. Därför är det det bästa stället att lagra alla känsliga data i din app i den interna lagringsmappen.
För att bestämma den absoluta sökvägen för din appars interna lagringskatalog rekommenderas att du använder getFilesDir ()
metod. När du väl känner till sin väg är det enkelt att referera till filer inuti det som refererar till filer i någon annan katalog. Så här kan du till exempel hänvisa till en fil som heter myfile.dat i katalogen för din interna lagring:
Fil myFile = Ny fil (getFilesDir (), "myfile.dat");
Den interna lagringskapaciteten hos en Android-enhet är ofta begränsad. Därför kan du kanske inte ha något annat val än att lagra känslig data på externa lagringsmedier, till exempel ett flyttbart SD-kort.
Eftersom data på externa lagringsmedier kan nås direkt av både användare och andra appar på enheten, är det viktigt att du lagrar det i krypterat format. En av de mest populära krypteringsalgoritmer som används av utvecklare idag är AES, kort för Avancerad krypterings standard, med en nyckelstorlek på 256 bitar.
Skriv kod för att kryptera och dekryptera din apps data med hjälp av javax.crypto
paketet, som ingår i Android SDK, kan vara förvirrande. Därför föredrar de flesta utvecklare att använda tredje parts bibliotek, till exempel Facebooks Conceal-bibliotek, som vanligtvis är mycket enklare att arbeta med.
Erfarna programmörer som är nya på Android-applikationsutveckling försöker ofta använda uttag, namngivna pipar eller delade filer för att kommunicera asynkront med andra appar installerade på en Android-enhet. Dessa tillvägagångssätt är inte bara svåra och ineleganta, men också utsatta för hot. Ett enklare och säkrare tillvägagångssätt för kommunikationen mellan processer på Android-operativsystemet är att använda avsikt.
Om du vill skicka data till en viss komponent i en app måste du skapa en ny instans av Avsikt
klass och använd dess setComponent ()
Metod för att ange både paketets namn på appen och komponentens namn. Du kan sedan lägga till data till den med hjälp av putExtra ()
metod.
Det här är till exempel hur du kan skicka strängen Hej världen till en Aktivitet
kallad MyActivity, som tillhör en app vars namn på paketet är my.other.app:
// Skapa en avsikt Intent intention = new Intent (); // Ange komponentnamnet intent.setComponent (nytt komponentnamn ("my.other.app", "my.other.app.MyActivity")); // Lägg till data intent.putExtra ("DATA", "Hello World!"); // Skicka avsikt till aktiviteten startActivity (avsikt);
Om du vill skicka data till flera appar på en gång kan du skicka avsikt som en sändning med hjälp av sendBroadcast ()
metod. Som standard kan en sändning läsas av någon app som har en lämplig konfiguration BroadcastReceiver
.
Om du vill skicka känslig information som en sändning måste du därför använda ett anpassat tillstånd vars protectionLevel
är satt till signatur
. Genom att göra så kontrollerar Android-operativsystemet att endast appar som signerades med din signeringsnyckel kan ta emot sändningen.
Här är en kodbit som visar hur du skickar strängen Hej världen som en säker sändning:
// Skapa en avsikt Intent intention = new Intent (); // Lägg till data intent.putExtra ("DATA", "Hello World"); // Ange ett åtgärdsnamn för // mottagarens avsiktsfilter intent.setAction ("my.app.receive"); // Skicka som en sändning med hjälp av ett anpassat tillstånd sendBroadcast (avsikt, "my.custom.permission");
Observera att ovanstående kod fungerar som förväntat endast om de anpassade tillstånden deklareras och används i manifestfilerna för både avsändar- och mottagarapparna.
All kommunikation mellan din app och dina servrar måste vara över en HTTPS-anslutning, helst med hjälp av HttpsURLConnection
klass. Om du tror att du använder HTTP för att data som inte är konfidentiella är bra, tänk igen.
Många Android-användare kopplar till flera öppna Wi-Fi-hotspots i offentliga utrymmen varje dag. Några av dessa hotspots kan vara skadliga. Ett skadligt hotspot kan enkelt ändra innehållet i HTTP-trafiken så att din app beter sig på ett oväntat sätt, eller ännu värre, injicera annonser eller utnyttjar det.
Om du använder HTTPS, så länge servern är konfigurerad med ett certifikat som utfärdats av en betrodd certifikatmyndighet, som DigiCert eller GlobalSign, kan du vara säker på att din nätverkstrafik är säker mot både avlyssning och man-i-mitten attacker.
Om din app har mycket nätverkskod och du är rädd att du eventuellt kan skicka några data som cletext, bör du överväga att använda nogotofail, ett open source-verktyg som byggts av Google för att hitta sådana misstag.
Tillbaka när GCM, kort för Google Cloud Messaging, inte fanns, använde många utvecklare SMS för att driva data från sina servrar till sina appar. Idag är denna praxis till stor del borta.
Om du är en av de utvecklare som fortfarande inte har gjort omkopplaren från SMS till GCM, måste du veta att SMS-protokollet inte är krypterat eller säkert mot spoofingattacker. Dessutom kan ett SMS läsas av någon app på användarens enhet som har READ_SMS
lov.
GCM är mycket säkrare och är det bästa sättet att trycka meddelanden till en app eftersom alla GCM-kommunikationer är krypterade. De autentiseras med regelbundna uppdaterade registreringstecken på klientsidan och en unik API-nyckel på serverns sida. För att lära dig mer om GCM kan du hänvisa till den här handledningen om push-meddelanden.
Användarnas integritet är mycket viktigt idag. Faktum är att det finns lagar, såsom Europeiska unionens dataskyddsdirektiv och Canadas personuppgiftsskydd och elektroniska dokumentlagar, som innebär att användaren ska skydda användarens privatliv. Om du inte har en bra anledning och en mycket säker infrastruktur för att samla, lagra och överföra personlig användarinformation måste du därför undvika att direkt be om det i dina appar.
Ett bättre tillvägagångssätt för användarautentisering och användarprofilinformation ser upp på Android är via Google Identity Platform. Google Identity Platform tillåter användare att snabbt logga in på din app med sitt Google-konto. Efter en framgångsrik inloggning via plattformen kan din app när som helst leta upp olika detaljer om användaren, till exempel användarens namn, e-postadress, profilfoto, kontakter och mer. Alternativt kan du använda gratis tjänster som Firebase som kan hantera användarautentisering för dig.
Om du själv måste hantera användaruppgifter, rekommenderas att du lagrar och sänder dem i form av säkra hashser. Det enklaste sättet att generera olika typer av hascher med hjälp av Android SDK är att använda MessageDigest
klass.
Här är en liten kodbit som visar hur du skapar en hash av strängen Hej världen med SHA-256 hashfunktionen:
// Initiera MessageDigest för att använda SHA-256 MessageDigest md = MessageDigest.getInstance ("SHA-256"); // Konvertera strängen till en hash byte [] sha256Hash = md.digest ("Hello World" .getBytes ());
På Android leder vanligtvis inte användarinmatning till säkerhetsproblem som buffertövergångar. Om du tillåter användare att interagera med en SQLite-databas eller en innehållsleverantör som internt använder en SQLite-databas måste du emellertid antingen noggrant sanera användarinmatning eller använda parametrerade frågor. Om du inte gör det gör din data sårbar för SQL-injektionsattacker.
På samma sätt är användardatavalidering och sanering också mycket viktigt om du använder användarinmatning för att dynamiskt generera kod för att köras på en inbäddad skriptmotor, till exempel Mozilla Rhino.
Säkerhetsåtgärder som är inbyggda i en Android-app kan skadas allvarligt om angripare kan hämta källkoden. Innan du publicerar din app rekommenderas att du använder ett verktyg som heter ProGuard, som ingår i Android SDK, för att förvirra och begränsa källkoden.
Android Studio innehåller automatiskt ProGuard i byggprocessen om buildType
är satt till släpp
. Standardproguardkonfigurationen är tillgänglig i Android SDK: s ProGuard-android.txt filen är tillräcklig för de flesta appar. Om du vill lägga till egna regler i konfigurationen kan du göra det inom en fil med namnet proguard-rules.pro, som ingår i varje Android Studio-projekt.
Jag hoppas att du nu har en bättre förståelse för hur du gör dina Android-appar säkert. De flesta av de bästa metoderna som jag nämnde i den här artikeln är bara tillämpliga om du använder Android SDK för att utveckla dina appar. Om du använder Android NDK istället måste du vara mycket försiktigare eftersom du, när du programmerar på C-språket, förväntas hantera detaljer på låg nivå, t.ex. pekare och minnesfördelning själv.
Om du vill veta mer om säkerhet på Android kan du se AOSP-säkerhetsdokumenten.