Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
JSでDoSる/ Shibuya.XSS techtalk #11
Search
Masato Kinugawa
May 16, 2019
Technology
20
7k
JSでDoSる/ Shibuya.XSS techtalk #11
Shibuya.XSS techtalk #11 の発表資料です。
Masato Kinugawa
May 16, 2019
Tweet
Share
More Decks by Masato Kinugawa
See All by Masato Kinugawa
Shadow DOMとセキュリティ - 光と影の境界を探る / Shibuya.XSS techtalk #13
masatokinugawa
0
420
Shadow DOM & Security - Exploring the boundary between light and shadow
masatokinugawa
1
1.1k
ブラウザのレガシー・独自機能を愛でる-Firefoxの脆弱性4選- / Browser Crash Club #1
masatokinugawa
1
780
注目したいクライアントサイドの脆弱性2選/ Security.Tokyo #3
masatokinugawa
8
3.9k
バグハンティングのすゝめ / P3NFEST
masatokinugawa
5
2.4k
Pwn2OwnでMicrosoft Teamsをハッキングして2000万円を獲得した方法/ Shibuya.XSS techtalk #12
masatokinugawa
13
20k
How I Hacked Microsoft Teams and got $150,000 in Pwn2Own
masatokinugawa
1
22k
Electron: Abusing the lack of context isolation - CureCon(en)
masatokinugawa
5
100k
Electron: Context Isolationの欠如を利用した任意コード実行 / Electron: Abusing the lack of context isolation - CureCon(ja)
masatokinugawa
9
27k
Other Decks in Technology
See All in Technology
いかにして命令の入れ替わりについて心配するのをやめ、メモリモデルを愛するようになったか(改)
nullpo_head
7
2.6k
金融サービスにおける高速な価値提供とAIの役割 #BetAIDay
layerx
PRO
1
830
Agent Development Kitで始める生成 AI エージェント実践開発
danishi
0
150
Amazon Q Developerを活用したアーキテクチャのリファクタリング
k1nakayama
2
210
AI関数が早くなったので試してみよう
kumakura
0
290
JAWS AI/ML #30 AI コーディング IDE "Kiro" を触ってみよう
inariku
3
370
Findy Freelance 利用シーン別AI活用例
ness
0
500
AWS DDoS攻撃防御の最前線
ryutakondo
1
160
【新卒研修資料】数理最適化 / Mathematical Optimization
brainpadpr
27
13k
僕たちが「開発しやすさ」を求め 模索し続けたアーキテクチャ #アーキテクチャ勉強会_findy
bengo4com
0
2.4k
ファッションコーディネートアプリ「WEAR」における、Vertex AI Vector Searchを利用したレコメンド機能の開発・運用で得られたノウハウの紹介
zozotech
PRO
0
330
【OptimizationNight】数理最適化のラストワンマイルとしてのUIUX
brainpadpr
2
480
Featured
See All Featured
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
183
54k
Site-Speed That Sticks
csswizardry
10
770
Why Our Code Smells
bkeepers
PRO
337
57k
Measuring & Analyzing Core Web Vitals
bluesmoon
8
550
Writing Fast Ruby
sferik
628
62k
Rebuilding a faster, lazier Slack
samanthasiow
83
9.1k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
8
450
Thoughts on Productivity
jonyablonski
69
4.8k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
18
1.1k
Intergalactic Javascript Robots from Outer Space
tanoku
272
27k
Transcript
for(;;){ alert(` `); } /* 2019/05/16 Shibuya.XSS techtalk #11*/ /*
Masato Kinugawa */
• • •
None
• • • • •
• • • •
• • • • • • • • • •
•
while(1){ alert(` `); }
• •
•
• • > decodeURIComponent("%E3%81%82"); < " " > decodeURIComponent("%FF"); ‣
Uncaught URIError: URI malformed
None
• • • > encodeURIComponent(" "); < "%E3%81%82" > encodeURIComponent("\uDC00");
‣ Uncaught URIError: URI malformed
https://www.ecma-international.org/ecma-262/9.0/index.html#sec-encode
(function a(){ alert(` `); a(); })()
• • • • / \/ • " \" •
\ \\ <script> userInput = "AAA\\\";alert(1)\/\/ <\/script>"; displayContents(); </script>
• <script> userInput = "AAA [ ] BBB"; displayContents(); </script>
• <script> userInput = "AAA BBB"; displayContents(); </script>
• https://www.ecma-international.org/ecma-262/9.0/index.html#table-33
• https://www.ecma-international.org/ecma-262/9.0/index.html#table-33
• <script> userInput = "AAA [U+2028] BBB"; displayContents(); </script>
• • • • •
<script> userInput = "<!--<script>"; displayContents(); </script>
• • <script> userInput = "<!--<script>"; </script> <textarea></script> <img src=x
onerror=alert(1)> </textarea>
• • https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script- elements
• <script> userInput = "<%"; </script> <textarea>%></script><img src=x onerror=alert(1)> </textarea>
https://html5sec.org/#91 <xmp> <% </xmp> <textarea> %></xmp><img src=x onerror=alert(1)> </textarea>
• • • • •
setInterval(` alert(\` \`) `,1);
• •
•
• • • userInfo = {"name": 123}// name = userInfo.name.toUpperCase()
Uncaught TypeError: userInfo.name.toUpperCase is not a function
siteData = {"url":"https:// ...","title":{"toString":null},...}; url = "url: " + siteData.url;
title = "title: " + siteData.title;
• • • ({toString: function(){alert(1)} })+""; ({valueOf : function(){alert(2)} })+"";
• • • > ({toString:null})+""; ‣ Uncaught TypeError: Cannot convert
object to primitive value
• • • • •
• > typeof "aaa"; < ‣ "string" > typeof 123;
< ‣ "number" > typeof true; < ‣ "boolean" > typeof []; < ‣ "object" > typeof {}; < ‣ "object" > typeof null; < ‣ "object"
• • > Array.isArray([]); < ‣ true > Array.isArray({}); <
‣ false > null === null < ‣ true
• • > Object.prototype.toString.call("aaa"); < ‣ "[object String]" > Object.prototype.toString.call(123);
< ‣ "[object Number]" > Object.prototype.toString.call(true); < ‣ "[object Boolean]" > Object.prototype.toString.call([]); < ‣ "[object Array]" > Object.prototype.toString.call({}); < ‣ "[object Object]" > Object.prototype.toString.call(null); < ‣ "[object Null]"
<style>*{ color:expression( alert(" ") )}
• • • <toString>AAA</toString>
• • •
• • function tellMeFruitColor(USER_INPUT){ fruits = { "apple":"red", "lemon":"yellow", "peach":"pink"
}; if(fruits[USER_INPUT]){ return USER_INPUT + ": " + fruits[USER_INPUT]; }else{ return "I don't know that fruit"; } }
> tellMeFruitColor("apple"); < "apple: red" > tellMeFruitColor("lemon"); < "lemon: yellow"
> tellMeFruitColor("strawberry"); < "I don't know that fruit" > tellMeFruitColor("toString"); < "toString: function toString() { [native code] }" > tellMeFruitColor("constructor"); < "constructor: function Object() { [native code] }" > tellMeFruitColor("__proto__"); < "__proto__: [object Object]"
None
• •
https://qiita.com/howdy39/items/35729490b024ca295d6c
if(fruits["toString"]){ return "toString" + ": " + fruits["toString"]; }else{ return
"I don't know that fruit"; }
if(fruits["toString"]){ return "toString" + ": " + fruits["toString"]; }else{ return
"I don't know that fruit"; }
if(fruits["toString"]){ return "toString" + ": " + fruits["toString"]; }else{ return
"I don't know that fruit"; }
if(fruits["toString"]){ return "toString" + ": " + fruits["toString"]; }else{ return
"I don't know that fruit"; }
if(fruits["toString"]){ return "toString" + ": " + fruits["toString"]; }else{ return
"I don't know that fruit"; }
if(fruits["toString"]){ return "toString" + ": " + fruits["toString"]; }else{ return
"I don't know that fruit"; }
> ({"toString":function(){return "a"}})+""; < " " > ({"prop":"a"})+""; < "[object
Object]"
whiteListTags = { "span":funcForSanitizingSpanElem, "div": funcForSanitizingDivElem, "a":" funcForSanitizingAElem, ... }
// whiteListTags[ ] <toString> whiteListTags["toString"]()
fileIcons = { "txt":"https://example.com/img/icon-txt.gif", "png":"https://example.com/img/icon-png.gif", "jpg":" https://example.com/img/icon-jpg.gif ", ... }
// fileIcons[ ] dos.constructor fileIcons["constructor"]
• • • •
• • function tellMeFruitColor(USER_INPUT){ fruits = { ... }; -
if(fruits[USER_INPUT]){ + if(Object.prototype.hasOwnProperty.call(fruits,USER_INPUT)){ return USER_INPUT + ": " + fruits[USER_INPUT]; }else{ return "I don't know that fruit"; } }
> tellMeFruitColor("apple"); < "apple: red" > tellMeFruitColor("lemon"); < "lemon: yellow"
> tellMeFruitColor("strawberry"); < "I don't know that fruit" > tellMeFruitColor("toString"); < "I don't know that fruit" > tellMeFruitColor("constructor"); < "I don't know that fruit" > tellMeFruitColor("__proto__"); < "I don't know that fruit"
• • fruits["toString"] undefined function tellMeFruitColor(USER_INPUT){ - fruits = {
... }; + fruits = Object.create(null); + fruits = Object.assign(fruits,{"apple":"red","lemon": ... }) if(fruits[USER_INPUT]){ return USER_INPUT + ": " + fruits[USER_INPUT]; }else{ return "I don't know that fruit"; } }
• • function tellMeFruitColor(USER_INPUT){ - fruits = { ... };
+ fruits = new Map(["apple","red"], + ["lemon","yellow"], + ["peach","pink"]); - if(fruits[USER_INPUT]){ - return USER_INPUT + ": " + fruits[USER_INPUT]; + if(fruits.get(USER_INPUT)){ + return USER_INPUT + ": " + fruits.get(USER_INPUT); }else{ return "I don't know that fruit"; } }
({toString: function(){ alert(` `); this+""; } })+"";
• •
• • • USER_INPUT = {"length": 1e10,"constructor":{"name":"Array"}}; if(USER_INPUT.constructor.name === "Array"){
array = []; for (var i = 0; i < USER_INPUT.length; i++) { array.push(USER_INPUT[i]); } }
==== JS stack trace ========================================= Security context: 00000099763A5549 <JSObject> 1:
/* anonymous */ [repl:~1] [pc=000000C1A3E8B9B9](this=00000382794865D9 <JSGlobal Object>) 5: /* anonymous */ [vm.js:65] [bytecode=000002EDD76E8421 offset=87](this=0000021A2A00C731 <ContextifyScript map = 00000203C25E1319>,options=0000021A2A00C709 <Object map = 00000203C25E13C9>) 6: defaultEval [repl.js:244] [bytecode=000002EDD76E7089 offset=445](this=0000021A2A00C7A1 <REPLServer ... FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 1: node::DecodeWrite 2: node_module_register 3: v8::internal::FatalProcessOutOfMemory 4: v8::internal::FatalProcessOutOfMemory 5: v8::internal::Factory::NewUninitializedFixedArray 6: v8::internal::WasmDebugInfo::SetupForTesting 7: v8::internal::interpreter::BytecodeArrayRandomIterator::UpdateOffsetFromIndex 8: 000000C1A3D043C1
• • •
•
• • • • •
for(;;){ alert(` `); } /* */