Skip to content

Instantly share code, notes, and snippets.

@mattbrundage
Last active October 25, 2024 16:04
Show Gist options
  • Save mattbrundage/68adc36afcd3cfcb965e31cf2986aaa9 to your computer and use it in GitHub Desktop.
Save mattbrundage/68adc36afcd3cfcb965e31cf2986aaa9 to your computer and use it in GitHub Desktop.
cfdump XSS demo
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<title>&lt;cfdump&gt; is not vulnerable to XSS in its default configuration</title>
<style>
main {
margin-inline: auto;
max-width: 64ch;
}
td:not(:last-child) { white-space: nowrap; }
td:last-child { word-break: break-all; }
</style>
</head>
<body>
<main>
<cfif NOT getPageContext().getResponse().isCommitted()>
<!--- inner double quotes are mandatory --->
<!--- <cfheader name="Clear-Site-Data" value='"*"' /> --->
</cfif>
<cfset Variables.exampleValue="<script>alert(0);</script>" />
<cfparam name="Form.XSS_attempt" default="#Variables.exampleValue#" />
<cfparam name="URL.XSS_attempt" default="#Variables.exampleValue#" />
<cfcookie name="XSS_attempt" httpOnly="yes" preserveCase="yes" sameSite="strict" secure="yes" value="#Form.XSS_attempt#" />
<h1><code>&lt;cfdump&gt;</code> is not vulnerable to XSS in its default configuration</h1>
<h2>Offical documentation</h2>
<p>The <a href="https://docs.lucee.org/reference/tags/dump.html#attribute-format"><code>format</code> attribute</a> defaults to "html" when the <code>output</code> attribute is set to "browser" (also the default). That is, the struct's key/value pairs are output in ColdFusion's standard HTML table format and the contents are encoded/escaped for inclusion in this HTML context. Comparatively, when the <code>format</code> attribute is "text", then the struct's key/value pairs are dumped as plain text without encoding/escaping special characters. In this case, the dump is wrapped in a <code>&lt;pre&gt;</code> tag, which affords line break formatting.</p>
<h2>Reduced test cases</h2>
<p>The following <code>&lt;cfdump&gt;</code> instances use the default values of the <code>format</code> and <code>output</code> attributes: "html" and "browser", respectively.</p>
<p>This page sets the default values of the "<var>XSS_attempt</var>" variables in the Form, URL, and Cookie scopes to an unencoded script tag, <code><cfoutput>#encodeForHTML(Variables.exampleValue)#</cfoutput></code>. This method bypasses ColdFusion ScriptProtect to demonstrate that <code>&lt;cfdump&gt;</code> still protects against XSS even if ScriptProtect is not in play.</p>
<p>If <code>&lt;cfdump&gt;</code> were vulnerable to XSS in its default configuration, then this page would have opened four successive JavaScript <code>alert()</code> dialogs. Internally, as <code>&lt;cfdump&gt;</code> builds its HTML table of key/value pairs to output, it encodes for HTML the values of each key and value. This is performed to maintain the layout integrity of the table and is also a built-in security feature of <code>&lt;cfdump&gt;</code>.</p>
<p>The end result is a set of HTML-encoded script tags &mdash; which are displayed as inert text on the page because special characters are encoded. For instance, <code>&lt;</code> and <code>&gt;</code> are encoded as <code>&amp;lt;</code> and <code>&amp;gt;</code>, respectively.</p>
<h3>Attempt XSS via the Form scope</h3>
<p>ColdFusion ScriptProtect is in play with this method.</p>
<form method="post">
<textarea name="XSS_attempt" rows="1" cols="40"><cfoutput>#encodeForHTML(Form.XSS_attempt)#</cfoutput></textarea>
<button>Submit</button>
</form>
<cfdump label="Form" var="#Form#" />
<h3>Attempt XSS via the URL scope</h3>
<p>ColdFusion ScriptProtect is in play with this method.</p>
<p>
<cfif URL.XSS_attempt EQ Variables.exampleValue AND structCount(URL) EQ 1>
<a href="?XSS_attempt=REPLACE_THIS">Add an XSS attempt to the query string.</a>
<cfelse>
<a href="./">Remove query string.</a>
</cfif>
</p>
<cfdump label="URL" var="#URL#" />
<h3>Attempt XSS via the Cookie scope</h3>
<p>Attempting XSS via the Form scope will change the value of <var>Cookie.XSS_attempt</var> accordingly. As such, ColdFusion ScriptProtect is in play with this method.</p>
<cfdump label="Cookie" var="#Cookie#" />
<h3>Attempt XSS via the structure returned from <code>getHttpRequestData()</code></h3>
<p>See the <var>content</var> field after a form submission, the <var>headers.cookie</var> field, and the <var>headers.referer</var> field when a query string is present in the referring URL. In addition to the usual HTML encoding that <code>&lt;cfdump&gt;</code> provides to each key/value pair, the posted form value in <var>content</var>, the cookie value in <var>headers.cookie</var> and the query string value(s) in <var>headers.referer</var> are already URL-encoded per the HTML spec.</p>
<cfdump var="#getHttpRequestData()#" label="getHttpRequestData()" />
</main>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment