Plan :
Pas le mien :-/
Danger: toute entrée de donnée
Cf. http://php.net/manual/fr/security.database.sql-injection.php
code PHP
<?php
$id = $_GET['id'];
$sql = "SELECT username
FROM users
WHERE id = $id";
...
requête envoyée à :
http://localhost/?id=-1%20UNION%20SELECT%20password%20FROM%20users%20where%20id=1
argument de la requête GET :
id : -1 UNION SELECT password FROM users where id=1
Induire l’exécution de transition dans le graphe d’états de l’application en jouant des requêtes à l’insu de l’utilisateur.
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)
Source : https://www.wallarm.com/what/what-is-cross-site-request-forgery
Exemple de transaction sur site banque : virement de 100 euros à destination d’olivier :
POST http://bank.com/transfer.do HTTP/1.1 acct=olivier&amount=100
Objectif : faire exécuter ce formulaire à l’insu de l’utilisateur :
<form action="http://bank.com/transfer.do" method="POST">
<input type="hidden" name="acct" value="philippe"/>
<input type="hidden" name="amount" value="100000"/>
<input type="submit" value="View my pictures"/>
</form>
Exemple de page :
<?php
echo '<html>';
// ...
echo $_POST["name"];
Requête POST : injection de name
qui vaut
name=%3Cscript%3Ealert%2842%29;%3C/script%3E
Résultat :
<script>alert(42);</script>
Tout dépend où se trouve le echo
…
Solution possible :
<?php
echo '<html>';
// ...
echo htmlentities($_POST["name"]);
Résultat :
<html>
...
<script>alert(42);</script>
Normalement, c’est plus sûr…
Le framework permet de gérer automatiquement certaines précautions
On ne manipule pas SQL directement.
On ne manipule pas HTML directement
Protection CSRF
Objectif : éviter d’arriver sur la soumission d’un formulaire directement, contrôler les transitions dans le graphe HATEOS
Figure 1 : Identifying Legitimate Requests with an CSRF Token
_token
en Symfony)Construction du formulaire :
stockage dans la session
Session Attributes _csrf/post : "RfofubWU_auc33Mef-EdbvVlHOBh5J1561Z9rJ_FJ5I"
génération du formulaire envoyé au client
<form>
...
<input type="hidden" id="post__token"
name="post[_token]"
value="RfofubWU_auc33Mef-EdbvVlHOBh5J1561Z9rJ_FJ5I" />
</form>
Réception de la requête POST :
données du POST
[▼ "title" => "Lorem Ipsum" "summary" => "" "content" => "Lorem Ipsum" "publishedAt" => "2017-11-26T20:07:34+01:00" "tags" => "" "_token" => "RfofubWU_auc33Mef-EdbvVlHOBh5J1561Z9rJ_FJ5I" ]
code du contrôleur (dans isValid()
) :
if ($this->isCsrfTokenValid('token_id', $submittedToken)) {
// ...
}
Sécurité des dépendances ?
S’abonner à des listes de notification de vulnérabilités, pour être notifié des alertes (CVE).
.onion
)déjà vu
Approfondir :
Figure 2 : HTTP Headers FTW (CommitStrip)
HTTP Headers FTW par CommitStrip
throw new OutOfBoundsException("not good");
try {
...
} catch (RequestException $e) {
...
}
Checklists : https://symfony.com/doc/current/deployment.html
PHPUnit
Vraiment ?
Tester de bout en bout, systématiquement :
public function testPageIsSuccessful($url)
{
$client = self::createClient();
$client->request('GET', $url);
$this->assertTrue($client->getResponse()->isSuccessful());
}