Disseny segur

La seguretat ha de ser una preocupació, no una funcionalitat.

Criteris de disseny

Aquesta és una llista de possibles criteris a tenir en compte per a dissenyar codi segur:

  • El menor privilegi: una entitat només ha de tenir el conjunt necessari de permisos per realitzar les accions per a les quals estiguin autoritzades, i cap altre més.
  • Fail-Safe per defecte: el nivell d’accés predeterminat d’un usuari a qualsevol recurs del sistema hauria de ser "denegat" a menys que se'ls concedís un "permís" explícitament.
  • Economia del mecanisme: el disseny ha de ser el més simple possible. Això els fa més fàcils d'inspeccionar i confiar.
  • Mediació completa: un sistema ha de validar els drets d’accés a tots i cadascun dels seus recursos.
  • Disseny obert: els sistemes s'han de construir de forma oberta, sense secrets ni algorismes confidencials.
  • Separació de privilegis: la concessió de permisos a una entitat ha de basar-se en múltiples condicions, no només una.
  • Mecanisme menys comú: qualsevol cosa que es comparteixi entre diferents components pot ser una via de comunicació i un potencial forat de seguretat, i per tant s'han de compartir les dades mínimes possibles.
  • Acceptabilitat psicològica: els mecanismes de seguretat no haurien de fer més difícil l'accés al recurs que si no hi fossin.
  • Responsabilitat: el sistema ha de registrar qui és responsable d'utilitzar un privilegi. Si hi ha abús, podrem identificar el responsable.

Pràctiques de codificació

Aspectes tècnics que potencien la seguretat del codi:

  • Immutabilitat: ens podem estalviar problemes associats a la integritat i disponibilitat de les dades.
  • Disseny fail-fast per contractes: establint clarament quines són les precondicions i postcondicions perquè quelcom funcioni correctament.
  • Validació: validem l'origen, la mida, el context, la sintaxi i semàntica de les dades que interactuen amb el sistema. Hi ha llibreries que ajuden a aquesta tasca, com la Commons Validator.

Pràctiques a Java

  • Utilitza correctament els modificadors d'accés i redueix al màxim l'acoblament (API mínima).
  • Evita serialització, reflection i introspection.
  • No exposis credencials o informació personal, ni l'emmagatzemis al codi font o a arxius de recursos: utilitza l'entorn.
  • Utilitza llibreries conegudes i testades, segueix les vulnerabilitats de dependències de tercers i actualitza a l'última versió.
  • Utilitza sempre prepared statements (evita SQL injection).
  • No mostris informació de la implementació als missatges d'error.
  • Controla que l'entrada al sistema no causi ús desproporcionat de CPU, memòria i espai de disc.
  • Allibera els recursos sempre: fitxers, memòria, etc.
  • Comprova que no es produeixen overflows a tipus primitius, com integer (pots utilitzar addExact, multiplyExact, decrementExact de java.lang.Math).

Eines d'anàlisi

Tenim eines dinàmiques (que executen el codi) i estàtiques (analitzen el codi sense executar-lo).

Dinàmic:

  • Integration and unit testing: cal dissenyar proves d'integració i unitàries al codi. A Java, tenim JUnit.
  • Code coverage: eines que serveixen per detectar quin codi s'ha executat o no, i decidir si hem d'afegir test cases. Tenim una eina de coverage a Eclipse (Java), per exemple.

Estàtic:

  • Static code analysis: permet fer anàlisi de la qualitat del codi que hem escrit, amb la detecció dels errors semàntics més habituals del llenguatge. A Java, podem utilitzar SpotBugs i les seves dues extensions, fb-contrib i find-sec-bugs.

Top 10 de controls proactius

Segons OWASP 2024, aquest és el TOP 10 dels controls que hauria de fer un desenvolupador:

  1. Implementar control d'accés. Cal permetre o denegar l'accés de forma granular i per a totes les peticions. Criteris: denegar per defecte, el privilegi menor, evitant rols hardcoded, i registrant els esdeveniments.
  2. *Utilitzar criptografia per a protegir les dades. Mai s'han de transmetre ni emmagatzemar dades sensibles en format pla. Cal utilitzar protocols coneguts amb pràctiques implementades a llibreries que estiguin al dia.
  3. Validar totes les entrades i gestionar excepcions. Fa el teu codi més segur i confiable. A més, els errors poden permetre detectar intents d'atac. Fes registre, i si mostres alguna cosa a l'usuari, que no contingui dades crítiques.
  4. Gestionar la seguretat des del començament. Integrar consideracions de seguretat en totes les fases del desenvolupament del programari per evitar la introducció de vulnerabilitats des del principi.
  5. Configurar la seguretat per defecte. Assegurar que el programari es desplega amb configuracions de seguretat robustes, minimitzant els riscos per defecte.
  6. Mantenir els components segurs. Actualitzar i gestionar correctament les llibreries i components utilitzats per evitar vulnerabilitats derivades de versions obsoletes o insegures.
  7. Identitats digitals segures. Hem de verificar la identitat de l'usuari (autenticació), i potser mantenir el seu estat (gestió de la sessió). Ho podem fer amb contrasenyes, amb múltiples factors i amb criptografia.
  8. Aprofitar les funcionalitats segures del navegador. Utilitzar les característiques integrades en els navegadors, com ara controls de contingut i polítiques de seguretat, per reforçar la protecció del costat client.
  9. Implementar el registre i monitoratge de la seguretat. Utilitzar sistemes de detecció d'intrusos, fer anàlisi forensic i implementar regulacions normatives.
  10. Refusar les sol.licituds falses de servidor (SSRF). Mitigar els riscos associats amb la capacitat d’un atacant per forjar peticions des del servidor, protegint així el sistema de possibles abusos.

Top 10 d'atacs

Segons el top 10 d'OWASP al 2021:

  1. Pèrdua del control d'accés: Les restriccions sobre el que els usuaris autenticats poden fer no s'apliquen correctament. Els atacants poden explotar aquests defectes per accedir, de forma no autoritzada, a funcionalitats i / o dades, comptes d'altres usuaris, veure arxius sensibles, modificar dades, canviar drets d'accés i permisos, etc.
  2. Exposició de dades sensibles: Moltes aplicacions web i APIs no protegeixen adequadament dades sensibles, com ara informació financera, de salut o Informació Personalment Identificable (PII). Els atacants poden robar o modificar aquestes dades protegides inadequadament per dur a terme fraus amb targetes de crèdit, robatoris d'identitat o altres delictes. Les dades sensibles requereixen mètodes de protecció addicionals, com el xifrat en emmagatzematge i trànsit.
  3. Injecció: Les falles d'injecció, com SQL, NoSQL, US o LDAP ocorren quan s'envien dades no fiables a un intèrpret, com a part d'un comando o consulta. Les dades nocives de l'atacant poden enganyar a l'intèrpret perquè executi ordres involuntaris o accedeixi a les dades sense la deguda autorització.
  4. Disseny insegur: la manca d’un disseny que integri principis de seguretat des del començament deixa l’aplicació més vulnerable a futurs atacs.
  5. Configuració incorrecta de seguretat: La configuració de seguretat incorrecta és un problema molt comú i es deu en part a establir la configuració manualment, ad hoc o per omissió (o directament per la falta de configuració). Són exemples: S3 buckets oberts, capçaleres HTTP mal configurades, missatges d'error amb contingut sensible, manca de pegats i actualitzacions, frameworks, dependències i components desactualitzats, etc.
  6. Utilització de components amb vulnerabilitats: Els components com biblioteques, frameworks i altres mòduls s'executen amb els mateixos privilegis que l'aplicació. Si s'explota un component vulnerable, l'atac pot provocar una pèrdua de dades o prendre el control del servidor. Les aplicacions i API que utilitzen components amb vulnerabilitats conegudes poden afeblir les defenses de les aplicacions i permetre diversos atacs i impactes.
  7. Trencament de l'autenticació: Les funcions de l'aplicació relacionades a autenticació i gestió de sessions són implementades incorrectament, permetent als atacants comprometre usuaris i contrasenyes, token de sessions, o explotar altres falles d'implementació per assumir la identitat d'altres usuaris (temporal o permanentment).
  8. Software and Data Integrity Failures: L’absència de mecanismes que verifiquin la integritat del codi i de les dades pot conduir a manipulacions malicioses.
  9. Registre i monitorització insuficients: El registre i monitorització insuficient, al costat de la manca de resposta davant incidents permeten als atacants mantenir l'atac en el temps, pivotear a altres sistemes i manipular, extreure o destruir dades. Els estudis mostren que el temps de detecció d'una bretxa de seguretat és major a 200 dies, sent típicament detectat per tercers en lloc de per processos interns.
  10. Server-Side Request Forgery (SSRF): aquesta vulnerabilitat permet a un atacant forjar peticions des del servidor cap a altres sistemes, exposant serveis interns o externs.