feat: Semaine 13

This commit is contained in:
gauvainboiche
2026-09-04 17:25:11 +02:00
parent d0b00802d7
commit 1a3b11555b
44 changed files with 14807 additions and 31 deletions
+29
View File
@@ -0,0 +1,29 @@
# Exercice 06 - Gauvain
## Chaque action dans le bon environnement
NDR : Il est maintenant de coutume de fusionner les environnements "DEV" et "TEST" dans le seul environnement "DEV", qui sert de test également. Cela allège le déploiement des environnements et les ressources utilisées. Il se peut que les deux concepts se confondent un peu dans les réponses.
### A. Un développeur essaie une idée et casse tout trois fois de suite
> DEV et TEST
### B. La suite des test automatisés tourne après chaque envoi de code
> TEST, STAGING et PROD (avant déploiement)
### C. Le comptable vérifie que la facture PDF est conforme avant la mise en ligne
> TEST, STAGING et PROD (avant déploiement)
### D. Un test de charge à 800 utilisateurs simultanés
> STAGING. Optionnels : TEST et PROD
### E. Un pentest avec autorisation écrite
> Hors scope, il s'agit d'un projet hors pipeline de production pour un client, donc sur application déjà déployée. Sinon il est évident qu'un pentest se fait en STAGING et en PROD, mais pas besoin d'autorisation écrite, on travaille sur SON application
### F. Un vrai client paie une vraie facture
> PROD (après déploiement, hors tests. La vérification se fera par une remontée de journaux sur un moniteur)
@@ -0,0 +1,58 @@
# Exercice 07 - Adam, Louis, Gauvain
## Audit de sécurité d'un environnement de test
Trouver les 5 failles de sécurité dans ce `docker-compose.yml` :
```yaml
services:
app:
build: .
environnement:
DB_PASSWORD: "Sup3rSecret2024!"
APP_DEBUG: "true"
ports:
- "0.0.0.0:8080:8080"
db:
image: mysql:5.7
ports:
- "3306:3306"
volumes:
- ./dump_clients_prod.sql:/docker-entrypoint-initdb.d/init.sql
```
1. BD_PASSWORD en clair
2. APP_DEBUG en true, soit une journalisation totale potentiellement en clair
3. Port 8080 ouvert à 0.0.0.0, donc n'importe quelle machine dans le monde
4. Image mySQL HYPER obsolète, on est à la version 26
5. dump_clients_prod.sql. Il utilise la BDD de production pour faire des tests
## Supplément à l'exercice 01 - Corriger les failles
```yaml
services:
app:
build: . # avec un .dockerignore bien formaté
environnement:
DB_PASSWORD: ${DB_PASSWORD} # dans un .env bien écarté du .dockerignore et du .gitignore
APP_DEBUG: "false" # après on est dans un environnement de test, donc bon...
ports:
- "8080:8080"
db:
image: mysql:latest # ou une version 26 à minima, ça va dépendre de quelle version on a utilisé en DEV
ports:
- "3306:3306"
volumes:
- ./dump_clients_test.sql:/docker-entrypoint-initdb.d/init.sql
```
## Supplément à l'exercice 02 - Trouver des vecteurs d'attaque
(HackTricks sur MySQL)[https://hacktricks.wiki/en/network-services-pentesting/pentesting-mysql.html]
1. Se connecter sur le port 3306 à distance et tenter de lire des journaux en clair
2. Lire un éventuel dépôt de code en public (pour récupérer le mot de passe)
3. Regarder l'arborescence sur le port 8080
4. Vérifier les CVE avec Metasploit après un `nmap -sV`
@@ -0,0 +1 @@
3.14
@@ -0,0 +1,13 @@
```bash
uv init --python 3.14
uv add faker
```
```bash
winget update PHP.PHP.8.5
https://getcomposer.org/Composer-Setup.exe
```
```bash
C:\composer\composer require --dev fakerphp/faker
```
@@ -0,0 +1,5 @@
{
"require-dev": {
"fakerphp/faker": "^1.24"
}
}
+206
View File
@@ -0,0 +1,206 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "3929b7bfae922ea6b3da92aabf968467",
"packages": [],
"packages-dev": [
{
"name": "fakerphp/faker",
"version": "v1.24.1",
"source": {
"type": "git",
"url": "https://github.com/FakerPHP/Faker.git",
"reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5",
"reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0",
"psr/container": "^1.0 || ^2.0",
"symfony/deprecation-contracts": "^2.2 || ^3.0"
},
"conflict": {
"fzaninotto/faker": "*"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.4.1",
"doctrine/persistence": "^1.3 || ^2.0",
"ext-intl": "*",
"phpunit/phpunit": "^9.5.26",
"symfony/phpunit-bridge": "^5.4.16"
},
"suggest": {
"doctrine/orm": "Required to use Faker\\ORM\\Doctrine",
"ext-curl": "Required by Faker\\Provider\\Image to download images.",
"ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.",
"ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.",
"ext-mbstring": "Required for multibyte Unicode string functionality."
},
"type": "library",
"autoload": {
"psr-4": {
"Faker\\": "src/Faker/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "François Zaninotto"
}
],
"description": "Faker is a PHP library that generates fake data for you.",
"keywords": [
"data",
"faker",
"fixtures"
],
"support": {
"issues": "https://github.com/FakerPHP/Faker/issues",
"source": "https://github.com/FakerPHP/Faker/tree/v1.24.1"
},
"time": "2024-11-21T13:46:39+00:00"
},
{
"name": "psr/container",
"version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/container.git",
"reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963",
"reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
"shasum": ""
},
"require": {
"php": ">=7.4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common Container Interface (PHP FIG PSR-11)",
"homepage": "https://github.com/php-fig/container",
"keywords": [
"PSR-11",
"container",
"container-interface",
"container-interop",
"psr"
],
"support": {
"issues": "https://github.com/php-fig/container/issues",
"source": "https://github.com/php-fig/container/tree/2.0.2"
},
"time": "2021-11-05T16:47:00+00:00"
},
{
"name": "symfony/deprecation-contracts",
"version": "v3.7.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/f3202fa1b5097b0af062dc978b32ecf63404e31d",
"reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d",
"shasum": ""
},
"require": {
"php": ">=8.1"
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/contracts",
"name": "symfony/contracts"
},
"branch-alias": {
"dev-main": "3.7-dev"
}
},
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.1"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2026-06-05T06:23:12+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {},
"platform-dev": {},
"plugin-api-version": "2.9.0"
}
@@ -0,0 +1,8 @@
from faker import Faker
faker = Faker(["fr_FR", "it_IT", "en_UK"])
Faker.seed(2026)
for _ in range(20):
print(f"{faker.name()} - {faker.city()} - {faker.email()}")
@@ -0,0 +1,79 @@
"""EXERCICE 8 — Fabriquer un jeu de données de test.
python generer_clients.py
Cette version n'utilise AUCUNE dépendance : elle fabrique les données à la
main pour que l'exercice tourne partout. En entreprise, on utiliserait Faker :
pip install faker
from faker import Faker
faker = Faker("fr_FR")
Faker.seed(2026)
faker.last_name() faker.email() faker.city()
TROIS CHOSES À REMARQUER :
1. la graine est figée → même exécution = mêmes données
2. les e-mails sont en @example.org → domaine réservé, qui n'existe pas
3. des cas volontairement pénibles sont injectés → c'est là que ça casse
"""
import csv
import random
from pathlib import Path
GRAINE = 2026
NOMBRE_DE_CLIENTS = 500
random.seed(GRAINE) # 1. reproductibilité
NOMS = ["Martin", "Bernard", "Dubois", "Thomas", "Robert", "Petit", "Durand",
"Leroy", "Moreau", "Simon", "Laurent", "Michel", "Garcia", "David"]
PRENOMS = ["Camille", "Louis", "Léa", "Hugo", "Emma", "Nathan", "Chloé",
"Lucas", "Manon", "Enzo", "Inès", "Théo", "Jade", "Raphaël"]
VILLES = ["Lyon", "Périgueux", "Neuvic", "Bordeaux", "Lille", "Nantes",
"Strasbourg", "Toulouse", "Rennes", "Le Puy-en-Velay"]
# 3. Les cas pénibles : c'est là que les bugs se cachent.
CAS_PENIBLES = [
("O'Connor", "Sean", "Brest"),
("Nguyễn", "Anh", "Paris"),
("Vandenberghe-" * 8, "Jan", "Lille"),
("Müller", "Jörg", "Colmar"),
("Test 🙂", "Emoji", "Nice"),
]
clients = []
for i, (nom, prenom, ville) in enumerate(CAS_PENIBLES, start=1):
clients.append({
"id": i,
"nom": nom,
"prenom": prenom,
"email": f"client{i}@example.org", # 2. domaine réservé
"ville": ville,
"siret": f"{random.randint(0, 99999999):014d}",
})
for i in range(len(clients) + 1, NOMBRE_DE_CLIENTS + 1):
clients.append({
"id": i,
"nom": random.choice(NOMS),
"prenom": random.choice(PRENOMS),
"email": f"client{i}@example.org",
"ville": random.choice(VILLES),
"siret": f"{random.randint(0, 99999999):014d}",
})
sortie = Path(__file__).parent / "clients.csv"
with sortie.open("w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=list(clients[0]))
writer.writeheader()
writer.writerows(clients)
print(f"{len(clients)} clients générés dans {sortie}")
print("Relancez le script : le fichier sera strictement identique (graine figée).\n")
print("Aperçu des 5 cas pénibles :")
for c in clients[:5]:
print(f" {c['nom']:<30} {c['prenom']:<10} {c['email']}")
print()
@@ -0,0 +1,9 @@
[project]
name = "faker-project"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.14"
dependencies = [
"faker>=40.38.0",
]
+35
View File
@@ -0,0 +1,35 @@
version = 1
revision = 3
requires-python = ">=3.14"
[[package]]
name = "faker"
version = "40.38.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "tzdata", marker = "sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/f2/55/baeae0ecb04ef56c92d6ac1ef7b3b965af0502ac9863fc85db7afc0884fd/faker-40.38.0.tar.gz", hash = "sha256:72e421098664edf38478f4269a5d5a539337de5da18883ce67cb1e6bb96b0b3a", size = 2029190, upload-time = "2026-09-01T19:19:46.958Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f1/b8/48cb8733de8448023983f64e81d7f731ce1459c21e93b9b29657e5c48cab/faker-40.38.0-py3-none-any.whl", hash = "sha256:69927515d61759c8a257540b8a91891cd622ba1c24a386b62a0a777e44ba46a9", size = 2065931, upload-time = "2026-09-01T19:19:45.234Z" },
]
[[package]]
name = "faker-project"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "faker" },
]
[package.metadata]
requires-dist = [{ name = "faker", specifier = ">=40.38.0" }]
[[package]]
name = "tzdata"
version = "2026.3"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/92/ff/5a28bdfd8c3ebec42564ac7d0e54ca3db65044a9314a97f9564fa7a1e926/tzdata-2026.3.tar.gz", hash = "sha256:4a1518b8993086a7982523e071643f3c0e5f213e75b21318e78bcabfff9d1415", size = 198674, upload-time = "2026-07-10T08:50:37.887Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e5/6d/b53b99a9f2766d095985947a5782f1702cabb129a34f7a802d7197af832f/tzdata-2026.3-py2.py3-none-any.whl", hash = "sha256:dc096730c87af6cab1b171c9d532be840741ff5d459015e7f6947bd7d7e54931", size = 348168, upload-time = "2026-07-10T08:50:36.46Z" },
]