Juhised tokenide turvaliseks hoidmiseks Androidis

Selle artikli proloogina tahan märkida lühikese lause mõttelisele lugejale. See pakkumine on edasiliikumisel oluline.

Absoluutset turvalisust pole olemas. Turvalisus on meetmete kogum, mis koondatakse ja kombineeritakse, püüdes aeglustada vältimatut.

Peaaegu kolm aastat tagasi kirjutasin postituse, kus anti ideid Stringi märkide kaitsmiseks hüpoteetilise ründaja eest meie Androidi rakenduse dekompileerimise eest. Mäletamise huvides ja Interneti vältimatu surma ärahoidmiseks taasesitan siin mõnda lõiku.

Üks levinumaid kasutusjuhtumeid juhtub siis, kui meie rakendus peab andmete vahetamiseks suhtlema veebiteenusega. See andmevahetus võib muutuda vähem tundlikust olemuselt ja varieeruda sisselogimistaotluse, kasutajaandmete muutmise avalduse jms vahel.

Esimene rakendatav absoluutne meede on kliendi ja serveri vahelise SSL (Secure Sockets Layer) ühenduse kasutamine. Minge uuesti algse pakkumise juurde. See ei taga absoluutset privaatsust ja turvalisust, ehkki see teeb hea algtöö.

Kui kasutate SSL-ühendust (nagu siis, kui näete oma brauseris kappi), näitab see, et teie ja serveri vaheline ühendus on krüptitud. Teoreetiliselt ei pääse miski juurde päringutes sisalduvale teabele (*)

(*) Kas ma mainisin, et absoluutset turvalisust pole olemas? SSL-ühendusi saab endiselt kahjustada. See artikkel ei kavatse esitada kõikehõlmavat loetelu kõigist võimalikest rünnakutest, kuid tahan teile teada anda mõningatest võimalustest. Kasutada võib võltsitud SSL-sertifikaate, aga ka kesktasemel rünnakuid.

Liigume edasi. Eeldame, et meie klient suhtleb meie taustaprogrammiga krüptitud SSL-kanali kaudu. Nad vahetavad kasulikke andmeid, teevad oma äri, on õnnelikud. Kuid me tahame pakkuda täiendavat turvakihti.

Järgmine tänapäeval kasutatav loogiline samm on kommunikatsioonis kasutatava autentimisloki või API-võtme pakkumine. See töötab nii. Meie taustaprogramm saab petitsiooni. Kuidas me teame, et petitsioon pärineb ühelt meie kontrollitud kliendilt, mitte juhuslikult tüübilt, kes proovib juurdepääsu meie API-le? Taustprogramm kontrollib, kas klient pakub kehtivat API-võtit. Kui eelmine väide vastab tõele, jätkame päringuga. Muidu me keelame selle ja sõltuvalt ettevõtte iseloomust võtame mõned parandusmeetmed (kui see juhtub, meeldib mulle eriti salvestada kliendi IP-sid ja ID-sid, et näha, kui sageli see juhtub. Kui sagedus on rohkem kui see on minu hea maitse jaoks soovitav, ma kaalun keeldu või jälgin tähelepanelikult seda, mida ebaviisakas Interneti-kutt üritab saavutada).

Ehitame meie lossi maast üles. Oma rakendusse lisame tõenäoliselt muutuja nimega API_KEY, mis sisestatakse automaatselt igasse päringusse (kui kasutate Androidi, siis tõenäoliselt oma Retrofiti kliendis).

privaatne lõplik staatiline string API_KEY = “67a5af7f89ah3katf7m20fdj202”

See on suurepärane ja töötab siis, kui soovime oma klienti autentida. Probleem on selles, et see ei taga iseenesest väga tõhusat kihti.

Kui kasutate rakenduse apktooli dekompileerimiseks ja stringi otsimiseks otsimist, leiate ühest saadud .smali-failist järgmise:

const-string v1, “67a5af7f89ah3katf7m20fdj202”

Jah muidugi. See ei ütle, et see on valideerimise tunnus, seetõttu peame ikkagi läbi tegema põhjaliku kontrolli, et otsustada, kuidas selle stringi juurde jõuda ja kas seda saab kasutada autentimiseks või mitte. Kuid teate, kuhu ma lähen: see on enamasti aja ja ressursside küsimus.

Kas Proguard saaks meid aidata selle stringi kindlustamisel, nii et me ei peaks selle pärast muretsema? Mitte päris. Proguard väidab oma KKK-s, et stringi krüptimine pole täiesti võimalik.

Kuidas oleks selle stringi salvestamisega mõnes muus Androidi pakutavas mehhanismis, näiteks SharedPreferences? See on vaevalt hea mõte. Jagatud eelistustele pääseb hõlpsalt juurde emulaatorist või mis tahes juurdunud seadmest. Mõni aasta tagasi tõestas üks mees nimega Srinivas, kuidas videomängus saadud punkte saab muuta. Meil on siin võimalused otsas!

Algse arengu komplekt (NDK)

Uuendan siin minu pakutud algset mudelit ja seda, kuidas saaksime selle kaudu ka korrata, et pakkuda turvalisemat alternatiivi. Kujutleme kahte funktsiooni, mida saaks kasutada meie andmete krüptimiseks ja dekrüpteerimiseks:

Siin pole midagi väljamõeldud. Need kaks funktsiooni võtavad võtmeväärtuse ja stringi, mis kodeeritakse või dekodeeritakse. Nad tagastavad vastavalt krüptitud või dekrüptitud tokeni. Me nimetaksime järgmist funktsiooni järgmiselt:

Kas sa arvad suunda? See on õige. Saime nõudmisel oma tokeni krüptida ja dekrüpteerida. See annab täiendava turvalisuse kihi: kui kood hävitatakse, pole see enam nii lihtne kui stringi otsimine ja selle stringi ümbritseva keskkonna kontrollimine. Kuid kas saate ikkagi välja mõelda probleemi, mis tuleb lahendada?

Saad sa?

Andke sellele paar sekundit rohkem, kui te pole seda veel välja mõelnud.

Jah sul on õigus. Meil on krüptimisvõti, mida salvestatakse ka kui String. See lisab varjamise kaudu veelgi turvalisuse kihte, kuid siiski on meil tavalises tekstis luba, sõltumata sellest, kas seda luba kasutatakse krüpteerimiseks või on see per-se.

Kasutame nüüd NDK-d ja kordugem meie turbemehhanismiga.

NDK võimaldab meil juurdepääsu Androidi koodist C ++ koodide baasile. Esimese lähenemisviisina mõelgem veidi aega, mida teha. Meil võiks olla loomulik C ++ -funktsioon, mis salvestab API-võtme või mis tahes delikaatseid andmeid, mida proovime talletada. Seda funktsiooni saab hiljem koodist kutsuda ja ühtegi Java-faili stringi ei salvestata. See tagaks automaatse kaitse dekompileerimise tehnikate vastu.

Meie funktsioon C ++ näeks välja järgmine:

Seda nimetatakse teie Java-koodis hõlpsalt:

Krüptimis- / dekrüptimisfunktsiooni nimetatakse järgmises lõigus:

Kui me teame, et genereerime APK, hägustame seda, dekompileerime selle ja proovime pääseda stringi, mis sisaldub natiivse funktsiooni getSecretKey (), ei leia me seda üles! Võit?

Mitte päris. NDK koodi saab tegelikult lahti võtta ja kontrollida. See muutub üha raskemaks ja te hakkate nõudma keerukamaid tööriistu ja tehnikaid. Saite lahti 95% -l skriptilistest lastest, kuid meeskond, kellel on piisavalt ressursse ja motivatsiooni, pääseb endiselt loa juurde. Kas mäletate seda lauset?

Absoluutset turvalisust pole olemas. Turvalisus on meetmete kogum, mis koondatakse ja kombineeritakse, püüdes aeglustada vältimatut.
Juurdepääs on endiselt lahti võetud koodilõikudes Literal!

Näiteks Hex Rays teeb looduslike failide dekompileerimisel väga head tööd. Olen kindel, et leidub ka hunnik tööriistu, mis võiksid dekonstrueerida mis tahes Androidi abil loodud päriskoodi (ma pole Hex Raysiga seotud ega saa neilt mingit rahalist hüvitist).

Millist lahendust saaksime kasutada taustaprogrammi ja kliendi vaheliseks suhtlemiseks ilma, et meid oleks märgistatud?

Genereerige võti seadmes reaalajas.

Teie seade ei pea mingisugust võtit talletama ega tegelema Stringi tähtversiooni kaitsmise probleemidega! See on väga vana tehnika, mida kasutavad sellised teenused nagu võtme kaugvalideerimine.

  1. Klient teab funktsiooni (), mis tagastab võtme.
  2. Taustprogramm teab kliendis rakendatud funktsiooni ()
  3. Klient genereerib võtme funktsiooni () kaudu ja see toimetatakse serverisse.
  4. Server valideerib selle ja jätkab päringuga.

Kas ühendate punkte? Natiivse funktsiooni asemel, mis tagastab teile stringi (hõlpsasti tuvastatav), miks ei peaks teil olema funktsiooni, mis tagastab teile kolme juhusliku algarvu summa vahemikus 1 kuni 100? Või funktsioon, mis võtab jooksva päeva ühekordselt väljendatuna ja lisab igale erinevale numbrile 1? Kuidas oleks seadmelt mingi kontekstuaalse teabe, näiteks suurema mälumahu saamiseks kasutatava mälumahu, võtmisega?

Viimane lõik sisaldab rea ideesid, kuid meie hüpoteetiline lugeja on loodetavasti võtnud põhipunkti.

Kokkuvõte

  1. Absoluutset turvalisust pole olemas.
  2. Kaitsemeetmete komplekti ühendamine on kõrge turvalisuse taseme võti.
  3. Ärge talletage String-tähestikke oma koodis.
  4. Kasutage NDK-d enda loodud võtme loomiseks.

Kas mäletate esimest lauset?

Absoluutset turvalisust pole olemas. Turvalisus on meetmete kogum, mis koondatakse ja kombineeritakse, püüdes aeglustada vältimatut.

Tahan veel kord rõhutada, et teie eesmärk on kaitsta oma koodi nii palju kui võimalik, kaotamata samas vaadet, et 100% turvalisusest on kättesaamatu. Kuid kui suudate oma koodi kaitsta viisil, mis nõuab teie käsutuses oleva mõistliku teabe dekrüpteerimiseks tohutult ressursse, saate magada hästi ja vaikselt.

Väike lahtiütlemine

Ma tean. Olete siin jõudnud, mõeldes kogu artikli vältel "kuidas see tüüp ei maini Dexguardit ja teeb kõik vaeva?" Sul on õigus. Dexguard võib keelpillid tegelikult hägustada ja nad teevad sellega väga head tööd. Dexguardi hinnakujundus võib siiski olla liiga kõrge. Olen Dexguardit kasutanud ka varasemates kriitiliste turvasüsteemidega ettevõtetes, kuid see ei pruugi olla kõigile kättesaadav. Ja nii tarkvaraarenduses kui ka elus on seda rohkem võimalusi, mida rikkamaks ja rikkalikumaks maailm saab.

Head kodeerimist!

Kirjutan oma Twitteri kontole oma mõtteid tarkvaratehnika ja eluolu kohta üldiselt. Kui teile see artikkel meeldis või see aitas teid, siis jagage seda, ♥ ja / või jätke kommentaar. See on valuuta, mis õhutab amatöörkirjanikke.