Aller au contenu

L'application trouée : l'installer, trois comptes, les règles du jeu, les tests rouges

Temps 2 · séance 1 · ~35 min

Les slides du chapitre (PDF)PDF

  • Installer le Tamagotchi troué sur votre machine et l'ouvrir à l'adresse tamagotchi.test.
  • Parcourir ses pages et nommer les modèles qu'elles utilisent.
  • Vous connecter comme Mallory et comme Alice en même temps, dans deux fenêtres.
  • Lancer les tests et lire combien de tests rouges chaque faille porte.
  • Décrire la méthode qui se répète à chaque faille et tenir le carnet des failles.

1. Ce que vous recevez

Votre portfolio est un site que vous avez construit page par page. Cette fois, vous ne construisez rien. Vous recevez une application entière, le Tamagotchi troué : un petit jeu où chaque joueur adopte des créatures, les nourrit, visite l'enclos des autres et achète au magasin.

Le jeu fonctionne. Il est aussi percé de failles de sécurité, mises là exprès. Une faille est une erreur dans le code qui permet à quelqu'un de faire ce que le site devrait lui refuser : lire les données d'un autre joueur, modifier son solde, payer un objet un centime. Pour chaque faille, vous allez comprendre le danger, refaire l'attaque sur votre copie, puis corriger le code.

Mallory est le compte qui sert aux attaques. Alice est celle dont elle vise les créatures et les données. Les deux séances suivent ce sommaire. La séance 1 porte sur la question « qui a le droit ? », la séance 2 sur l'argent.

Chapitre Ce qui s'y passe
2.02 Changer le numéro dans l'adresse elle ouvre et modifie la créature d'un autre joueur
2.03 Un champ de trop dans le formulaire elle ajoute un champ à un formulaire et change son solde
2.04 Tout ce que la page reçoit est public elle lit des données que la page n'affiche pas
2.05 Du code dans un message elle laisse un message qui agit chez celui qui le lit
2.06 Une recherche qui lit toute la base elle tape une recherche qui lit la table des joueurs
2.07 Un float n'est pas un montant aucune attaque : un calcul tombe à côté du bon montant
2.08 Le prix ne vient jamais du navigateur elle choisit elle-même le prix de ce qu'elle achète
2.09 Deux achats en même temps, un seul solde elle dépense deux fois le même argent
2.10 Essayer mille fois elle essaie tous les codes cadeau un par un
2.11 Avant de mettre en ligne les réglages qui trahissent un site en ligne
2.12 Le bilan tous les tests au vert, le carnet des failles

Ces erreurs de sécurité et de calcul, vous pouvez aussi les rencontrer dans votre portfolio. Le carnet des failles de la section 8 vous y renvoie. Le projet en binôme qui suit ces deux séances repart lui aussi de ces règles : ses pages d'administration auront besoin du contrôle d'accès du chapitre 2.02.

2. Installer l'application

Le jeu est sur GitHub, dans le dépôt du cours opmvpc/tamagotchi-troue-26. Vous n'y travaillez pas directement : vous en faites d'abord un fork. Un fork est une copie d'un dépôt dans votre propre compte GitHub, où vous pouvez envoyer vos commits. Votre compte, vous l'avez déjà : vous y avez envoyé votre portfolio au chapitre 1.04.

Connecté à votre compte, ouvrez la page https://github.com/opmvpc/tamagotchi-troue-26. Cliquez sur le bouton « Fork » en haut de la page, puis sur « Create fork ». GitHub crée le dépôt votre-compte/tamagotchi-troue-26 et vous l'affiche.

Placez-vous ensuite dans le dossier que Herd ou Laragon rend accessible, comme au chapitre 1.04 : ~/Herd sous macOS, C:\laragon\www sous Windows. Clonez votre fork dans un dossier nommé tamagotchi, en remplaçant votre-compte par le nom de votre compte GitHub :

git clone https://github.com/votre-compte/tamagotchi-troue-26 tamagotchi
cd tamagotchi

Le dernier mot de la commande git clone donne son nom au dossier. Herd et Laragon en tirent l'adresse du site : le dossier tamagotchi sera servi à l'adresse tamagotchi.test.

Votre dossier est relié à votre fork. À la fin du temps 2, git push y enverra vos corrections.

Un dépôt cloné ne contient ni les paquets PHP, ni les paquets JavaScript, ni le fichier .env, ni la base. Le fichier .gitignore les écarte de Git, comme dans votre portfolio. Installez d'abord les paquets PHP :

composer install
Installing dependencies from lock file (including require-dev)
Verifying lock file contents can be installed on current platform.
Package operations: 175 installs, 0 updates, 0 removals
…
122 packages you are using are looking for funding.
Use the `composer fund` command to find out more!

composer install lit composer.lock et installe exactement les versions que ce fichier liste, dans le dossier vendor/.

Copiez ensuite le fichier d'exemple de la configuration, puis générez la clé de chiffrement de l'application. Dans PowerShell comme dans le terminal de macOS :

cp .env.example .env
php artisan key:generate
 INFO Application key set successfully.

Ouvrez .env et remplacez APP_URL=http://localhost:8000 par l'adresse de votre copie :

APP_URL=http://tamagotchi.test

Créez la base et remplissez-la :

php artisan migrate:fresh --seed
 INFO Preparing database.

 Creating migration table .. 11.37ms DONE

 INFO Running migrations.

 0001_01_01_000000_create_users_table .. 27.60ms DONE
 …
 …_create_creatures_table .. 9.20ms DONE
 …_create_items_table .. 5.60ms DONE
 …_create_purchases_table .. 6.92ms DONE
 …_create_messages_table .. 5.13ms DONE
 …_create_gift_codes_table .. 8.81ms DONE

 INFO Seeding database.

Le fichier database/database.sqlite n'existait pas. migrate:fresh l'a créé sans rien demander. Retenez cette commande : elle efface la base et la remplit à nouveau avec les données du seeder. Après une attaque qui a tout cassé, elle vous rend un jeu neuf.

Installez les paquets JavaScript, puis lancez les programmes de développement dans un second terminal, comme au chapitre 1.04 :

npm install
composer run dev
[server] php artisan serve
[queue] php artisan queue:listen --tries=1 --timeout=0
[vite] npm run dev
…
[vite] … [vite+] (client) info: Types generated for actions, routes, form variants
…
[vite] VITE+ v1.4.0 ready in 7582 ms
…
[vite] LARAVEL v13.42.0 plugin v3.2.1

La ligne Types generated for actions, routes, form variants vient de Wayfinder. Les dossiers resources/js/routes/ et resources/js/actions/ ne sont pas dans le dépôt : Wayfinder les génère au lancement. Un message [laravel:fonts] qui parle du paquet fontaine peut suivre : il ne vous concerne pas.

Ouvrez http://tamagotchi.test. La page d'accueil du jeu s'affiche.

Astuce

Le fichier composer.json déclare aussi un script composer run setup. Il enchaîne composer install, la copie de .env, la clé, migrate --force, npm install et npm run build. Il ne lance pas le seeder : sans migrate:fresh --seed ensuite, la base n'a aucun joueur. Suivez plutôt les commandes de cette section, dans l'ordre.

3. Le tour du jeu

Connectez-vous avec l'adresse alice@example.com et le mot de passe password. Vous arrivez sur /dashboard, la page « Mon tamagotchi ».

La page Mon tamagotchi d'Alice : en haut, le menu 01 Mon tamagotchi, 02 Enclos, 03 Classement, 04 Magasin et le solde de 120 €. Au centre, la fiche n° 001 de Braise, un dragon, avec ses jauges Nourriture 90, Humeur 95 et Énergie 80, sous le titre la phrase « Pas d'inventaire : un article acheté au magasin est donné aussitôt à la créature choisie, et sa jauge monte tout de suite, sans dépasser 100. », et un boîtier rose avec les touches Magasin, Jouer et Dodo. En bas, la pellicule Mes créatures avec Braise et Moustache

Chaque créature a trois jauges de 0 à 100 : nourriture, humeur, énergie. Le boîtier porte trois touches. « Jouer » remonte l'humeur, « Dodo » recharge l'énergie, « Magasin » ouvre le magasin. Il n'y a pas d'inventaire : un article acheté au magasin est donné aussitôt à la créature choisie, et sa jauge monte tout de suite, sans dépasser 100. La pellicule « Mes créatures » choisit la créature affichée. Le lien « Modifier la fiche » ouvre /creatures/1/modifier, où Alice renomme ou relâche Braise. Le numéro 1 dans l'adresse est l'id de Braise, celui que la page affiche aussi en « Fiche n° 001 ».

En haut à droite, le solde : l'argent du jeu de la personne connectée. Alice a 120 €.

L'enclos est la page d'un joueur que tous les joueurs connectés peuvent visiter, à l'adresse /enclos/{user}. Il montre sa devise, ses créatures et son livre d'or. Le lien « 02 Enclos » ouvre le vôtre, où vous pouvez changer votre devise. Pour visiter celui d'un autre joueur, cliquez sur son nom dans le classement. Voici l'enclos d'Alice, visité par Mallory :

L'enclos n° 001 d'Alice vu par Mallory, dont le solde affiche 5 € : la devise « Un enclos propre, des créatures heureuses. », les vignettes de Braise et de Moustache avec leurs jauges, et à droite le livre d'or avec le message de Bob « Braise est magnifique, bravo ! » et le formulaire Laisser un message, sous lequel est écrit « Le gras est permis : <b>comme ceci</b>. »

Le livre d'or garde les messages laissés par les visiteurs. Bob y a écrit le premier.

Le classement, à /classement, range les créatures de tous les joueurs par points. Les points d'une créature sont la somme de ses trois jauges.

Le classement Les plus heureuses : sur le podium, Braise d'Alice avec 265 points, Moustache d'Alice avec 215 et Noisette de Bob avec 210, et sous le podium le titre Suite du classement

Le magasin, à /magasin, vend sept articles. Chaque article remonte une jauge. Vous choisissez la créature qui le reçoit et la quantité, puis vous cliquez sur « Acheter », et le prix est retiré de votre solde. Une recherche filtre les articles par nom. En bas de la page, un champ accepte un code cadeau de quatre chiffres, qui crédite votre solde.

Le haut du magasin : la recherche « Chercher un article », puis trois annonces, la Balle rebondissante à 3.2 €, la Boisson vitaminée à 4.5 € et le Bonbon à 0.1 €, chacune avec son effet, son stock, le choix de la créature, la quantité et le bouton Acheter

Derrière ces pages, six modèles. Le schéma relie chaque page aux modèles qu'elle utilise, d'après routes/web.php et les contrôleurs. Le magasin, par exemple, lit les articles et vos créatures. L'achat et le code cadeau, eux, écrivent dans Purchase et GiftCode.

Les six pages du jeu, chacune avec son adresse et les modèles qu'elle lit. Mon tamagotchi, à /dashboard, Adopter, à /creatures/nouvelle, et la Fiche d'une créature, à /creatures/{creature}/modifier, lisent Creature. L'Enclos, à /enclos/{user}, lit User, Creature et Message. Le Classement, à /classement, lit Creature et User. Le Magasin, à /magasin, lit Item et Creature, et écrit Purchase et GiftCode

Modèle Ce qu'il représente
User un joueur, avec sa devise (motto) et son solde (balance)
Creature une créature d'un joueur, avec ses trois jauges
Message un message du livre d'or
Item un article du magasin
Purchase un achat
GiftCode un code cadeau

Les migrations du dossier database/migrations/ donnent les colonnes de ces modèles et leurs liens. Le diagramme de classes se lit en deux parties. La première montre le joueur, ses créatures et son livre d'or.

@startuml
class User {
  +name: string
  +email: string
  +password: string
  +motto: string [0..1]
  +balance: float
  +creatures: Creature [0..*]
  +writtenMessages: Message [0..*]
  +receivedMessages: Message [0..*]
}

class Creature {
  +name: string
  +species: string
  +food: int
  +mood: int
  +energy: int
  +user: User [1]
}

class Message {
  +body: string
  +author: User [1]
  +recipient: User [1]
}

User "1 +user" *-- "0..* +creatures" Creature : possède >
User "1 +author" -- "0..* +writtenMessages" Message : écrit >
User "1 +recipient" *-- "0..* +receivedMessages" Message : reçoit >
@enduml

Le losange plein {uml:composition} entre User et Creature se lit ainsi : un joueur possède zéro, une ou plusieurs créatures, et une créature a un seul propriétaire, avec qui elle disparaît. Dans la migration, la clé user_id porte cascadeOnDelete().

Un message a deux liens vers User, donc deux traits. author est le joueur qui l'écrit, recipient celui dont le livre d'or le garde. Le message disparaît avec le livre d'or de son destinataire, d'où le second losange plein. La base efface aussi les messages d'un auteur supprimé, mais une partie n'entre que dans une seule composition : le lien vers l'auteur reste un trait simple {uml:association}.

La seconde partie montre le magasin. User et Creature n'y répètent pas les attributs de la première.

@startuml
class GiftCode {
  +code: string
  +amount: float
  +redeemed_at: datetime [0..1]
  +redeemer: User [0..1]
}

class User {
  +creatures: Creature [0..*]
  +purchases: Purchase [0..*]
  +redeemedCodes: GiftCode [0..*]
}

class Creature {
  +user: User [1]
  +purchases: Purchase [0..*]
}

class Purchase {
  +quantity: int
  +total: float
  +user: User [1]
  +item: Item [1]
  +creature: Creature [1]
}

class Item {
  +name: string
  +description: string
  +effect: string
  +effect_value: int
  +price: float
  +stock: int
  +purchases: Purchase [0..*]
}

User "0..1 +redeemer" o-- "0..* +redeemedCodes" GiftCode : utilise >
User "1 +user" *-- "0..* +creatures" Creature : possède >
User "1 +user" *-- "0..* +purchases" Purchase : effectue >
Purchase "0..* +purchases" -- "1 +creature" Creature : profite à >
Purchase "0..* +purchases" -- "1 +item" Item : porte sur >
@enduml

Un achat relie trois modèles : le joueur qui l'effectue, l'article qu'il achète et la créature qui en profite. Il disparaît avec le joueur, d'où le losange plein. Les liens vers l'article et la créature restent des traits simples, pour la même raison que l'auteur d'un message.

Le losange vide {uml:agregation} entre User et GiftCode dit l'inverse : un code cadeau survit au joueur qui l'a utilisé. Sa colonne redeemed_by reste vide tant que personne ne l'a utilisé, d'où le 0..1, et redevient vide si ce joueur est supprimé.

4. Trois comptes, deux fenêtres

Le seeder crée trois joueurs. Le mot de passe de chacun est password.

Compte Adresse Rôle Au départ
Alice alice@example.com la victime 120 €, Braise et Moustache
Mallory mallory@example.com l'attaquante 5 €, Encre
Bob bob@example.com un joueur de plus 0,30 €, Roux et Noisette

Une attaque se joue presque toujours à deux. Mallory agit, et le résultat se voit chez Alice : sa créature renommée, son enclos changé. Pour voir les deux côtés, il faut être connecté deux fois en même temps.

Un navigateur garde un cookie de session par site, c'est-à-dire un petit fichier qui dit au serveur quelle session vous appartient. Deux onglets ordinaires partagent ce cookie : vous connecter comme Alice dans le second déconnecterait Mallory dans le premier. Une fenêtre de navigation privée a ses propres cookies.

Prenez cette habitude dès maintenant, elle revient à chaque chapitre.

  1. Dans une fenêtre normale, connectez-vous comme Mallory.
  2. Ouvrez une fenêtre de navigation privée : Ctrl+Maj+N dans Chrome et Edge, Ctrl+Maj+P dans Firefox, Cmd+Maj+N dans Safari.
  3. Dans cette fenêtre, ouvrez tamagotchi.test/login et connectez-vous comme Alice.

Deux fenêtres du navigateur ouvrent tamagotchi.test, votre copie sur votre machine. La fenêtre normale est connectée comme Mallory, l'attaquante, avec 5 € et la créature Encre. La fenêtre de navigation privée est connectée comme Alice, la victime, avec 120 €, Braise et Moustache. Chaque fenêtre a son cookie de session. Vous êtes au clavier des deux. Bob, avec 0,30 €, Roux et Noisette, est un joueur de plus. Le mot de passe de tous les comptes est password

Au départ, Mallory a 5 € et Alice 120 €. Mais ce solde change avec les achats et les attaques. Pour savoir qui est connecté dans une fenêtre, ouvrez le menu du joueur, le carré à l'initiale en haut à droite : il affiche le nom et l'adresse e-mail du compte.

5. Ce que le kit fait déjà

Le Tamagotchi est construit sur le même kit que votre portfolio. Au chapitre 1.10, vous avez vu le middleware auth, qui renvoie un visiteur vers /login, et $request->user(), qui rend l'utilisateur connecté. Toutes les routes du jeu passent par auth. Un visiteur qui ouvre tamagotchi.test/magasin sans être connecté arrive sur la page de connexion.

Les contrôleurs du jeu lisent le joueur connecté avec $request->user(). Voici la méthode qui affiche la page « Mon tamagotchi », dans app/Http/Controllers/CreatureController.php :

public function index(Request $request): Response
{
    return Inertia::render('creatures/Index', [
        'creatures' => $request->user()->creatures()
            ->orderBy('name')
            ->get(['id', 'name', 'species', 'food', 'mood', 'energy']),
    ]);
}

$request->user()->creatures() ne lit que les créatures de la personne connectée. Alice voit Braise et Moustache, Mallory voit Encre. L'application sait donc qui envoie chaque requête. Les failles de ce temps commencent après cette question : ce joueur connecté a-t-il le droit de faire ce qu'il demande ?

6. La règle de la salle

Vous n'attaquez que votre propre copie, sur votre propre machine. Jamais le site d'un autre étudiant, jamais celui de l'école, jamais un site en ligne pour « voir si ça marche aussi ».

La première raison est la loi. En Belgique, le Code pénal punit le fait d'entrer sans autorisation dans un système informatique, même sans rien abîmer ni rien voler. Sur un autre site, une adresse accessible ne vous donne pas l'autorisation de consulter les données d'un autre joueur. La seconde raison est la confiance. Une entreprise qui vous engage comme développeur vous donne accès à ses données et à celles de ses clients. Elle a besoin de savoir que vous connaissez ces gestes et que vous ne les faites que là où on vous l'a demandé.

Sur tamagotchi.test, vous êtes à la fois le propriétaire du site, Alice, Mallory et Bob. Tout y est permis.

7. Le tableau de bord : les tests

Le Tamagotchi arrive avec ses tests Pest, comme ceux que vous avez écrits au chapitre 1.17. Lancez-les dans le premier terminal. Comme au chapitre 1.17, les tests utilisent une base SQLite en mémoire : ils ne touchent pas aux créatures de votre partie.

php artisan test
   PASS  Tests\Unit\ExampleTest
  ✓ that true is true
…
   FAIL  Tests\Feature\Flaws\Flaw02AccessControlTest
  ⨯ a player cannot open the edit page of someone else's creature
  ⨯ a player cannot rename someone else's creature
  ⨯ a player cannot play with someone else's creature
  ⨯ a player cannot put someone else's creature to sleep
  ⨯ a player cannot release someone else's creature
  ✓ the owner still can

   FAIL  Tests\Feature\Flaws\Flaw03MassAssignmentTest
  ⨯ extra fields sent with the motto are ignored
…
   PASS  Tests\Feature\Game\GameTest
  ✓ guests are sent to the login page with ('/dashboard')
…
  ✓ a gift code works once
…
  Tests:    24 failed, 61 passed (290 assertions)
  Duration: 10.99s

Ces 85 tests forment votre tableau de bord. Ils se rangent en trois groupes.

  • Les tests du kit, dans tests/Feature/Auth/, tests/Feature/Settings/ et quelques autres fichiers : la connexion, le profil, le mot de passe. Ils sont 42, tous verts.
  • Les tests du jeu, dans tests/Feature/Game/GameTest.php : adopter, jouer, acheter, laisser un message. Ils sont 18, tous verts.
  • Les tests des failles, dans tests/Feature/Flaws/ : un fichier par faille, numéroté comme son chapitre. Flaw02AccessControlTest.php va avec le chapitre 2.02. Ils sont 25, et 24 sont rouges.

Le 25e test des failles, the owner still can, est vert. Il vérifie qu'Alice peut toujours ouvrir la page de modification de sa propre créature, et il doit le rester après votre correction.

Attention

Si le total annonce 42 tests rouges au lieu de 24, avec le message Vite manifest not found, les pages ne sont pas compilées. Lancez composer run dev dans le second terminal, puis relancez les tests.

Le tableau de bord de php artisan test au départ. Séance 1 : 2.02 contrôle d'accès, 5 tests rouges · 2.03 assignation de masse, 1 · 2.04 props publiques, 1 · 2.05 XSS, 1 · 2.06 injection SQL, 2. Séance 2 : 2.07 les centimes, 4 · 2.08 le prix du navigateur, 6 · 2.09 l'achat atomique, 3 · 2.10 la limitation de débit, 1. En tout 24 rouges, et 61 verts qui doivent le rester : 42 du kit, 18 du jeu, 1 dans Flaw02

Un test rouge d'un fichier Flaw dit qu'une vérification échoue. Lisez son message : il peut montrer une attaque qui réussit, un calcul faux ou une colonne qui manque encore dans la base. Une faille est corrigée quand tous les tests de son fichier sont verts. Les tests du jeu et du kit doivent rester verts à chaque étape : une correction qui casse l'achat d'un bonbon n'est pas une correction.

Les tests des chapitres 2.07 à 2.09 échouent d'abord pour la même raison : ils cherchent des colonnes que la base n'a pas encore. Ils passent au vert dans l'ordre des chapitres, et certains plus tôt que leur numéro : deux des trois tests du 2.09 sont déjà verts à la fin du 2.08.

Les tests d'une seule faille

Pendant un chapitre, vous ne lancez que les tests de sa faille. L'option --filter garde les tests dont le nom contient le mot donné :

php artisan test --filter=Flaw02
   FAIL  Tests\Feature\Flaws\Flaw02AccessControlTest
  ⨯ a player cannot open the edit page of someone else's creature
  ⨯ a player cannot rename someone else's creature
  ⨯ a player cannot play with someone else's creature
  ⨯ a player cannot put someone else's creature to sleep
  ⨯ a player cannot release someone else's creature
  ✓ the owner still can
  ────────────────────────────────────────────────────────────
   FAILED  Tests\Feature\Flaws\Flaw02AccessControlTest > a player cannot open the edit page of someone else's creatu…
  Expected response status code [403] but received 200.
…
  Tests:    5 failed, 1 passed (6 assertions)

Lisez le premier échec comme au chapitre 1.17 : le test attendait le code 403, « accès refusé », et le serveur a répondu 200, la page s'est affichée. Ce constat est le point de départ du chapitre 2.02.

À la fin d'un chapitre, relancez php artisan test en entier. Le nombre de rouges doit avoir baissé, et les tests déjà verts doivent le rester. Au chapitre 2.07, vous écrivez quatre cas de test de plus : la suite passe de 85 à 89 tests.

composer test, le critère de réussite

Le kit déclare un second script, composer test. Il enchaîne quatre commandes : config:clear, Pint qui vérifie la mise en forme du code, PHPStan qui analyse le code sans le lancer, puis php artisan test. Il s'arrête à la première qui échoue. Sur le dépôt que vous venez de cloner, il s'arrête à PHPStan :

composer test
 ------ ---------------------------------------------------------------------
  Line   app\Http\Controllers\ShopController.php
 ------ ---------------------------------------------------------------------
  19     Parameter #1 $sql of method … whereRaw() expects …
 ------ ---------------------------------------------------------------------

 [ERROR] Found 1 error
…
Script phpstan analyse handling the types:check event returned with error code 1

Les tests ne sont même pas lancés. Cette erreur de PHPStan est l'une des failles, celle du chapitre 2.06. C'est pourquoi votre tableau de bord pendant les deux séances est php artisan test. Au chapitre 2.12, composer test doit être vert de bout en bout : la mise en forme, l'analyse et les 89 tests de la version corrigée.

8. La méthode, et le carnet des failles

Les chapitres 2.02 à 2.10 suivent le même ordre, en sept temps. Trois d'entre eux le varient. Le chapitre 2.04 se regarde plus qu'il ne s'attaque : vous lisez ce que la page a reçu, puis vous corrigez. Le chapitre 2.07 montre une erreur de calcul, rejouée avec le compte de Bob. Le chapitre 2.09 explique les achats simultanés par des schémas, et vous fait tester une panne au milieu d'un achat.

  1. L'histoire. Un incident réel, en quelques phrases : quelle entreprise, quelle faille, ce que ça a coûté.
  2. Le danger. Ce que l'attaquante obtient, qui est touché, et pourquoi le développeur ne l'a pas vu.
  3. L'attaque, montrée. Le chapitre la déroule pas à pas, avec les captures de l'application.
  4. L'attaque, refaite. Vous la refaites sur votre copie, connecté comme Mallory, avec le navigateur et ses outils de développement.
  5. La correction. Vous corrigez le code avec la bonne pratique de Laravel. Le chapitre dit ce que vous devez obtenir et où chercher. La correction complète est cachée dans un encart à déplier : cherchez dix minutes avant de l'ouvrir.
  6. La preuve. Les tests de la faille passent du rouge au vert, et l'attaque refaite échoue.
  7. La règle. Une phrase à retenir.

Cette dernière phrase va dans votre carnet des failles. C'est un document d'une page, que vous remplissez au fil des chapitres et que vous relisez au chapitre 2.12. Il ne se rend pas : il vous sert à retrouver ces failles dans votre portfolio. Pour chaque faille, il porte deux choses :

  • La règle, en une phrase, recopiée du chapitre.
  • L'endroit de votre portfolio où elle s'applique : un fichier, une méthode, un formulaire, ou « nulle part », avec la raison.

La seconde ligne est la plus utile. Elle vous fait relire votre propre code avec les yeux de Mallory. Si une page de votre portfolio a le même trou que le Tamagotchi, notez-le et corrigez-le.

9. Pratique : votre copie prête (10 min)

  1. Votre fork créé sur GitHub et cloné dans tamagotchi, composer install, .env copié avec APP_URL=http://tamagotchi.test, la clé générée.
  2. php artisan migrate:fresh --seed, npm install, puis composer run dev dans le second terminal.
  3. Mallory connectée dans une fenêtre normale, Alice dans une fenêtre de navigation privée.
  4. php artisan test dans le premier terminal.

Vérifiez dans le navigateur et dans le terminal.

  • tamagotchi.test affiche la page d'accueil du jeu.
  • Le menu du joueur affiche Mallory dans une fenêtre, Alice dans l'autre.
  • Depuis le classement, Mallory ouvre l'enclos d'Alice et y lit le message de Bob.
  • php artisan test se termine par 24 failed, 61 passed.
  • php artisan test --filter=Flaw02 se termine par 5 failed, 1 passed.

À retenir

  • Le Tamagotchi troué fonctionne, et ses failles ont été mises là exprès pour être attaquées puis corrigées.
  • php artisan migrate:fresh --seed remet le jeu dans son état de départ, avec Alice, Mallory et Bob, tous avec le mot de passe password.
  • Une fenêtre de navigation privée garde ses propres cookies, ce qui permet d'être Mallory et Alice en même temps.
  • On n'attaque que sa propre copie, sur sa propre machine.
  • php artisan test --filter=FlawNN lance les tests d'une faille, et composer test vert de bout en bout est le critère de réussite du temps 2.