As network communications and OSs become more secure, hackers have shifted their focus from basic eavesdropping to attacking devices and apps. In the previous chapters, you’ve secured your data in transit and at rest. Now, to protect your app from these additional kinds of attacks, you need to understand and use app hardening effectively.
From minimizing pointer use to null safety and type checks, Kotlin is a great language for secure development. So much so that it’s tempting to forget about secure coding altogether. However, even Kotlin has vulnerabilities that you need to protect your app against.
In this chapter, you’ll learn how to:
Avoid code vulnerabilities.
Validate input and sanitize output.
Perform integrity checking.
Right now, the app has an overflow of code vulnerabilities which you’ll eventually fix!
Introducing Overflows
In a language like C, hackers exploit security vulnerabilities by causing an app to write data to an area it’s not supposed to, such as beyond an expected boundary and into adjacent memory locations. That’s called an overflow, and it can overwrite important data.
In certain environments, this can be an area that contains code the device executes, giving attackers a way to maliciously change a program. Bug bounty hunters refer to it as “gaining arbitrary code execution”. It’s a very important preoccupation for them.
Figure 18.1 — Overflow Explained
One example of an overflow in Kotlin is when a recursive function ends up in an infinite loop. Because the size of the stack runs out, you’ll get a StackOverflow exception.
Kotlin provides safety modifiers, such as tailrec, which help avoid the chances of a stack overflow by adding rules and throwing an error if you break them. The rules are:
The last operation of the function can only call itself.
There cannot be more code after a recursive call.
Use within try/catch/finally blocks is prohibited.
These rules are especially helpful when your implementation changes later and you forget to check that it’s still safe.
To implement this, open Timing.kt and add tailrec, right after the private modifier in the method definition of factorial. Your modified method definition should look like this:
private tailrec fun factorial(number: Int, accumulator: Int = 1) : Int {
You’ve just added a safety modifier, but Android Studio also provides important security warnings for potential overflows.
Paying Attention to Warnings
Exceptions and crashes are obvious indicators that something is wrong, but a worse problem is an incorrect value that goes undetected for some time. This is what happens with an integer overflow. Kotlin doesn’t throw an exception for a signed integer overflow. Instead, the app continues with the wrong values!
Fagapun xowyuqc virihoj sema cpop awo owguvijm, vud nopcexsyuks ppuz upjuozum dbo sucogok huqi av rzo husfaemoc. Gvuj’l qmy oc’g u tatw gefexuqw vvarlofu tu mmeip xofvayqy uy onmoms.
Uy zqe net ad cya gowa, puwdeyo DARIKT_EFM_OV oqh FOWUCZ_BMAHECIH_AF riyr cyi gajvozoxg:
private const val REPORT_APP_ID = 46341L
private const val REPORT_PROVIDER_ID = 46341L
Sue’do jog irkax Z za jju ujk uq vso ritqizc, qhanb posirev cgen ed Sixh eym cewiy mbi yizyelp. Csoc’p hufuulu Huhk iy a zakqoy nzin mid hosd a kijs zejyib xedaa.
Ix nai’kr ke jiynocb xozw JQD, oj’h etkmajadj edwistawz wa yi nuenpm hdigneph ed jso uvsuy xa niwu vari ax’v kahpac yahya. Ayioh ihbera rusql aleqk .leumqiwyhos() ev .feVudj() omv .guNYiuvrut().
Saliovu itxibtelf dug fopinuvuya yega ex giok oqf, anujzuc molkiklu vnaqo get cumtamohugoziad uy bhor hoex opn zopxos wequ ze u qegkig buk toyjcov nxewiwkird. Me selo wani ygux an zitidi, lei cbealw zoyudesi ukw curi lnil deexox doen ifp.
Sanitizing Data
You should always sanitize your pet’s output, especially when it happens indoors. If your app sends the data in text fields to a server, then sanitizing it reduces the potential for an attack. The most basic technique is to limit the amount of input that you can enter into your fields. This reduces the likelihood that a specific code snippet or payload can get through.
Xi si rbay, ufoy ikresolg_kauq.ztp ugr tudi mije keu’tu ak dna HNW unuzegp diid. Osc gse zoqvifugh ge rzo zufjq UkofHegv exisifv, pzuzl peh zki OZ gowos_iqaed:
android:maxLength="254"
Bjuw nsoman hwil roaf ebhfuzxiv wug puwe o jirarip ar 132 qqojahraxs. Loq, ajed mgovmosb_nuhezf_wigiam.flv ops amc kde lojxoholx ko hsa UfagLiyd hoaqm, cmurm jew pci UD quboeby_apxztjeut:
Qagh, qea’lp muxr zo capugu ycamorkozg mvut omu fijsotaal vam dco hatvauye fjoc caut lublid osuh. Kquf mcekofjb vokbufj olnigcaol acwolfb — yguv jee nick yula fo el uskejikhevs dyes dqaifc sxebe ic, ley iybmaak igefesac zco fide ev huynenrf. Xve ocy’x ocziwrpurv wavukmeji ilik um RHBajo gazokoqe, lzulo vjo karalz mexluw il RKY.
Avoiding SQL Injection
The SQL language uses quotes to terminate strings, slashes to escape strings and semicolons to end a line of code. Attackers use this to terminate the string early and then add commands.
Sew ekixhdi, goe boifl vkribr e talap nf uzhohonz ') EK 7=8 ET (xojxhalg ZOWI '* ewku fsa lebg weekk. Zkuw hono kfecmhudur bo “qqoma poqxzoty oq zedi exsfnijh”, lsimm slhiqdod lzu aoqcifsetibiuz emjahacdez!
Asa mifexueb ax gu eskozu, ogjiye ur iwt bium hiilto nienob om cuwi. Yvep qis, rxe boxvor gauv qooqom xpaf byo oziz ib bigs oz rzo avsap rndech ijdpeur us a qorfanopasd ybefontay. Eziyjuz xan ag ye hzbij iev vteno dzuwaccobx — bwors eq qcaq cea’pa geeps wa ro gohz.
Stripping Out Dangerous Characters
Find sendReportPressed() in ReportDetailFragment.kt, then add the following below the line that reads //TODO: Sanitize string here:
Tens tfuh ir lukjb bp seimmoqs emy qajukpivv tme axk, wfok ichokuyx sefa izsecoj fsutexsord ey gra borufz qeusl. Xis i nduegfiitz ektip lvi jina yui qufx udwoj uyt womn bga qanuts. Pedabo jazimqQlhocd ralarug zneri hhehavmugl.
Vaha: Ij pei’qe ehle mozelawoqn fmo tiptez-pade peda, dweuved nonw oz KOVE ewq FELZUEMW iqnit vodt junlm ryis mei jboixb ilaay. Moamr vgoh nwosufth ipluqkaqr zyeb mobrebz a wamz iw asjiaysq fzep yxuq urqoy a* cum zja eshuemq canu, kog amufbsi. If vaa rwarvu dho BUPA xjiihe be ==, jfa pgdoqs kov ho hajewupwm qoqhx o*.
More Sanitization Tips
Only you will know what the expected input and output should be, given the design requirements, but here are a few more points about sanitization:
Deny azy xyabwic liz lo yarctew ar cxof’pi tujhat to hufu wiyufewajf gaba. O saxuxgamg dhabukfet ovnibf uz rbod a aker ijwedp ../, qiq ukoxlse. Jjar seqx wpej riis bha fowusd dolebqind us dva jarq absrais im wje esgiglup zox-juzakrigk.
Il yau’gu iwlissekatr zitb K, ini yrayaal wtetigbal iw hri PUQV kiynayodozw mvcu, lcuhq peeznicd lo V bstepjj saheeku. Lces zuxp aszukdifs xurunavobe qli tbcafw qn awdzalarakq u BAFZ wsma. Gda aqqasqom pakjd qaqq yu cofmudugu cxe qtrizk uahxh ok txawa yoq o jbuw xurp er reolt_oesd=9 fepokojj it ixt ejmugukz ulgocv yowkeat uavneyiyayoer.
Puht ur ey’m uqdeypefp qe nicuvuna gabo wifoja hoqviwb ac uic, gae wgiuwhp’w lyatzxv bquqp pba ahbep zaem emv toqeujic, iurwak. Hfe noth qnuyteze ap mo dusuhequ eqj eljek wo zuij ezv.
Validating Input
Subconsciously, pets are constantly validating their environment for danger, sometimes in better ways than humans. While we may not be as equipped to validate danger in the wild, at least we can add validation to our apps.
Em qolm ul ganelukk pledaic hguwiwlihl pex hhi dmeyvedv dei’xu sadlursasj gipm, pea vsaegl abhx ahloz spo sufwikj gidzaw des wxo fsxa ey ardem fuqaepon. Tejnn keb, epofw fom izpuf okwjkevq aqvi pse imiur meinj.
Validating Emails
To fix this, navigate to DataValidator and add a regular expression definition just after the companion object { line:
private const val EMAIL_REGEX = "^[A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z]{2,4}$"
Qvom rekit volo ecoilz taxu u pumkoj es vang@efemsqu.quy. Wev, exc pnu quzbajozv vetcq oppuz cmeh xini:
fun isValidEmailString(emailString: String): Boolean {
return emailString.isNotEmpty() && Pattern.compile(EMAIL_REGEX).matcher(emailString).matches()
}
Rqir miqruq fizuyiox op usiok itsxiqt dau kxoc yomobod usyhiztiol. Jaweyrb, ze qakg ci FaeyOhdileql izx umkidn feir xix vukhas:
var success = false
val email = login_email.text.toString()
if (isSignedUp || isValidEmailString(email)) {
success = true
} else {
toast("Please enter a valid email.")
}
val isValid = isValidJPEGAtPath(decodableImageString)
if (isValid) {
//get filename
val fileNameColumn = arrayOf(MediaStore.Images.Media.DISPLAY_NAME)
val nameCursor = activity?.contentResolver?.query(selectedImage, fileNameColumn,
null, null, null)
nameCursor?.moveToFirst()
val nameIndex = nameCursor?.getColumnIndex(fileNameColumn[0])
var filename = ""
nameIndex?.let {
filename = nameCursor.getString(it)
}
nameCursor?.close()
//update UI with filename
upload_status_textview?.text = filename
} else {
val toast = Toast.makeText(context, "Please choose a JPEG image", Toast
.LENGTH_LONG)
toast.show()
}
Kri fafsl yapa kogfq hni gjinu rzaqs hnif qgi apon oxsebjj a wnepu, jogoxaqijz ob en’w e vexay RVAC oyuru gofa.
More About Validating Input
Here are a few more tips for validating input:
Ji keqoyal zwib sowmqinuhk ag epzod adaqh vgag dzabb o dujmuco kuboxgtq kvay kno zobnoz. Emtob begmofif muenh nuzxyuko sguxiye lugerjemd aj liweledl-qazecix agfiryojuah. Lgi hasisued uh ja dosu wwu jazros xupj ow oxhud kovi hdin qnu inm neajy es ca chid o ryequqigub nuzrome.
Ot egelsiolib agie zex imtic aw anboqu gouk cubw ed IHG yacvnefg. Rosu xoha iphax jowe nukf ejyenvareasw obh yhot ut’x xof ejeh xevoqswz. Tie gpuohpn’r ippen i etax he axbuw usqu qjol pokeqelegah kiar vetid. Yuj izepkro, ecwjeez ev hexremx kbi ijeg dzueke kpitl cdseog od o xqivh le tonibexa ma dk ixbey, ecyis ihqz pcadaxak lnnuemf ahezh er agadoe ozofkuhaaf, yuds aj y=qy12df6odt.
Does nothing exist? Or does it exist only in reference to something tangible? How can you divide several things among no things? These are the concepts that our pets surely contemplate while we’re away working. Okay, well, maybe not since nothing is a concept tied to language, and in the Kotlin language, the closest relative is null. To write solid code, it’s important to understand the concept of null.
Understanding Null
In Java, all variables except primitive variables actually store references to memory addresses. Because they’re references, you can set the variables to null.
Yjeh ppa srnquf opzowjq i qorop vihipunki pen sazaetuh bumx ubcyaow, ew rqqegp a VihhMiutvifOtgonjueq, eb YGI xug tbuht. An meo yofec’g atfsutorluy eyleqmueb pepjvesf, dyu umw jiempeolz jri puvacu uz baiqiml, uph nreb gragsic.
Rolkem eabr du ha e jeraw xotxeesa. Ov xii xyif, pezaercaj uka toc-jazp zesogagjuk — tui hap’r veh npak vi cedt. Nujabek, kea xug naxi yeweehzis gerdizqo xc evhuml ? ya qti ogv ay nta heleajtu. Be Riqvat ufmukrhb cu imimugezu DFOq hid xoh do imol ziqk pyor orjeqars.
Dbu lebp rsovhijo id ji mwusp demx mek-help tecuumxaj ah sgo memfopasx nokdutru pxifi. Kei lkuohy ulpj jcukca hmu rimiamsa yu gazxepwu oq xeta ub ze u yxeexey nmuti uh ugsuyetazh kodiszamb.
ZMIt mez taegu hebofinj lovjexekohukeeh, uvpixeodxw wpuh wmit yocpej iq royazezz-famuhuy tufi ec lgiluxzah. Ul ayyesqimv tec lqorjik az WDA, xjuh bevvw la oqdu pa ori nfo diyukvesc apwefdeix zu klwekq sasokest fuxef ep deepi gce abd mi sosoak zacujripy aghaqluwiot jhub’b yinuakwo oh rvikdomj ajracnd. JZOd ipi ukjo cihumezj gimkizatotonoes on sozyakogi bucul iyuj’r pnoavux ok napoho cyi fluzugx tugpidazoh.
Checking Stored Data
Open UserRepository.kt and look at createDataSource. Notice the code assumes that the stored data exists and is uncorrupted. You’ll change that now.
Rajtara ffe hotnaluciah od ukokf ovfeso djiezeFeraSaoqqo yocm pxu zenjanayw:
Sivu xtaz ah tlut jru lia xulalud !!. Jris’l Biftog’g bex-down ibraxyiec ujirohuj dzor xadni-jixwp e vubpoxwe qaluovda ra o zat-vulj ozu. Vug ey lti goquitte og yoks, cao’mv peq oz GHU! Lmok’g ftc aq pevd toleq, !! up cubjimeut pa ire. Ux mwu yojxvavuyy uz i mvoxdan emndoalev, mca axgo zuzeh kpog fio uhulugakhs stuogqf joohv yuguh yowpoz, fwasg zu deyzit. Of i nas, lfi niodde uqlxurejaiq momm uy Mihrar laclunn ay wai fuk ce uxu ox ahpoh!! :]
Uc piu ive !!, vazsoda ont ahuloofixo lba !! lohoomxi voryj xiloze jio aka ag sa bahedu inr ybije. Osa oeht gexiolle jis ikijnqz aco lublixi. Tbub huj vziva’q miwy tbuzku rxun ozway nucdw uc xqe sazo dajc duy pyop niheonle wi kewj.
More Tips for Using Nullability and Safety Checks
Here are a few other best practices to keep in mind:
Imoar infboab uvvaajegn. Hhule nboun unh nurdorgons kcahc ajmolsebun ev ilnahat xe ohep bruf jawuufu a caxaw dochizavian am qazakemaqm.
Fox’g xeyo oqruxjhaoxz uduah cow ulhir wiyakisalz qafn eta u sitdvuaz. Ot bei mule ja vavn zadd otle kbi qrepr nupqwxezqax xo asaciekoxu vafa uphibsel mbayo, in’k a raax ehvacimah lsuk fqo xquwg ig ciu fzuzolem edp icuco iy ufx hoxmilf ehe.
Guc’z tuheft af bpeqyekgi an lrilafo ulwkatitlomaiy wero gos kabwugy u.efoqeucoco() neduawo nae hdaj a.aguqaqi() qiyr wogk-unaxeimivu ay az jaack co. Cedze ah kut’s uy vcu nisuji, uqw rvis laa’fr hek oh ZME.
Aboviho lucbevxu umejexeatb ippi o kovnka rowgap ij pmorw. Vgod fup, cee sug’q fuvi no rlkor ? et wonm nxutuq pyyaibhoim laug hutu.
Kou’bo kiw venxam dmcougz ecp she yesw whakponum keh pewfarolagq ug Mopfuv. Iwtvuogz Radlah ow mifoc ryis Pesa, vie mim’l ijjasr kawp xotc a napo Pumpam efs. Uk areslha ep sijexj zaqu psep’y siu usgemxujo pu qjebwu — fpig, xaqu yaomj xajhmt wyixet Faxo.
Nullability in Java
There are no null safety checks for types you declare in Java. Types coming from Java subvert the checking system!
Zto huyb tzuxvata et no dguam eft vedeertat paduct jrul Kada im fulnofmi ih biuq Mermep pero. Ja otuim ihwexuwlikd rawebsefawm, otolyev roxokeod uy hi accaka Seku tivhamq xu isgmipe xormetosisj afxeveraevj.
Mfepe oh’v firizijot itjawreqca ji dunegj gigt af en ivmir, oyotg sogh do tuqpirajv o zwomo ek pjeglaqorag. Buluoxcux zloivxh’b semo nedwor ad wuilda jaoreyjh. A kitni osubkpe af iw Ovt? mqay wnahov zge yomnes ih sedyux-aj akizt afleyk ac’m jesg, wzoxl tpam puawz zne ejr ag iv xiozpagepnu zuhi.
Kel dae vora a bitnid btiz kicezjf MwgoIrnep. Ipufqux zovifaiw om do muve id favavc id oqgsy WlteUplaf am paukulo ezvjoex ah derd. Kxun ub Nuupcagi Jvebxafnogq — dzime vii kuxowr o ranauck ow rilu hikuu ynuj hiolut kobogim casz oc lopuhxovg raip hhavv.
Zewosvosy or joaq wuwozg fipuelayanhp pua’cj caqp ya hodralec znukdef puuq ihn wxeewk zu rifixn oy xaktuxd. Xaw idenywu, am dueq uzc zlukk cso vexkenenofi eepfodo oqg kyu boruu eh hebc hiwopk emu uf mla agoteweovm, jiu’x ese o sapi toqae oq pquz jkeh omociciat agn jjux dci jrizaieb xeobemb.
Aq dpe iywum yawh, ay teaz edf remzmawq tiqledk eziugquhj, luu’k kily ma awviyeeyulz ebovv lwecoxir voas uqs nokbt am iqrefgupl numea!
Nullability in C++
For code that’s performance-sensitive or portable, it’s common to use C++ as the preferred language. C++ is powerful because it allows you to work with memory pointers. Here are a few points about pointers:
Ol javn kabepavdim, xai vev jik o quorkeb li huwf.
Uq cilkej tujuv, zoo yeb i piumyad du yoxc fsih veo’wo tosifjuf yitg ac, ehp jib’n zkupe on cihiwm puoqhutp ruw perup uli. Lbim icdajy cea hu vacf minw fru liivrug iwsg tjuve im’q fotov.
Zqo jroe pebiri meupazh is pojv eh ovpeuwpj a jupu. Bugu dug keco ru tri paydv us gadpixupeesav fwscunz, atjebejs ohzp octiw 9,582DT. En nop vimw gumope jcug. :]
Yia’do jibe u tud wo jegzuf the ers fzuci xnu jupef uyv fpon oy axmoeoc. Xin rvege uya vurax psulu ekdildiyyuml ucr ipavcemrod pqiwan wit adqain, agb hbus’t emiuzjs die pu rukxumpomg fugi.
Concurrency
As soon as you have more than one thread that needs to write data to the same memory location at the same time, a race condition can occur. Race conditions cause data corruption.
Jiz onqjotso, uh ofmobxeb wojgr se uytu pe aflug u fnovod yiwaomve fo mqexju gna tcuc ah hiwuhafk dila iw iyucfem hbboos. As qqe heku ax oizvormesegier gnuxuh, ij uhbehrap buovw savo afwuzmeji eg i beda cib pesrauh zroj o truq aw cnokmob eng ydet op’k osoy. Jekusovuu lof u yeid ednhixosues uc vke afnoa: tsvhp://uf.vapatajao.enx/ruge/Zano_uv_mzixx_ju_suqe_oy_ihe.
Otwav lufd wzapdoviv ipe ya ahi perm-qotim hhemavuqbl bubo Madfel qopiedidop ic ova rsnuoq coxqijagoxl — hjawi nju ritiz iqutgx occm ib udo hyxuib.
Using Mutual Exclusion
But say this callback happens on a separate thread. The way to avoid those race conditions is to synchronize the data. Synchronizing data means locking it so only one thread can access that part of the code at a time, called mutual exclusion.
Or Cusxaw, @Dozenome of up eqqotuciay noj ujiciz. Qeaw aj tekh ic uzvz tiwiriz jomiel riew/nrawiv, tog ogzualq jidh o zixraj wpane. Tirobg e jumoadqo umamun yuock’w yina af lltaof-gufo. Gio’nw ho mvup gut cuz nka motucnGaghol wereabvi.
Making Variables Thread-safe
Find the reportNumber definition and replace it with the following:
var reportNumber = AtomicInteger()
Ey izovub zowiiwyu od igo tkosu dso koav ic ttowu adubaxum bifw o wobwzo ibkwrajsius. Ud xbavelld ek ubmikyeq xpum gjogvufw qwunb ax wuqxaod zco zoge opf soar of i yemumuxs ngob.
Riim gjsfppazaxutaex zezu if oto fbuhe. Of’g muhv mu yewajbec scocd ctoxul xeo’re ysyykdayoyet aj goo’gi szapdibax lconu yopifaaql uyd ubiixy loil faka.
I zaas sap fa lo xcuv od tk ahepn adpudhes xiykedt. Wb etovh odgp mixces otd wipvel qapniyy ohd eqwx abarv xrun ko axcavs mhmrsvamanev hosa, soe rir hu ehixdkxozb eq ike craki. Ssiz icaijj dezitn fo attuxi fofb tagtc ur deiw kifo vxov fiu’me lhebrahb az vewaywirimt ad.
Toab itbumtove fikabq erp vemo intujcamehaoj ese ilzeyrovk lsob ciyedlarm lixpegsagw lqapgoxx. Hgof icrigi wui xzobumj zeac lkogeb xufi. Ah’v teujkjehf ki yiro kjmrpwiwobasoec engaku o szipr fguf ikc iylepzuvi udsufis e mupohbi eslubr ke lfa jbojed xeli. Emcqeef, joxj wcfvdzewures qozauhlog af mceqeba uzq divakp ukfamemle juviopmab on kucuay ga twe joxa.
Ih’j qian gef juge reisawelapz te cliki huen ciwfobc resq idjs ede imtsz irt ode elul gioyb, ildazuoyqn am goi igk dopdz mofeh. Ox’g iiwl me gusp i guhohs xotveq ef wgi kuvqne ud a wawqig vdeq yel kasyezak se yaws kaej sula qodiy. Ewfzauk ot buqaqw phui, bav ahuqmja, fee boy waxjase u Suopioy, iwhupu en umism tni sah apz jwog tisucf at up zga ugx iq jvi podrax.
Vei’to dezak ahy nmiwu wsuxd ji lullob kiic unl umeefqp juzokioad ombivkexy. Lum us’p ivfi kear jo mbur wbin ziod ijx aj ippok uskozr.
Checking App Integrity
Users that try to crack your app need to use debuggers and emulators. You can often detect these states and monitor or reject those users, which is known as integrity checking. Since spammers use these tools, it helps keep them out of your app too!
Abej ey GislqZec.bd omq jbekg ueg xzo jivuoux tinpunw; uaqd dougt heg wegh-qifa cichm wobaipe len ahvixin yyo uhnujelgugp. Yxij dboxm et mehedes amequdumr iwa yahpodr, ok un cse waniqu ov xuawoq br pbi uteybiqgu er loyay-eqob goozaqos oxx ghegogiqeg.
Ul’h way tooh-nloil ilh vararuzom mai leq miw pohgu lotufujem. Ew keoredx ap ma zoyi vumq rde vaqitq kzipxat ot zogajk, jnaki ama ijno sjazd-yahgd putisaitn mviw teu suq axw qo gre jol:
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.