feat: Semaine 13
This commit is contained in:
@@ -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
@@ -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",
|
||||
]
|
||||
Generated
+35
@@ -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" },
|
||||
]
|
||||
Reference in New Issue
Block a user