Skip to content

Commit 8e1b48e

Browse files
committed
StoredXSS.qhelp
1 parent 182a926 commit 8e1b48e

File tree

4 files changed

+78
-0
lines changed

4 files changed

+78
-0
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>
7+
Directly writing an uncontrolled stored value (for example, a database
8+
field) to a webpage, without properly sanitizing the value first, allows
9+
for a cross-site scripting vulnerability.
10+
</p>
11+
<p>
12+
This kind of vulnerability is also called <i>stored</i> cross-site
13+
scripting, to distinguish it from other types of cross-site scripting.
14+
</p>
15+
</overview>
16+
17+
<recommendation>
18+
<p>
19+
To guard against stored cross-site scripting, consider escaping before
20+
using uncontrolled stored values to create HTML content. Some frameworks,
21+
such as Rails, perform this escaping implicitly and by default.
22+
</p>
23+
24+
<p>
25+
Take care when using methods such as <code>html_safe</code> or
26+
<code>raw</code>. They can be used to emit a string without escaping
27+
it, and should only be used when the string has already been manually
28+
escaped (for example, with the Rails <code>html_escape</code> method),
29+
or when the content is otherwise guaranteed to be safe (such as a
30+
hard-coded string).
31+
</p>
32+
</recommendation>
33+
34+
<example>
35+
<p>
36+
The following example is safe because the
37+
<code>user.name</code> content within the output tags will be
38+
HTML-escaped automatically before being emitted.
39+
</p>
40+
<sample src="examples/stored_xss_rails_safe.html.erb" />
41+
42+
<p>
43+
However, the following example may be unsafe because
44+
<code>user.name</code> is emitted without escaping, since it is marked as
45+
<code>html_safe</code>. If the <code>name</code> is not sanitized before
46+
being written to the database, then an attacker could use this to insert
47+
arbitrary content into the HTML output, including scripts.
48+
</p>
49+
<sample src="examples/stored_xss_rails_unsafe.html.erb" />
50+
51+
<p>
52+
In the next example, content from a file on disk is inserted literally
53+
into HTML content. This approach is sometimes used to load script
54+
content, such as extensions for a web application, from files on disk.
55+
Care should taken in these cases to ensure both that the loaded files are
56+
trusted, and that the file cannot be modified by untrusted users.
57+
</p>
58+
<sample src="examples/stored_xss_file_unsafe.html.erb" />
59+
</example>
60+
61+
<references>
62+
<li>
63+
OWASP:
64+
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Ruby_on_Rails_Cheat_Sheet.html#cross-site-scripting-xss">XSS
65+
Ruby on Rails Cheatsheet</a>.
66+
</li>
67+
<li>
68+
Wikipedia: <a href="http://en.wikipedia.org/wiki/Cross-site_scripting">Cross-site scripting</a>.
69+
</li>
70+
</references>
71+
</qhelp>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<script>
2+
<%= File.read(File.join(SCRIPT_DIR, "script.js")).html_safe %>
3+
</script>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<% user = User.find(1) %>
2+
<p>Hello <%= user.name %>!</p>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<% user = User.find(1) %>
2+
<p>Hello <%= user.name.html_safe %>!</p>

0 commit comments

Comments
 (0)