https://grunk.github.io/sec_dev/
Olivier ROGER
Développeur & Architecte @ Pryntec
+15 XP
Expert PHP, Senior Android, JS, C++, SQL, etc ...
Dév web, Informatique industrielle, vidéo surveillance, ...
En ligne : oroger.fr / grunk @ dvp | stackoverflow | github
Sécurité
=
A SEISMIC SHIFT IN APPLICATION SECURITY - Gitlab
On veux tout tester mais ... | Donc on ... | Mais ... |
---|---|---|
Pas les moyens | test uniquement ce qu'on pense à risque | les attaquants peuvent naviguer horizontalement |
Manque d'expert | se repose sur des tests externes ponctuels | Les exploits évoluent très vite |
Déjà trop à corriger | réduits les tests | De multiples test permettent de trouver différents type d'exploits |
Liste des risques
Conception sûre
Analyse statique (white box)
Test auto, CI/CD
Audit (black box)
Monitoring
Prévention + Analyse des correctifs
DEVOPS
Ajout des notions de sécurité dans un process de développement
Ex : écrire les contraintes sécuritaires en même temps que le besoin fonctionnel
Déterminer les données à protéger
Déterminer le type d'attaquant
Connaitre son environnement
Ex : Facebook et Impots.gouv.fr
Sécurité de l'information
Architecture
10 principes de sécurité
Connexion identifiant / mot de passe
Email de confirmation
Récupération de mot de passe
Connexion "permanente"
Page de login
"White box testing"
Tests unitaires
public function testPasswordSize()
{
$login = new Login();
$tooShort = 'toto';
$tooWeak = 'jesuisunmotdepasse';
$ok = 'Je$u!5u|\|M0†d3P4$$e';
$this->boolean($login->checkPassword($tooShort))->isFalse();
$this->boolean($login->checkPassword($tooWeak))->isFalse();
$this->boolean($login->checkPassword($ok))->isTrue();
}
Failles internes
public function testDateOutput()
{
$date = '2019-11-11 10:00:00';
$util = new DateFormatter();
$this->string($util->format($date,'d/m/Y'))
->isEqualTo('11/11/2019');
}
Validité des outputs
public function testLoop()
{
$looper = new MyObj();
$array = $looper->GenerateDatas(10);
$this->integer(count($array))
->isEqualTo(10);
}
Boucle conditionnelle
Améliorer le test coverage
Standard
ASVS
Evaluer
Extraire
Règles pour un standard sécurisé
Outils
Revue de code
int MyClass::MySuperNewFeature() {
auto obj = new MyObject();
int r = obj->GetResult();
return r;
}
Merge/Pull Request = code review
Intégration
int MyClass::MySuperNewFeature() {
auto obj = new MyObject();
int r = obj->GetResult();
delete obj;
return r;
}
"Fuite mémoire"
/**
* @brief Super fonctionnalité
*/
int MyClass::MySuperNewFeature() {
auto obj = new MyObject();
int r = obj->GetResult();
delete obj;
return r;
}
"Documentation"
Black box testing
Externe
Interne
Processus qui aide à concevoir et implémenter des logiciels qui protègent les données qu'ils manipulent
Pour qui ?
Résumé
Quelques stats
Gouvernance
Stratégie et métrique
Conformité
Formation
Construction
Exigences en matière de sécurité
Évaluation de la menace
Architecture sécuritaire
Vérification
Design review
Revue de code
Test de sécurité
Déploiement
Gestion des vulnérabilités
Durcissement de l’environnement
Operational enablement
Comment démarrer
SAMM Assessment toolbox
Roadmap
Work !
Exercice : EG 0 à EG3
https://opensamm.org/downloads/SAMM-1.0-en_US.pdf
Client
Serveur
"je suis : xxxx"
"Données de : xxxx"
Attaquant
Client
Serveur
Attaquant
Donnée
secrète
Chiffrement
Déchiffrement
TUNNEL
Client
Serveur
Attaquant
1€
100€
100€
Signature
bc32a
af44
bc32a != af44
Client
Attaquant
1€
Serveur
Compartimenter
App 1
R
App 2
RW
App 2
RW+Admin
UserApp1
UserApp2
UserApp3
UserAdmin
Architecture
App distante
Webservice
Offline
Journalisation
En vrac
Introduction
SELECT password FROM users WHERE login = 'admin'
$user = $_POST['user'];
$req = 'SELECT password FROM users WHERE login = '.$user
Injection impossible
Risque d'injection
Contournement d'une identification
$login = $_GET['login'];
$password = $_GET['password'];
$query = '
SELECT id, login
FROM users
WHERE login = '.$login.' AND password ='.$password;
Contournement d'une identification
http://monsite.com/connect?login=admin&password=12345
SELECT id, login
FROM users
WHERE login = 'admin' AND password ='12345';
password=unknown' or '1'='1
SELECT id, login
FROM users
WHERE login = 'admin' AND password ='unknown' or '1'='1;
Accès autorisé !
http://oroger.fr/labs/injection/
Contournement d'une identification
SELECT id, login
FROM users
WHERE login = 'unknown' or '1'='1' AND password = 'unknown' or '1'='1';
login = unknown' or '1'='1
password = unknown' or '1'='1
Extraction de données
SELECT info,... FROM activites WHERE user_id = 1
http://monsite.com/list?id=1
SELECT info,... FROM activites WHERE user_id = 1 UNION SELECT username, password FROM users
Vol de toute la liste des utilisateurs et mots de passe
UNION SELECT username, password FROM users
Backdoor
SELECT info,... FROM activites WHERE user_id = 1
SELECT info,aff FROM activites WHERE user_id = 1
UNION
SELECT null,'ici du code dangereux'
INTO OUTFILE '/var/www/backdoor.php'
http://monsite.com/backdoor.php
Protection
2 solutions possibles :
Requêtes préparées
Requêtes préparées : principe
SELECT id, login
FROM users
WHERE login = $1 AND password = $2;
PREPARE
BIND ('admin')
BIND ('12345')
EXECUTE()
Requêtes préparées : injection
SELECT id, login
FROM users
WHERE login = $1 AND password = $2;
PREPARE
BIND ("admin'#")
BIND ('12345')
SELECT id, login
FROM users
WHERE login = "admin'#" AND password ="12345";
Risques
Solutions
Saisie de données innatendues
Crash application
Comportements aléatoires
Validation de saisie
cast,filtre,regex ...
$email = filter_var($email, FILTER_VALIDATE_EMAIL);
const regex = /^((\+|00)33\s?|0)[67](\s?\d{2}){4}$/;
if ((m = regex.exec(str)) !== null) {
// OK
}
Vol de données (xss)
Saisie de données innatendues
Validation serveur uniquement !
Aucune donnée n'est sûre
Mot de passe , clé de chiffrement, clé API, données sensibles
Risques
Solutions
Usurpation d'identité
Vol de données
Prise de contrôle
Obfuscation
Délocaliser*
Exemple
std::string codeSecret = "MYPassword";
[...]
if(login == codeSecret) {
DisplayAdminWindow();
}
Quelles solutions ?
isAdmin = true;
try {
codeWhichMayFail();
isAdmin = isUserInRole( “Administrator” );
}
catch (Exception ex) {
log.write(ex.toString());
}
Utiliser des chiffrements ou hash fort.
https://blog.codinghorror.com/your-password-is-too-damn-short/
Exercice : trouver la valeur de : d0763edaa9d9bd2a9516280e9044d885
const num = 5;
num.isNaN();