<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>gruyere.py &#8211; @Forensicxs</title>
	<atom:link href="https://www.forensicxs.com/tag/gruyere-py/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.forensicxs.com</link>
	<description>Ethical Hacking &#124; Cybersecurity</description>
	<lastBuildDate>Mon, 27 Dec 2021 14:56:10 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	
	<item>
		<title>Google Gruyere</title>
		<link>https://www.forensicxs.com/google-gruyere/</link>
					<comments>https://www.forensicxs.com/google-gruyere/#respond</comments>
		
		<dc:creator><![CDATA[Forensicxs]]></dc:creator>
		<pubDate>Sat, 18 Sep 2021 17:37:21 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[AJAX vulnerabilities]]></category>
		<category><![CDATA[Client-State Manipulation]]></category>
		<category><![CDATA[Code Execution]]></category>
		<category><![CDATA[Cookie Manipulation]]></category>
		<category><![CDATA[CSRF]]></category>
		<category><![CDATA[Denial of Service]]></category>
		<category><![CDATA[DoS]]></category>
		<category><![CDATA[File upload XSS]]></category>
		<category><![CDATA[Google Gruyere]]></category>
		<category><![CDATA[gruyere.py]]></category>
		<category><![CDATA[Injection vulnerabilities]]></category>
		<category><![CDATA[OWASP]]></category>
		<category><![CDATA[Path Trasversal]]></category>
		<category><![CDATA[Phishing]]></category>
		<category><![CDATA[Reflected XSS]]></category>
		<category><![CDATA[Reflected XSS via AJAX]]></category>
		<category><![CDATA[secret.txt]]></category>
		<category><![CDATA[Stored XSS]]></category>
		<category><![CDATA[Stored XSS via AJAX]]></category>
		<category><![CDATA[Stored XSS via HTML attribute]]></category>
		<category><![CDATA[Web Exploits]]></category>
		<category><![CDATA[XSS]]></category>
		<category><![CDATA[XSSI]]></category>
		<guid isPermaLink="false">https://www.forensicxs.com/?p=1871</guid>

					<description><![CDATA[This article is a walkthrough of Google Gruyere vulnerabilities]]></description>
										<content:encoded><![CDATA[
<p>Let&#8217;s practice some Web Hacking. For this purpose, there is a good resource developed by Google. It&#8217;s a Website called Google Gruyere; it is a <strong><span class="has-inline-color has-luminous-vivid-orange-color">Hacking Lab</span></strong>, and as per it&#8217;s name, it is riddled with vulnerabilities. Link : <a href="https://google-gruyere.appspot.com/" target="_blank" rel="noreferrer noopener">https://google-gruyere.appspot.com/</a></p>



<p>This website mimicks the principles of a very basic <strong><span class="has-inline-color has-luminous-vivid-orange-color">social network</span></strong>, where you can create a user profile (name, photo, pinned message and website&#8230;), manage it, and post some short messages (snippets in this case), so it really makes sense as a study material</p>



<p>The Lab shows how web application vulnerabilities can be exploited and how to defend against these attacks. Among other <strong><span class="has-inline-color has-luminous-vivid-orange-color">Challenges</span></strong>, we will practice cross-site scripting (XSS), cross-site request forgery (XSRF),&#8230;and also get an opportunity to assess the impacts of such vulnerabilities ( denial-of-service, information disclosure, remote code execution&#8230;)</p>



<p>Some of these Challenges can be solved by using black box techniques, other Challenges will require to look at the Gruyere source code (that&#8217;s why Google provides both client side and server side code along with the Lab). The code is written in <strong><span class="has-inline-color has-luminous-vivid-orange-color">Python</span></strong>. Reading through the code will help build a good understanding how the vulnerabilities work. The code relies on Templates &#8211; Gruyere Template Language or GTL &#8211; , and in this respect, look similar to Django (<a href="https://www.djangoproject.com/start/overview/" target="_blank" rel="noreferrer noopener">https://www.djangoproject.com/start/overview/</a>)</p>



<p>Google provides all the solutions on the Gruyere site, so I&#8217;m not going to provide new solutions but rather walk through the proposed solutions</p>



<hr class="wp-block-separator"/>



<p><strong><span class="has-inline-color has-vivid-red-color">Introduction to Gruyere</span></strong></p>



<p>The Lab looks like this when you launch it for the first time (it will create an incremental session number, specific to you)</p>



<figure class="wp-block-image size-full is-resized"><img fetchpriority="high" decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image.png" alt="" class="wp-image-1885" width="406" height="333" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image.png 730w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-300x247.png 300w" sizes="(max-width: 406px) 100vw, 406px" /></figure>



<p>As a warm-up, we are requested to perform a few basic tasks, to gain a first understanding of the user interface :</p>



<ul class="wp-block-list"><li><em>View another user&#8217;s snippets by following the &#8220;All snippets&#8221; link on the main page. Also check out what they have their Homepage set to</em></li><li><em>Sign up for an account for yourself to use when hacking</em></li><li><em>Fill in your account&#8217;s profile, including a private snippet and an icon that will be displayed by your name</em></li><li><em>Create a snippet (via &#8220;New Snippet&#8221;) containing your favorite joke</em></li><li><em>Upload a file (via &#8220;Upload&#8221;) to your account</em></li></ul>



<p>This is what my login page now looks like :</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="424" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-3-1024x424.png" alt="" class="wp-image-1894" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-3-1024x424.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-3-300x124.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-3-768x318.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-3-1536x637.png 1536w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-3.png 1795w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" /></figure>



<p>About <strong><span class="has-inline-color has-luminous-vivid-orange-color">snippets</span></strong> : some of you may not know where this comes from. It is the usual word used by Google to highlight a  summary text in the Google search engine result. In our context, a snippet refers to a small bit of text added as a tag, after a user name</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-9.png" alt="" class="wp-image-1914" width="414" height="96" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-9.png 663w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-9-300x69.png 300w" sizes="(max-width: 414px) 100vw, 414px" /></figure>



<p>Before going through the Challenges, let&#8217;s have a <strong><span class="has-inline-color has-luminous-vivid-orange-color">first look into the code</span></strong> (I&#8217;m using the code editor &#8220;Sublime Text&#8221;)</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-4.png" alt="" class="wp-image-1898" width="233" height="414" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-4.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-4-169x300.png 169w" sizes="(max-width: 233px) 100vw, 233px" /></figure>



<p>Here is a short explanation about the Gruyere modules (we will come back to it with deeper analysis during the Challenges) : </p>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">data.py</span></strong> stores the <strong><span class="has-inline-color has-vivid-cyan-blue-color">default data in the database</span></strong>. There is an administrator account and three default users</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-5.png" alt="" class="wp-image-1901" width="531" height="666" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-5.png 695w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-5-239x300.png 239w" sizes="(max-width: 531px) 100vw, 531px" /></figure>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">gruyere.py</span></strong> is the main Gruyere <strong><span class="has-inline-color has-vivid-cyan-blue-color">web server</span></strong></p>



<p>The code enables the setup of a local server with the necessary functionalities (creation of a working directory, installation of a database, cookie management, URL/HTML responses, management of user profile, data/file upload,&#8230;)</p>



<p>Here are important text comments included in the code, it helps understand the server logic and limitations</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-6.png" alt="" class="wp-image-1904" width="523" height="145" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-6.png 659w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-6-300x83.png 300w" sizes="(max-width: 523px) 100vw, 523px" /></figure>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">gtl.py</span></strong> is the <strong><span class="has-inline-color has-vivid-cyan-blue-color">Gruyere Template Language</span></strong></p>



<p>Gruyere Template Language (GTL) is a new template language, and as its siblings such as Django, it helps create web pages more efficiently. Documentation for GTL can be found directly in gruyere/gtl.py</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-7.png" alt="" class="wp-image-1907" width="526" height="599" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-7.png 687w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-7-264x300.png 264w" sizes="(max-width: 526px) 100vw, 526px" /></figure>



<p>Most of the Gruyere resources are written using GTL</p>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">sanitize.py</span></strong> is the Gruyere module used for <strong><span class="has-inline-color has-vivid-cyan-blue-color">sanitizing HTML, to protect the application from security holes</span></strong></p>



<p>HTML sanitization is the process of examining an HTML document and producing a new one that preserves only whatever tags are designated &#8220;safe&#8221; and desired. HTML sanitization can be used to protect against attacks such as cross-site scripting (XSS) by sanitizing any HTML code submitted by a user. For example, tags such as &lt;script&gt; are usually removed during the sanitizing process. The process is usually based upon a white list of allowed tags, and a black list of disallowed tags</p>



<p>In our case, here are the allowed/disallowed tags</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-8.png" alt="" class="wp-image-1910" width="485" height="302" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-8.png 727w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-8-300x187.png 300w" sizes="(max-width: 485px) 100vw, 485px" /></figure>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">resources</span></strong> directory holds all <strong><span class="has-inline-color has-vivid-cyan-blue-color">CSS code</span></strong>, images, <strong><span class="has-inline-color has-vivid-cyan-blue-color">template files</span></strong> (it will provide important functionalities such as account creation, login process, user profile, snippets, file upload), and a <strong><span class="has-inline-color has-vivid-cyan-blue-color">Javascript library</span></strong> (for snippets user interaction and refresh)</p>



<hr class="wp-block-separator"/>



<p><strong><span class="has-inline-color has-vivid-red-color">Data Sanitization and Escaping</span></strong></p>



<p>We should always be very carefull with <strong><span class="has-inline-color has-vivid-cyan-blue-color">user inputs</span></strong> on our websites. Some users will try to &#8220;inject code&#8221; in our website, using different tricks (as we will see below in the following Challenges)</p>



<p>The root cause of <strong><span class="has-inline-color has-vivid-cyan-blue-color">code injection vulnerabilities</span></strong> is the mixing of code and data which is then handed to a browser. Injection is possible when the <strong><span class="has-inline-color has-vivid-cyan-blue-color">data is treated as code</span></strong></p>



<p>Data sanitization and Escaping is a mitigation for code injection vulnerabilities</p>



<p><strong><span class="has-inline-color has-vivid-cyan-blue-color">Sanitization</span></strong>&nbsp;involves&nbsp;<strong><span class="has-inline-color has-vivid-cyan-blue-color">removing&nbsp;characters</span></strong> entirely in order to make the value “safe”. Sanitization is difficult to do correctly, that&#8217;s why most sanitization implementations have seen a number of bypasses</p>



<p>The term “<strong><span class="has-inline-color has-vivid-cyan-blue-color">Escaping</span></strong>” originates from situations where text is being interpreted in some mode and we want to “escape” from that mode into a different mode</p>



<p>For example, you want to tell your terminal to switch from interpreting a sequence of code to text</p>



<p>One common situation is when a developer needs to tell <strong><span class="has-inline-color has-vivid-cyan-blue-color">a browser to&nbsp;<em>not</em>&nbsp;interpret a value as code but as text</span></strong></p>



<p>Please keep in mind these concepts as they will be important for the Challenges</p>



<p>If you want to go deeper on these topics before starting the Challenges, you could check this <strong><span class="has-inline-color has-vivid-cyan-blue-color">OWASP</span></strong> video about &#8220;<strong><span class="has-inline-color has-vivid-cyan-blue-color">killing injection vulnerabilities</span></strong>&#8220;</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="APPSEC Cali 2018 - Taking on the King: Killing Injection Vulnerabilities" width="525" height="295" src="https://www.youtube.com/embed/g_24036NDhM?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<hr class="wp-block-separator"/>



<p><strong><span class="has-inline-color has-vivid-red-color">Cross-Site Scripting (XSS)</span></strong></p>



<p>Cross-site scripting (XSS) is a vulnerability that permits an attacker to <strong><span class="has-inline-color has-vivid-cyan-blue-color">inject code</span></strong> (typically HTML or JavaScript) into contents of a website not under the attacker&#8217;s control. When a victim views such a page, the injected code executes in the victim&#8217;s browser. Thus, the attacker can <strong><span class="has-inline-color has-vivid-cyan-blue-color">steal victim&#8217;s private information</span></strong> associated with the website in question</p>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">File Upload XSS</span></strong></p>



<p>This attack is well documented by the <strong><span class="has-inline-color has-vivid-cyan-blue-color">OWASP Foundation</span></strong> : <a href="https://bit.ly/3xVUjqE" target="_blank" rel="noreferrer noopener">https://bit.ly/3xVUjqE</a></p>



<p>We can create the following file, including a warning message &#8220;Forensicxs hacked you&#8221;, and a script &#8211; <strong><span class="has-inline-color has-vivid-cyan-blue-color">Javascript</span></strong> &#8211; that will pop-up the content of the session cookie</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-10.png" alt="" class="wp-image-1918" width="311" height="177" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-10.png 468w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-10-300x171.png 300w" sizes="(max-width: 311px) 100vw, 311px" /></figure>



<p>Here below a bit more information about cookies and the potential use of <strong><span class="has-inline-color has-vivid-cyan-blue-color">document.cookie</span></strong></p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-14.png" alt="" class="wp-image-1922" width="504" height="238" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-14.png 806w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-14-300x142.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-14-768x363.png 768w" sizes="(max-width: 504px) 100vw, 504px" /><figcaption><a href="https://javascript.info/cookie" target="_blank" rel="noreferrer noopener">https://javascript.info/cookie</a></figcaption></figure>



<p>Let&#8217;s upload our HTML file into Gruyere. Once the upload is completed, we are provided with an https link to access our file directly from the browser</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="203" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-11-1024x203.png" alt="" class="wp-image-1919" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-11-1024x203.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-11-300x60.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-11-768x152.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-11-1536x305.png 1536w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-11.png 1798w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" /></figure>



<p>Let&#8217;s follow this link in our browser. We get the alert(document.cookie) pop-up window displayed. It provides the content of our session cookie</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-15-1024x158.png" alt="" class="wp-image-1924" width="555" height="85" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-15-1024x158.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-15-300x46.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-15-768x119.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-15.png 1087w" sizes="(max-width: 555px) 100vw, 555px" /><figcaption>alert(document.cookie) pop-up window</figcaption></figure>



<p>When we click OK, we land on our HTML message &#8220;Forensicxs hacked you&#8221;. In developer mode, we can confirm the cookie value</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-12-1024x362.png" alt="" class="wp-image-1920" width="674" height="238" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-12-1024x362.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-12-300x106.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-12-768x272.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-12-1536x543.png 1536w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-12.png 1915w" sizes="(max-width: 674px) 100vw, 674px" /></figure>



<p>The cookie content is consistent with the server side code</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-13.png" alt="" class="wp-image-1921" width="527" height="449" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-13.png 799w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-13-300x256.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-13-768x656.png 768w" sizes="(max-width: 527px) 100vw, 527px" /><figcaption>function CreateCookie in gruyere.py</figcaption></figure>



<p>Our script is very basic, but we could write a more sophisticated one, that would be able to steal user informations contained in the cookie. The next step of the hack is to make the upload link (<a href="https://bit.ly/3jYcVl7)" target="_blank" rel="noreferrer noopener">https://bit.ly/3jYcVl7)</a> available to our victim, and once he clicks on it, this will run the script on his session and steal the data as per the script (with our basic script, we will not be able to retrieve the user data). Since the file we uploaded is on a trusted site, a user will&nbsp;more likely&nbsp;trust the link and click on it. As a summary, the attack looks as follows :</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-16.png" alt="" class="wp-image-1930" width="567" height="306" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-16.png 809w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-16-300x162.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-16-768x415.png 768w" sizes="(max-width: 567px) 100vw, 567px" /><figcaption><a href="https://bit.ly/3gaXmoY" target="_blank" rel="noreferrer noopener">https://bit.ly/3gaXmoY</a></figcaption></figure>



<p>There are many countermeasures detailed by the OWASP : <a href="https://bit.ly/3xVUjqE" target="_blank" rel="noreferrer noopener">https://bit.ly/3xVUjqE</a>. Here below some important ones :</p>



<ul class="wp-block-list"><li><strong><span class="has-inline-color has-vivid-cyan-blue-color">host the content on a</span></strong> <strong><span class="has-inline-color has-vivid-cyan-blue-color">separate domain</span></strong> so the script won&#8217;t have access to any content from your domain. That is, instead of hosting user content on&nbsp;<code>example.com/<em>username</em></code>&nbsp;we would host it at&nbsp;<code><em>username</em>.usercontent.example.com</code>&nbsp;or&nbsp;<code><em>username</em>.example-usercontent.com</code>. (Including something like &#8220;<code>usercontent</code>&#8221; in the domain name avoids attackers registering usernames that look innocent like&nbsp;<code>wwww</code>&nbsp;and using them for phishing attacks.)</li><li>the application should perform <strong><span class="has-inline-color has-vivid-cyan-blue-color">filtering and content checking on any files which are uploaded to the server</span></strong>. Files should be thoroughly scanned and validated before being made available on the server. If in doubt, the file should be discarded</li></ul>



<p>We can see in the Gruyere code that none of these protections are included in the server side</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-17.png" alt="" class="wp-image-1932" width="542" height="363" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-17.png 820w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-17-300x201.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-17-768x514.png 768w" sizes="(max-width: 542px) 100vw, 542px" /></figure>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">Reflected XSS</span></strong></p>



<p>This attack is well documented by the&nbsp;<strong><span class="has-inline-color has-vivid-cyan-blue-color">OWASP Foundation</span></strong>&nbsp;: <a href="https://bit.ly/3CUevwZ" target="_blank" rel="noreferrer noopener">https://bit.ly/3CUevwZ</a></p>



<p>Reflected cross-site scripting arises when an application receives data in an HTTP request and includes that data within the immediate response in an unsafe way. For example : </p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-18.png" alt="" class="wp-image-1936" width="321" height="43" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-18.png 470w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-18-300x40.png 300w" sizes="(max-width: 321px) 100vw, 321px" /><figcaption><a href="https://bit.ly/3xZzivr" target="_blank" rel="noreferrer noopener">https://bit.ly/3xZzivr</a></figcaption></figure>



<p>The questions guide us to type in &#8220;invalid&#8221; in the adress bar. We get an error message as this adress leads to nothing on Gruyere Website</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-26.png" alt="" class="wp-image-1949" width="359" height="144" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-26.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-26-300x120.png 300w" sizes="(max-width: 359px) 100vw, 359px" /></figure>



<p>And we can see in the Developer tools that the code has been inserted</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-25.png" alt="" class="wp-image-1948" width="446" height="215" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-25.png 566w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-25-300x145.png 300w" sizes="(max-width: 446px) 100vw, 446px" /></figure>



<p>In a reflected XSS, an attacker forces the web-application to return an error search result, or any other response that includes some or all of the input provided by the user as part of the request, without that data being made safe to render in the browser, and without permanently storing the user provided data</p>



<p>The questions provide us tips about potential code to type in. Let&#8217;s type again a script such as this one : <em>&lt;script&gt;alert(document.cookie)&lt;/script&gt;</em></p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-22.png" alt="" class="wp-image-1944" width="326" height="94" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-22.png 444w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-22-300x86.png 300w" sizes="(max-width: 326px) 100vw, 326px" /></figure>



<p>Our session cookie is displayed in the message box, and we can also see the script inserted in the Elements inspector</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-24.png" alt="" class="wp-image-1947" width="451" height="247" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-24.png 625w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-24-300x164.png 300w" sizes="(max-width: 451px) 100vw, 451px" /></figure>



<p>This is the demonstration of the Reflected XSS. We could pass this link to a victim and steal its session informations (but we would need a more complex script to retrieve the victim&#8217;s data)</p>



<p>Now, let&#8217;s have a look at the <strong><span class="has-inline-color has-vivid-cyan-blue-color">flaws in the code</span></strong>. One issue is that Gruyere sends us an error message, but the script is included in the output rendered code (as seen before in the Elements inspector)</p>



<p>As per Google statement in the Challenge, one fix is to <strong><span class="has-inline-color has-vivid-cyan-blue-color">escape</span></strong> the user input that is displayed in error messages. Error messages are displayed using&nbsp;<code><a href="https://google-gruyere.appspot.com/code/?resources/error.gtl">error.gtl</a></code>, but are not escaped in the template. The part of the template that renders the message is&nbsp;<code>{{message}}</code>&nbsp;and it&#8217;s missing the modifier that tells it to escape user input. Add the&nbsp;<code>:text</code>&nbsp;modifier to escape the user input. This is called <strong><span class="has-inline-color has-vivid-cyan-blue-color">manual escaping</span></strong></p>



<pre class="wp-block-preformatted">&lt;div class="message"&gt;{{_message:text}}&lt;/div&gt;</pre>



<p>I try to fix this issue by downloading the Gruyere code, modifying it and running it locally</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-29.png" alt="" class="wp-image-1957" width="388" height="244" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-29.png 638w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-29-300x189.png 300w" sizes="(max-width: 388px) 100vw, 388px" /><figcaption>Modification of the code</figcaption></figure>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="194" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-27-1024x194.png" alt="" class="wp-image-1953" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-27-1024x194.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-27-300x57.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-27-768x145.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-27.png 1209w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" /><figcaption>Running Gruyere locally (the session code is new as I switched to Linux during the Challenge)</figcaption></figure>



<p>We can see that the script is escaped to text and the script is not executed</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="161" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-30-1024x161.png" alt="" class="wp-image-1959" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-30-1024x161.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-30-300x47.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-30-768x121.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-30-1536x241.png 1536w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-30.png 1918w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" /></figure>



<p>The simplest and best means to protect an application and their users from XSS bugs is to use a web template system&nbsp;or&nbsp;web application development framework&nbsp;that auto-escapes output and is context-aware</p>



<p>&#8220;<strong><span class="has-inline-color has-vivid-cyan-blue-color">Auto-escaping</span></strong>&#8221; refers to the ability of a template system or web development framework to automatically escape user input in order to prevent any scripts embedded in the input from executing. If you wanted to prevent XSS without auto-escaping, you would have to manually escape input; this means writing your own custom code (or call an escape function) everywhere your application includes user-controlled data. In most cases, manually escaping input is not recommended</p>



<p>&#8220;<strong><span class="has-inline-color has-vivid-cyan-blue-color">Context-aware</span></strong>&#8221; refers to the ability to apply different forms of escaping based on the appropriate context. Because CSS, HTML, URLs, and JavaScript all use different syntax, different forms of escaping are required for each context</p>



<p>Here in the link an article about how the template language <strong><span class="has-inline-color has-vivid-cyan-blue-color">Django</span></strong> handles autoescaping and various other XSS protections : <a href="https://bit.ly/3sGT6CU" target="_blank" rel="noreferrer noopener">https://bit.ly/3sGT6CU</a>. There is no such autoescaping in the GTL language</p>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">Stored XSS</span></strong></p>



<p>This attack is well documented by the&nbsp;<strong><span class="has-inline-color has-vivid-cyan-blue-color">OWASP Foundation</span></strong>&nbsp;: <a href="https://bit.ly/3CUevwZ" target="_blank" rel="noreferrer noopener">https://bit.ly/3CUevwZ</a></p>



<p>As induced by the questions, we can input the following script in the &#8220;New Snippet&#8221; form</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-31.png" alt="" class="wp-image-1962" width="402" height="153" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-31.png 785w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-31-300x115.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-31-768x294.png 768w" sizes="(max-width: 402px) 100vw, 402px" /></figure>



<p>After clicking Submit, we can hover our mouse on the &#8220;read this&#8221; link, and again, we see a pop-up window with our session cookie</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-32.png" alt="" class="wp-image-1963" width="322" height="93" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-32.png 442w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-32-300x86.png 300w" sizes="(max-width: 322px) 100vw, 322px" /></figure>



<p>We can see that our script has been <strong><span class="has-inline-color has-vivid-cyan-blue-color">embedded</span></strong> in the code</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-33.png" alt="" class="wp-image-1965" width="519" height="248" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-33.png 720w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-33-300x143.png 300w" sizes="(max-width: 519px) 100vw, 519px" /></figure>



<p>Any user who would hover its mouse on my snippet would face a risk (but actually stealing any user data would require a more complex script). So, what is wrong with the code ? We do have a <strong><span class="has-inline-color has-vivid-cyan-blue-color">Sanitizer</span></strong>, but obviously it&#8217;s too weak to catch this threat</p>



<p>The call to the Sanitizer is done in this piece of code, inside the Template language GTL</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-34.png" alt="" class="wp-image-1966" width="465" height="392" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-34.png 676w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-34-300x253.png 300w" sizes="(max-width: 465px) 100vw, 465px" /><figcaption>gtl.py</figcaption></figure>



<p>Let&#8217;s have a deeper look at sanitize.py</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-35.png" alt="" class="wp-image-1967" width="475" height="146" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-35.png 696w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-35-300x92.png 300w" sizes="(max-width: 475px) 100vw, 475px" /><figcaption>sanitize.py</figcaption></figure>



<p>The attribute &#8220;onmouseover&#8221; is not in the disallowed attributes. That&#8217;s an obvious flaw. Let&#8217;s add this attribute in the code and let&#8217;s test again</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-37.png" alt="" class="wp-image-1970" width="416" height="94" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-37.png 612w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-37-300x68.png 300w" sizes="(max-width: 416px) 100vw, 416px" /></figure>



<p>Now, the script is not executed, it&#8217;s blocked by this additional disallowed attribute. But, if write the &#8220;ONMOUSEOVER&#8221; in capital letters, the script is executed again</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-36.png" alt="" class="wp-image-1969" width="360" height="152" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-36.png 625w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-36-300x127.png 300w" sizes="(max-width: 360px) 100vw, 360px" /></figure>



<p>So we can see how the Sanitizer is sensitive to upper/lower cases and probably other parameters. Developping our own Sanitizer is surely not a robust method</p>



<p>As per Google, the right approach to HTML sanitization is to :</p>



<ul class="wp-block-list"><li>Parse the input into an intermediate DOM structure, then rebuild the body as well-formed output</li><li>Use strict whitelists for allowed tags and attributes</li><li>Apply strict sanitization of URL and CSS attributes if they are permitted</li></ul>



<p>This is done using a proven <strong><span class="has-inline-color has-vivid-cyan-blue-color">HTML sanitizer</span></strong>, such as this one : <a href="https://bit.ly/3sx15SW" target="_blank" rel="noreferrer noopener">https://bit.ly/3sx15SW</a></p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-38.png" alt="" class="wp-image-1971" width="663" height="270" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-38.png 858w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-38-300x122.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-38-768x312.png 768w" sizes="(max-width: 663px) 100vw, 663px" /></figure>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">Stored XSS via HTML Attribute</span></strong></p>



<p>Let&#8217;s start with a usefull reminder about <strong><span class="has-inline-color has-vivid-cyan-blue-color">HTML attributes</span></strong> : <a href="https://bit.ly/2W5b9a5" target="_blank" rel="noreferrer noopener">https://bit.ly/2W5b9a5</a></p>



<p>Here is an example based upon the <strong><span class="has-inline-color has-vivid-cyan-blue-color">style attribute</span></strong>, allowing to add style to an element, such as <strong><span class="has-inline-color has-vivid-cyan-blue-color">color</span></strong></p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="190" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-39-1024x190.png" alt="" class="wp-image-1974" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-39-1024x190.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-39-300x56.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-39-768x143.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-39.png 1420w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" /></figure>



<p>Now, let&#8217;s start the Challenge. My profile color is green</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-40.png" alt="" class="wp-image-1976" width="306" height="46" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-40.png 503w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-40-300x45.png 300w" sizes="(max-width: 306px) 100vw, 306px" /></figure>



<p>We are totally guided here and just need to type the following script in the profile box</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-41.png" alt="" class="wp-image-1977" width="317" height="36" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-41.png 445w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-41-300x34.png 300w" sizes="(max-width: 317px) 100vw, 317px" /></figure>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-42.png" alt="" class="wp-image-1978" width="488" height="432" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-42.png 905w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-42-300x266.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-42-768x681.png 768w" sizes="(max-width: 488px) 100vw, 488px" /></figure>



<p>The script is launched each time the mouse hovers over the profile name</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-43.png" alt="" class="wp-image-1979" width="300" height="86" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-43.png 444w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-43-300x86.png 300w" sizes="(max-width: 300px) 100vw, 300px" /></figure>



<p>Now, let&#8217;s check in the code where this flaw is occuring. There are two noticeable code sections where colours are managed. The first one is in &#8220;home.gtl&#8221;. We can see that the color parameter is <strong><span class="has-inline-color has-vivid-cyan-blue-color">escaped</span></strong> as follows : <strong><span class="has-inline-color has-vivid-cyan-blue-color">{{color:text}}</span></strong></p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-45-1024x267.png" alt="" class="wp-image-1981" width="701" height="182" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-45-1024x267.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-45-300x78.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-45-768x200.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-45.png 1467w" sizes="(max-width: 701px) 100vw, 701px" /><figcaption>home.gtl</figcaption></figure>



<p>The second one is in &#8220;editprofile.gtl&#8221;. The color parameter is also escaped as follows :<strong><span class="has-inline-color has-vivid-cyan-blue-color">{{_profile.color:text}}</span></strong></p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="146" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-44-1024x146.png" alt="" class="wp-image-1980" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-44-1024x146.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-44-300x43.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-44-768x110.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-44.png 1189w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" /><figcaption>editprofile.gtl</figcaption></figure>



<p>So, how come the script is executed ? The bug is in this code section of glt.py</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-46.png" alt="" class="wp-image-1983" width="452" height="277" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-46.png 765w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-46-300x184.png 300w" sizes="(max-width: 452px) 100vw, 452px" /><figcaption>gtl.py</figcaption></figure>



<p>What is CGI ? <strong><span class="has-inline-color has-vivid-cyan-blue-color">Common Gateway Interface (CGI)</span></strong> is an interface specification that enables web servers to execute an external program, typically to process user requests</p>



<p>A typical use case occurs when a Web user submits a Web form on a web page that uses CGI. The form&#8217;s data is sent to the Web server within an HTTP request with a URL denoting a CGI script. The Web server then launches the CGI script in a new computer process, passing the form data to it. The output of the CGI script, usually in the form of HTML, is returned by the script to the Web server, and the server relays it back to the browser as its response to the browser&#8217;s request</p>



<p>CGI is a rather old technology. It requires some coding effort for complex websites. Nowadays, the <strong><span class="has-inline-color has-vivid-cyan-blue-color">Frameworks</span></strong> such a <strong><span class="has-inline-color has-vivid-cyan-blue-color">Django</span></strong> (Python) will manage the link between the Front-End and Back-End more efficiently</p>



<p>Now, back to the code. During a user input, <strong><span class="has-inline-color has-vivid-cyan-blue-color">cgi.escape</span></strong> is designed to escape the user HTML attribute, considering a <strong><span class="has-inline-color has-vivid-cyan-blue-color">double quote &#8220;</span></strong>, as per this example</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-47.png" alt="" class="wp-image-1986" width="396" height="46" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-47.png 470w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-47-300x35.png 300w" sizes="(max-width: 396px) 100vw, 396px" /><figcaption>code with double quote &#8220;</figcaption></figure>



<p>But in our script, we have just put <strong><span class="has-inline-color has-vivid-cyan-blue-color">single quotes &#8216;</span></strong></p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-41.png" alt="" class="wp-image-1977" width="317" height="36" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-41.png 445w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-41-300x34.png 300w" sizes="(max-width: 317px) 100vw, 317px" /><figcaption>code with single quote &#8216;</figcaption></figure>



<p>That&#8217;s why the script is slipping through the cgi.escape function and is executed</p>



<p>To be noted : cgi.escape will never escape single quotes</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-48.png" alt="" class="wp-image-1987" width="433" height="297" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-48.png 549w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-48-300x206.png 300w" sizes="(max-width: 433px) 100vw, 433px" /><figcaption><a href="https://www.ietf.org/rfc/rfc3875" target="_blank" rel="noreferrer noopener">https://www.ietf.org/rfc/rfc3875</a></figcaption></figure>



<p>Let&#8217;s improve the escape function, that will escape single and double quotes too. As per Google recommendation, let&#8217;s add this function to gtl.py : <strong><span class="has-inline-color has-vivid-cyan-blue-color">_EscapeTextToHtml()</span></strong></p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-49.png" alt="" class="wp-image-1989" width="490" height="325" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-49.png 719w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-49-300x199.png 300w" sizes="(max-width: 490px) 100vw, 490px" /><figcaption>gtl.py</figcaption></figure>



<p>The single quote escape is this line : <strong><span class="has-inline-color has-vivid-cyan-blue-color">&#8216;\&#8221;: &#8216;&amp;#39;&#8217;</span></strong>. You can find some further explanations in this article : <a href="https://bit.ly/3j2tPjk" target="_blank" rel="noreferrer noopener">https://bit.ly/3j2tPjk</a></p>



<p>Let&#8217;s replace cgi.escape by _EscapeTextToHtml()</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-50.png" alt="" class="wp-image-1990" width="450" height="311" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-50.png 643w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-50-300x208.png 300w" sizes="(max-width: 450px) 100vw, 450px" /><figcaption>gtl.py</figcaption></figure>



<p>This is, in my case, efficiently blocking the script (my browser : <strong><span class="has-inline-color has-vivid-cyan-blue-color">Firefox in Kali Linux</span></strong>)</p>



<p>The rest of the questions are applicable for those of you still running a deprecated version of <strong><span class="has-inline-color has-vivid-cyan-blue-color">Internet Explorer</span></strong>, which had some flaws in dealing with <strong><span class="has-inline-color has-vivid-cyan-blue-color">CSS</span></strong> <strong><span class="has-inline-color has-vivid-cyan-blue-color">dynamic properties</span></strong> . Please refer to the explanations provided by Google, as I&#8217;m not going to perform this part of the Challenge</p>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">Stored XSS via AJAX</span></strong></p>



<p>AJAX stands for <strong><span class="has-inline-color has-vivid-cyan-blue-color">Asynchronous&nbsp;JavaScript&nbsp;And&nbsp;XML</span></strong>. AJAX allows web pages to be updated <strong><span class="has-inline-color has-vivid-cyan-blue-color">asynchronously</span></strong> by exchanging data with a web server behind the scenes. This means that it is possible to update parts of a web page, without reloading the whole page</p>



<p>AJAX is not a programming language. It just uses a combination of:</p>



<ul class="wp-block-list"><li>A browser built-in <strong><span class="has-inline-color has-vivid-cyan-blue-color">XMLHttpRequest object</span></strong> (to request data from a web server)</li><li><strong><span class="has-inline-color has-vivid-cyan-blue-color">JavaScript</span></strong> and <strong><span class="has-inline-color has-vivid-cyan-blue-color">HTML DOM</span></strong> (to display or use the data)</li></ul>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-51.png" alt="" class="wp-image-1997" width="423" height="239" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-51.png 727w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-51-300x170.png 300w" sizes="(max-width: 423px) 100vw, 423px" /></figure>



<p>AJAX is quite a misleading name. AJAX applications might use <strong><span class="has-inline-color has-vivid-cyan-blue-color">XML</span></strong> to transport data, but it is equally common to transport data as plain text or <strong><span class="has-inline-color has-vivid-cyan-blue-color">JSON</span></strong> text</p>



<p>Here below an introduction video with some code examples</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="JSON and AJAX Tutorial: With Real Examples" width="525" height="295" src="https://www.youtube.com/embed/rJesac0_Ftw?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p>Gruyere uses AJAX principles to implement <strong><span class="has-inline-color has-vivid-cyan-blue-color">refresh</span></strong> on the home and snippets page</p>



<p>In a real application, refresh would probably happen automatically, but in Gruyere it is made manual. So, the user can be in complete control</p>



<p>When clicking the refresh link, Gruyere fetches <strong><span class="has-inline-color has-vivid-cyan-blue-color">feed.gtl</span></strong> which contains refresh data for the current page and then the client-side script uses the browser <strong><span class="has-inline-color has-vivid-cyan-blue-color">DOM API</span></strong> (<strong><span class="has-inline-color has-vivid-cyan-blue-color">Document Object Model</span></strong>) to insert the new snippets into the page. Here is an introduction video about the DOM, in case of need</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="An Introduction to the DOM (Document Object Model) in JavaScript" width="525" height="295" src="https://www.youtube.com/embed/l-0nPnSvbX8?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p>Since AJAX runs code on the client side, this script is <strong><span class="has-inline-color has-vivid-cyan-blue-color">visible to attackers</span></strong> who do not have access to the source code</p>



<p>Let&#8217;s start the Challenge. We are invited to start a curl request on the feed.gtl page</p>



<p>What is<strong><span class="has-inline-color has-vivid-cyan-blue-color"> curl</span></strong> ? It&#8217;s a command-line tool for transferring data specified with URL syntax. Find out how to use curl by reading&nbsp;<a href="https://curl.se/docs/manpage.html" target="_blank" rel="noreferrer noopener">the curl.1 man page</a>&nbsp;or&nbsp;<a href="https://curl.se/docs/manual.html" target="_blank" rel="noreferrer noopener">the MANUAL document</a>. Find out how to install curl by reading&nbsp;<a href="https://curl.se/docs/install.html" target="_blank" rel="noreferrer noopener">the INSTALL document</a>.</p>



<p><strong><span class="has-inline-color has-vivid-cyan-blue-color">libcurl</span></strong> is the library curl is using to do its job. It is readily available to be used by your software. Read&nbsp;<a href="https://curl.se/libcurl/c/libcurl.html" target="_blank" rel="noreferrer noopener">the libcurl.3 man page</a>&nbsp;to learn how!</p>



<p>The most important part in the code is this one</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-55.png" alt="" class="wp-image-2007" width="416" height="187" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-55.png 828w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-55-300x135.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-55-768x345.png 768w" sizes="(max-width: 416px) 100vw, 416px" /><figcaption>feed.gtl</figcaption></figure>



<p>Here is the output of the curl request on the feed.gtl. The result is consistent with the above code</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-52.png" alt="" class="wp-image-2003" width="451" height="262" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-52.png 650w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-52-300x174.png 300w" sizes="(max-width: 451px) 100vw, 451px" /><figcaption>curl on feed.gtl</figcaption></figure>



<p>We see that the corresponding code has been inserted on the client side </p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-56.png" alt="" class="wp-image-2008" width="584" height="113" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-56.png 681w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-56-300x59.png 300w" sizes="(max-width: 584px) 100vw, 584px" /></figure>



<p>Now let&#8217;s input the <strong><span class="has-inline-color has-vivid-cyan-blue-color">code injection</span></strong> suggested by Google</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-58.png" alt="" class="wp-image-2010" width="261" height="56" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-58.png 312w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-58-300x64.png 300w" sizes="(max-width: 261px) 100vw, 261px" /></figure>



<p>The JSON output of the curl command reads like this. The code is injected</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-59.png" alt="" class="wp-image-2011" width="471" height="301" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-59.png 647w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-59-300x191.png 300w" sizes="(max-width: 471px) 100vw, 471px" /></figure>



<p>Now let&#8217;s click on the <strong><span class="has-inline-color has-vivid-cyan-blue-color">refresh</span></strong> button. There is a pop-up window with the &#8220;1&#8221; prompt. The snippet reads &#8220;all your base&#8221; (that means that our script is &#8220;<strong><span class="has-inline-color has-vivid-cyan-blue-color">invisible</span></strong>&#8220;), the rest of the script enables the pop-up window</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="127" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-57-1024x127.png" alt="" class="wp-image-2009" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-57-1024x127.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-57-300x37.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-57-768x95.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-57-1536x190.png 1536w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-57.png 1769w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" /></figure>



<p>That&#8217;s an evidence of a <strong><span class="has-inline-color has-vivid-cyan-blue-color">stored XSS via AJAX</span></strong>. The flaws are both on server side and client side</p>



<p><strong><span class="has-inline-color has-luminous-vivid-amber-color">Server side</span></strong> : </p>



<p>The code below does not include any sanitizer (<strong><span class="has-inline-color has-vivid-cyan-blue-color">snippet:html</span></strong> or <strong><span class="has-inline-color has-vivid-cyan-blue-color">snippets.0:html</span></strong>)</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-60.png" alt="" class="wp-image-2013" width="449" height="96" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-60.png 781w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-60-300x65.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-60-768x166.png 768w" sizes="(max-width: 449px) 100vw, 449px" /><figcaption>feed.gtl</figcaption></figure>



<p>As Google says, the text is going to be inserted into the <strong><span class="has-inline-color has-vivid-cyan-blue-color">innerHTML</span></strong> of a <strong><span class="has-inline-color has-vivid-cyan-blue-color">DOM</span></strong> node so the HTML does have to be sanitized. However, that sanitized text is then going to be inserted into <strong><span class="has-inline-color has-vivid-cyan-blue-color">JavaScript</span></strong> and therefore single and double quotes have to be escaped too</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-61.png" alt="" class="wp-image-2014" width="505" height="272" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-61.png 861w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-61-300x162.png 300w" sizes="(max-width: 505px) 100vw, 505px" /><figcaption>lib.js</figcaption></figure>



<p><strong><span class="has-inline-color has-luminous-vivid-amber-color">Client side</span></strong> :</p>



<p>A common use of <strong><span class="has-inline-color has-vivid-cyan-blue-color">JSON</span></strong> is&nbsp;to exchange data to/from a web server. When receiving data from a web server, the data is always a string. To become a JavaScript object, we have to parse the data</p>



<p>Gruyere converts the JSON by using <strong><span class="has-inline-color has-vivid-cyan-blue-color">JavaScript</span></strong>&#8216;s <strong><span class="has-inline-color has-vivid-cyan-blue-color">eval()</span></strong> function : <a href="https://bit.ly/3gn4H54" target="_blank" rel="noreferrer noopener">https://bit.ly/3gn4H54</a></p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-62.png" alt="" class="wp-image-2015" width="455" height="243" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-62.png 777w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-62-300x161.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-62-768x411.png 768w" sizes="(max-width: 455px) 100vw, 455px" /></figure>



<p>The eval() function evaluates or executes an argument. If the argument is an expression, eval() evaluates the expression. If the argument is one or more Javascript statements, eval() executes the statements</p>



<p>In modern programming eval is used very sparingly. It’s often said that “eval is evil”</p>



<p>The reason is simple : some time ago, JavaScript was a much weaker language, many things could only be done with eval. But that time is over</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-63.png" alt="" class="wp-image-2018" width="519" height="185" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-63.png 944w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-63-300x107.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-63-768x275.png 768w" sizes="(max-width: 519px) 100vw, 519px" /><figcaption><a href="https://do.co/3szEGV3" target="_blank" rel="noreferrer noopener">https://do.co/3szEGV3</a></figcaption></figure>



<p>Right now, there’s almost no reason to use eval. If someone is using it, there’s a good chance they can replace it with a modern language construct or a JavaScript Module</p>



<p>It is recommended by Google to use the <strong><span class="has-inline-color has-vivid-cyan-blue-color">JSON.parse()</span></strong> function : <a href="https://bit.ly/2WccjjI" target="_blank" rel="noreferrer noopener">https://bit.ly/2WccjjI</a></p>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">Reflected XSS via AJAX</span></strong></p>



<p>This &#8220;reflected XSS via AJAX&#8221; is very close to what we did in the previous paragraph &#8220;Stored XSS via AJAX&#8221;</p>



<p>Google provides us the <span class="has-inline-color has-vivid-cyan-blue-color"><strong>script</strong></span>s to put to the test (the two lines will work in the same way)</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-65-1024x52.png" alt="" class="wp-image-2021" width="591" height="30" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-65-1024x52.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-65-300x15.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-65-768x39.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-65.png 1091w" sizes="(max-width: 591px) 100vw, 591px" /></figure>



<p>The alert box is displayed as usual once we click the <strong><span class="has-inline-color has-vivid-cyan-blue-color">refresh</span></strong> button</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-64.png" alt="" class="wp-image-2020" width="231" height="65" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-64.png 445w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-64-300x84.png 300w" sizes="(max-width: 231px) 100vw, 231px" /></figure>



<p>Contrary to the Stored XSS, there is no code injection on the Server, it&#8217;s done directly in the <strong><span class="has-inline-color has-vivid-cyan-blue-color">Client</span></strong></p>



<p>The flaw is in this section of the code </p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-66-1024x294.png" alt="" class="wp-image-2022" width="575" height="165" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-66-1024x294.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-66-300x86.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-66-768x220.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-66.png 1092w" sizes="(max-width: 575px) 100vw, 575px" /><figcaption>feed.gtl</figcaption></figure>



<p>An <strong><span class="has-inline-color has-vivid-cyan-blue-color">HTML Sanitizer</span></strong> should be included to prevent such script to be executed</p>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">Python HTML Sanitizer</span></strong></p>



<p>For a good security, it&#8217;s best to <strong><span class="has-inline-color has-vivid-cyan-blue-color">rely on a template language</span></strong> and <strong><span class="has-inline-color has-vivid-cyan-blue-color">apply a security technology designed for a template system</span></strong>. A self made Sanitizer will most likely not be a good solution</p>



<p>Therefore, let&#8217;s mention some well known HTML Sanitizers for Python and the template language Django, as Gruyere is based upon a similar technology with GTL</p>



<p>Bleach, is an excellent HTML Sanitizer, doing all the basic work of a Sanitizer. For correct operation inside a template language such as Django, you will need an extra layer provided by a Django HTML Sanitizer</p>



<ul class="wp-block-list"><li><strong><span class="has-inline-color has-vivid-cyan-blue-color">Bleach</span></strong> : <a href="https://github.com/mozilla/bleach" target="_blank" rel="noreferrer noopener">https://github.com/mozilla/bleach</a></li></ul>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-67-1024x191.png" alt="" class="wp-image-2023" width="574" height="106" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-67-1024x191.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-67-300x56.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-67-768x143.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-67.png 1050w" sizes="(max-width: 574px) 100vw, 574px" /></figure>



<ul class="wp-block-list"><li><strong><span class="has-inline-color has-vivid-cyan-blue-color">Django HTML Sanitizer</span></strong> : <a href="https://github.com/ui/django-html_sanitizer" target="_blank" rel="noreferrer noopener">https://github.com/ui/django-html_sanitizer</a></li></ul>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-68-1024x84.png" alt="" class="wp-image-2024" width="588" height="48" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-68-1024x84.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-68-300x25.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-68-768x63.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-68.png 1033w" sizes="(max-width: 588px) 100vw, 588px" /></figure>



<hr class="wp-block-separator"/>



<p><strong><span class="has-inline-color has-vivid-red-color">Client-State Manipulation</span></strong></p>



<p>We should not trust any user data, the browser on the user machine actually sending this data back to our web server</p>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">Elevation of Privilege</span></strong></p>



<p>Privilege escalation or elevation, can be defined as an attack that involves gaining illicit access of elevated rights, or privileges, beyond what is intended or entitled for a user</p>



<p>This attack can involve an external threat actor or an insider. Privilege escalation is a key stage of the cyberattack chain and typically involves the exploitation of a <strong><span class="has-inline-color has-vivid-cyan-blue-color">privilege escalation vulnerability</span></strong>, such as a system bug, misconfiguration, or inadequate access controls</p>



<p>In this Challenge, we are going to elevate our account to <strong><span class="has-inline-color has-vivid-cyan-blue-color">administrator</span></strong>, using a specially crafted user input, and taking advantage of some flaws in Gruyere code</p>



<p>We notice some interesting code in the editprofile.gtl, showing the &#8220;saveprofile&#8221; process</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-71.png" alt="" class="wp-image-2031" width="396" height="171" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-71.png 723w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-71-300x130.png 300w" sizes="(max-width: 396px) 100vw, 396px" /><figcaption>editprofile.gtl</figcaption></figure>



<p>Therefore we can input the following code to our home URL : </p>



<p><strong><span class="has-inline-color has-vivid-cyan-blue-color">/saveprofile?action=update&amp;is_admin=True</span></strong></p>



<p>We then need to log out and log in to update our session cookie. Then, a link &#8220;<strong><span class="has-inline-color has-vivid-cyan-blue-color">Manage this server</span></strong>&#8221; has appeared in our profile. We can input our name :</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-70.png" alt="" class="wp-image-2030" width="302" height="84" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-70.png 487w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-70-300x83.png 300w" sizes="(max-width: 302px) 100vw, 302px" /></figure>



<p>Our profile management page now has the admin and author buttons. That means our <strong><span class="has-inline-color has-vivid-cyan-blue-color">privileges</span></strong> have been <strong><span class="has-inline-color has-vivid-cyan-blue-color">elevated to administrator rights</span></strong></p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-69.png" alt="" class="wp-image-2029" width="433" height="404" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-69.png 730w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-69-300x280.png 300w" sizes="(max-width: 433px) 100vw, 433px" /></figure>



<p>The flaw is that there are no validations of the above user query on the server side. A user ID without admin rights can place the request to become admin, which should not be possible</p>



<p>Here attached a <strong><span class="has-inline-color has-vivid-cyan-blue-color">complete walkthrough</span></strong> of this Challenge</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="An exploratory Technical Web Testing session using Gruyere and Google Chrome" width="525" height="295" src="https://www.youtube.com/embed/bB5naSncI_Q?start=274&#038;feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p>Here below for further reading, some typical <strong><span class="has-inline-color has-vivid-cyan-blue-color">access control vulnerabilites</span></strong> and potential mitigations :</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-72.png" alt="" class="wp-image-2034" width="663" height="179" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-72.png 830w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-72-300x81.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-72-768x208.png 768w" sizes="(max-width: 663px) 100vw, 663px" /><figcaption><a href="https://portswigger.net/web-security/access-control" target="_blank" rel="noreferrer noopener">https://portswigger.net/web-security/access-control</a></figcaption></figure>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">Cookie Manipulation</span></strong></p>



<p>A <strong><span class="has-inline-color has-vivid-cyan-blue-color">stateless protocol</span></strong> is a communication protocol in which the receiver must not retain the session state from previous requests. The sender transfers relevant session state to the receiver in such a way that every request can be understood in isolation, that is without reference to session state from previous requests retained by the receiver</p>



<p>Examples of stateless protocols include the Internet Protocol (IP), which is the foundation for the Internet, and the Hypertext Transfer Protocol (<strong><span class="has-inline-color has-vivid-cyan-blue-color">HTTP</span></strong>), which is the foundation of the World Wide Web</p>



<p>Web server cannot automatically know that two requests are from the same user. For this reason, <strong><span class="has-inline-color has-vivid-cyan-blue-color">cookies</span></strong> were invented</p>



<p>When a web site includes a cookie in a HTTP response, the browser automatically sends the cookie back to the browser on the next request. Web sites can use the cookie to save session state</p>



<p>Cookies are usually <strong><span class="has-inline-color has-vivid-cyan-blue-color">numeric</span></strong> <strong><span class="has-inline-color has-vivid-cyan-blue-color">hashes</span></strong> plaintext variables used by your browser to store that information and communicate it to the server — allowing you to sign in without logging in, because you&#8217;ve already been authenticated by your cookie</p>



<p>If cookies authenticate an individual, then if someone else steals that cookie, they can impersonate the person it&#8217;s tied to — accessing their account, payment information, and other sensitive details without having to know their username or password</p>



<p>Gruyere uses cookies to remember the identity of the logged in user, in this format [<strong><span class="has-inline-color has-vivid-cyan-blue-color">hash|User name|admin|author</span></strong>]</p>



<p>Here is my session cookie visible in <strong><span class="has-inline-color has-vivid-cyan-blue-color">Burp Suite</span></strong> :</p>



<p>Set-Cookie: GRUYERE=112960044|Forensicxs|admin|author; path=/486176820694247485940447649923087546312</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="522" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-78-1024x522.png" alt="" class="wp-image-2046" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-78-1024x522.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-78-300x153.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-78-768x392.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-78.png 1239w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" /></figure>



<p>Now, let&#8217;s create a new account with the user name <strong><span class="has-inline-color has-vivid-cyan-blue-color">foo|admin|author</span></strong> and let&#8217;s see the result in Burp :</p>



<p>Set-Cookie: GRUYERE=19209336|foo|admin|author||author; path=/486176820694247485940447649923087546312</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="520" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-77-1024x520.png" alt="" class="wp-image-2045" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-77-1024x520.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-77-300x152.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-77-768x390.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-77.png 1241w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" /></figure>



<p>What is a <strong><span class="has-inline-color has-vivid-cyan-blue-color">cookie path</span></strong>, and how to define it ? Read below :</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-79.png" alt="" class="wp-image-2047" width="437" height="263" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-79.png 812w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-79-300x180.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-79-768x462.png 768w" sizes="(max-width: 437px) 100vw, 437px" /><figcaption><a href="https://bit.ly/38kmcyi" target="_blank" rel="noreferrer noopener">https://bit.ly/38kmcyi</a></figcaption></figure>



<p>So, in our unique session ID, we have been able, under the same path, to trick Gruyere to issue a cookie that looks like the cookie of <strong><span class="has-inline-color has-vivid-cyan-blue-color">another user</span></strong>. We have also, as a side effect, been able to perform a <strong><span class="has-inline-color has-vivid-cyan-blue-color">privilege escalation</span></strong> as we gained admin rights. By inputing the string (foo|admin|author) into the username field we have successfully created an account which will return a cookie for someone with the username &#8216;foo&#8217; and with admin rights</p>



<p>The code used to parse cookies on the server-side is tolerant to <strong><span class="has-inline-color has-vivid-cyan-blue-color">abnormal cookies</span></strong> &#8212; a cookie string with varying characters and lengths will still be read by the server. This means that an attacker doesn&#8217;t need to know how cookies are parsed on the server-side to pass a malicious cookie</p>



<p>Here are the security recommendations from Google :</p>



<ul class="wp-block-list"><li>The server should <strong><span class="has-inline-color has-vivid-cyan-blue-color">escape</span></strong> the username when it constructs the cookie</li><li>The server should reject a cookie if it doesn&#8217;t match the exact <strong><span class="has-inline-color has-vivid-cyan-blue-color">pattern</span></strong> it is expecting</li></ul>



<p>We can see in the code below that only basic checks are included at the creation and afterwards</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-80.png" alt="" class="wp-image-2053" width="533" height="447" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-80.png 793w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-80-300x252.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-80-768x646.png 768w" sizes="(max-width: 533px) 100vw, 533px" /><figcaption>gruyere.py</figcaption></figure>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-83.png" alt="" class="wp-image-2063" width="503" height="292" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-83.png 901w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-83-300x174.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-83-768x447.png 768w" sizes="(max-width: 503px) 100vw, 503px" /><figcaption>gruyere.py</figcaption></figure>



<p>Here further reading about <strong><span class="has-inline-color has-vivid-cyan-blue-color">Cookie Security</span></strong> : <a href="https://bit.ly/3JlQMJu" target="_blank" rel="noreferrer noopener">https://bit.ly/3JlQMJu</a></p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/12/image-85.png" alt="" class="wp-image-2639" width="496" height="292" srcset="https://www.forensicxs.com/wp-content/uploads/2021/12/image-85.png 847w, https://www.forensicxs.com/wp-content/uploads/2021/12/image-85-300x177.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/12/image-85-768x452.png 768w" sizes="(max-width: 496px) 100vw, 496px" /><figcaption><a href="https://bit.ly/3JlQMJu" target="_blank" rel="noreferrer noopener">https://bit.ly/3JlQMJu</a></figcaption></figure>



<p>Nowadays, <strong><span class="has-inline-color has-vivid-cyan-blue-color">Web Application Firewalls (WAF)</span></strong> are putting protections against cookie related attacks, such as this one : <a href="https://bit.ly/3jpaZD5" target="_blank" rel="noreferrer noopener">https://bit.ly/3jpaZD5</a></p>



<p>Now, let&#8217;s have a closer look to the <strong><span class="has-inline-color has-vivid-cyan-blue-color">cookie hash</span></strong> function :</p>



<p><strong><span class="has-inline-color has-vivid-cyan-blue-color">h_data = str(hash(cookie_secret + c_data) &amp; 0x7FFFFFF)</span></strong></p>



<ul class="wp-block-list"><li>cookie_secret : is a static string (which is just &#8221; by default, that means an empty string is the cookie secret), used as initialization vector or salt</li><li>c_data : is the username</li><li>&amp; 0x7FFFFFF : AND operator with Hex 0x7FFFFFF</li><li>str(hash()) : string hashing function</li><li>h_data : hashed username</li></ul>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-81.png" alt="" class="wp-image-2056" width="471" height="95" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-81.png 740w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-81-300x61.png 300w" sizes="(max-width: 471px) 100vw, 471px" /><figcaption>Reminder : AND operator <strong>&amp;</strong></figcaption></figure>



<p>Python&#8217;s&nbsp;<code>hash()</code>&nbsp;is not fit for the purpose &#8211; or let&#8217;s say &#8220;insecure&#8221; in this context &#8211; because it&#8217;s possible to find <strong><span class="has-inline-color has-vivid-cyan-blue-color">cryptographic collisions</span></strong>. It is not a bug in Python, it&#8217;s just that it is not what it&#8217;s designed for in this use case</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-82.png" alt="" class="wp-image-2059" width="420" height="48" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-82.png 612w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-82-300x34.png 300w" sizes="(max-width: 420px) 100vw, 420px" /></figure>



<p>This  <code>hash()</code> function is used in Python&#8217;s <strong><span class="has-inline-color has-vivid-cyan-blue-color">dictionaries hash tables</span></strong>, where you can&#8217;t &#8220;afford&#8221; a fully secure hash function, because it would slow down so much the calculations and the use of these dictionaries</p>



<p>Here a video explaining in detail these hash tables and collisions</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Brandon Rhodes: The Mighty Dictionary (PyCon 2010)" width="525" height="394" src="https://www.youtube.com/embed/oMyy4Sm0uBs?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p>Python does provide secure hash functions in the <strong><span class="has-inline-color has-vivid-cyan-blue-color">hashlib</span></strong> module : <a href="https://bit.ly/3gK3hlb" target="_blank" rel="noreferrer noopener">https://bit.ly/3gK3hlb</a>. They are used each time a cryptographic secure application has to be implemented</p>



<p>Because of it&#8217;s lack of cookie protection, Gruyere is also prone to <strong><span class="has-inline-color has-vivid-cyan-blue-color">replay attacks</span></strong> : <a href="https://bit.ly/2WzSdjQ" target="_blank" rel="noreferrer noopener">https://bit.ly/2WzSdjQ</a></p>



<hr class="wp-block-separator"/>



<p><strong><span class="has-inline-color has-vivid-red-color">Cross-Site Request Forgery (XSRF/CSRF)</span></strong></p>



<p>Cross-site request forgery (also known as XSRF/CSRF) is a web security vulnerability that allows an attacker to induce users to perform actions that they do not intend to perform. It allows an attacker to partly circumvent the <strong><span class="has-inline-color has-vivid-cyan-blue-color">same origin policy</span></strong>, which is designed to prevent different websites from interfering with each other</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-84.png" alt="" class="wp-image-2065" width="600" height="321" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-84.png 784w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-84-300x161.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-84-768x412.png 768w" sizes="(max-width: 600px) 100vw, 600px" /><figcaption><a href="https://bit.ly/3mJmyHa" target="_blank" rel="noreferrer noopener">https://bit.ly/3mJmyHa</a></figcaption></figure>



<p>Let&#8217;s look at the URL used to delete a snippet. For this, let&#8217;s actually delete our snippet and check the result in <strong><span class="has-inline-color has-vivid-cyan-blue-color">Burp Suite</span></strong></p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="577" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-85-1024x577.png" alt="" class="wp-image-2067" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-85-1024x577.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-85-300x169.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-85-768x432.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-85.png 1245w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" /><figcaption>Burp Suite</figcaption></figure>



<p>We find the GET request : <strong><span class="has-inline-color has-vivid-cyan-blue-color">/deletesnippet?index=0</span></strong></p>



<p>So now we can easily simulate a CSRF attack. We can put the complete URL <em>https://google-gruyere.appspot.com/486176820694247485940447649923087546312/ deletesnippet?index=0</em> in our Gruyere icon, using the <strong><span class="has-inline-color has-vivid-cyan-blue-color">Edit Profile</span></strong> feature</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-86.png" alt="" class="wp-image-2069" width="509" height="121" srcset="https://www.forensicxs.com/wp-content/uploads/2021/08/image-86.png 943w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-86-300x72.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/08/image-86-768x183.png 768w" sizes="(max-width: 509px) 100vw, 509px" /><figcaption>Gruyere : Profile</figcaption></figure>



<p>You can check by yourself, that each time you will put a snippet in your page, and refresh the home page, the snippet will be automatically deleted</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/08/image-87.png" alt="" class="wp-image-2070" width="162" height="58"/></figure>



<p>To trigger the attack, we could imagine luring a victim to browse a page where this URL is embedded</p>



<p>Now, let&#8217;s look into the code. In the Edit Profile form, the code is accepting whatever <strong><span class="has-inline-color has-vivid-cyan-blue-color">text</span></strong> we are typing without any check</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-2-1024x163.png" alt="" class="wp-image-2074" width="652" height="103" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-2-1024x163.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-2-300x48.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-2-768x122.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-2.png 1211w" sizes="(max-width: 652px) 100vw, 652px" /><figcaption>editprofile.gtl</figcaption></figure>



<p>The Edit Profile code uses the <strong><span class="has-inline-color has-vivid-cyan-blue-color">GET Method</span></strong> in the user input forms</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-3.png" alt="" class="wp-image-2075" width="497" height="33" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-3.png 787w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-3-300x20.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-3-768x52.png 768w" sizes="(max-width: 497px) 100vw, 497px" /><figcaption>editprofile.gtl</figcaption></figure>



<p>When we include  <em>deletesnippet?index=0</em>  in the icon form, and after refresh, this triggers an action on the server with the function <strong><span class="has-inline-color has-vivid-cyan-blue-color">def _DoDeletesnippet</span></strong></p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-4.png" alt="" class="wp-image-2076" width="514" height="235" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-4.png 941w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-4-300x138.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-4-768x353.png 768w" sizes="(max-width: 514px) 100vw, 514px" /><figcaption>gruyere.py</figcaption></figure>



<p>The deletion of our snippet is then handled via this code</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-5-1024x454.png" alt="" class="wp-image-2077" width="546" height="241" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-5-1024x454.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-5-300x133.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-5-768x341.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-5.png 1071w" sizes="(max-width: 546px) 100vw, 546px" /><figcaption>snippets.gtl</figcaption></figure>



<p>We find that Grueyere has a <strong><span class="has-inline-color has-vivid-cyan-blue-color">systematic flaw</span></strong>, which is the use of GET request instead of POST request, for sending and updating sensitive data</p>



<p>GET is used for viewing something, without changing it, while POST is used for changing something. For example, a search page should use GET to get data, while a form that changes your password should use POST. Essentially GET is used to retrieve remote data, and POST is used to insert/update remote data</p>



<p><strong><span class="has-inline-color has-vivid-cyan-blue-color">GET request</span></strong> retrieves a representation of the specified resource and include all required data in the URL. For example :</p>



<p>https://www.example.com/login.php?user=myuser&#038;pass=mypass</p>



<p><strong><span class="has-inline-color has-vivid-cyan-blue-color">POST request</span></strong> is for writing and submit data to be processed (for example from an HTML form) to the identified resource. This may result in the creation of a new resource or the updates of existing resources or both. It may have side effects using the same request several times because this will likely result in multiple writes. Browsers typically give you warnings about this. POST is not fully secure, the data is included in the body of the request instead of the URL but it is still possible to view/edit</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image.png" alt="" class="wp-image-2072" width="319" height="105" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image.png 463w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-300x98.png 300w" sizes="(max-width: 319px) 100vw, 319px" /></figure>



<p>Here is a quick summary :</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-6.png" alt="" class="wp-image-2078" width="505" height="204" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-6.png 720w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-6-300x121.png 300w" sizes="(max-width: 505px) 100vw, 505px" /><figcaption><a href="https://bit.ly/3zMhN3w" target="_blank" rel="noreferrer noopener">https://bit.ly/3zMhN3w</a></figcaption></figure>



<p>A first action would be to change the GET to a POST request, as the GET method is not appropriate in this context. But, this will definitely not be sufficient</p>



<p>Here are a set of <strong><span class="has-inline-color has-vivid-cyan-blue-color">countermeasures</span></strong> to apply :</p>



<ul class="wp-block-list"><li>Enumerate the form values, evaluate that no extraneous fields show up, and <strong><span class="has-inline-color has-vivid-cyan-blue-color">sanitize</span></strong> and filter on expected values</li><li>CSRF <strong><span class="has-inline-color has-vivid-cyan-blue-color">tokens</span></strong> help against arbitrary form submission bots</li></ul>



<p>We have already seen sanitizing in the previous chapters. Let&#8217;s go deeper in the CSRF tokens</p>



<p>To avoid a CSRF attack, a potential solution is to <strong><span class="has-inline-color has-vivid-cyan-blue-color">embed additional authentication data</span></strong> into the HTTP request, so the web application will be able to detect any unauthorized requests crafted by an attacker and placed into a form</p>



<p>CSRF tokens are typically <strong><span class="has-inline-color has-vivid-cyan-blue-color">random numbers</span></strong> that are stored in a cookie or on a server. What will happen is the server will compare the token attached to the incoming requests with the value stored in the cookie or the server. If the values are identical, the server will approve the request. Similarly, it will reject the request if the token is missing or is incorrect</p>



<p>Google proposes to pass an <strong><span class="has-inline-color has-vivid-cyan-blue-color">action_token</span></strong> in all HTML requests, and use a hash of the value of the user&#8217;s cookie appended to a current timestamp (the timestamp in the hash will ensure that old tokens can be expired, which mitigates the risk if it leaks). The POST request will mitigate the risk to pass&nbsp;<code>action_token</code>&nbsp;as a URL parameter and let it leak</p>



<p>Here is the proposed code :</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-7.png" alt="" class="wp-image-2081" width="497" height="222" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-7.png 788w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-7-300x134.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-7-768x343.png 768w" sizes="(max-width: 497px) 100vw, 497px" /><figcaption>token valid for 24 hours</figcaption></figure>



<p>With such a token, an attacker would also need to guess the token to successfully trick a victim into sending a forged request</p>



<p>For an anti-CSRF mechanism to be effective, it needs to be <strong><span class="has-inline-color has-vivid-cyan-blue-color">cryptographically secure</span></strong>. The token cannot be easily guessed, so it cannot be generated based on a predictable pattern</p>



<p>It is recommended to use anti-CSRF options in popular <strong><span class="has-inline-color has-vivid-cyan-blue-color">frameworks such as AngularJS</span></strong> (<a href="https://bit.ly/3yMmGYO" target="_blank" rel="noreferrer noopener">https://bit.ly/3yMmGYO</a>) and refrain from creating own mechanisms</p>



<p>As a last word, you can find here a good summary how to <strong><span class="has-inline-color has-vivid-cyan-blue-color">protect your forms</span></strong> from malicious inputs : <a href="https://bit.ly/3kRgav7" target="_blank" rel="noreferrer noopener">https://bit.ly/3kRgav7</a></p>



<hr class="wp-block-separator"/>



<p><strong><span class="has-inline-color has-vivid-red-color">Cross Site Script Inclusion (XSSI)</span></strong></p>



<p>XSSI is a client-side attack similar to Cross Site Request Forgery (CSRF) but has a different purpose. Where CSRF uses the authenticated user context to execute certain state-changing actions inside a victim’s page (reset password, etc.), XSSI instead uses <strong><span class="has-inline-color has-vivid-cyan-blue-color">JavaScript</span></strong> on the client side to <strong><span class="has-inline-color has-vivid-cyan-blue-color">leak sensitive data</span></strong> from authenticated sessions</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-15.png" alt="" class="wp-image-2092" width="428" height="226" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-15.png 563w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-15-300x158.png 300w" sizes="(max-width: 428px) 100vw, 428px" /><figcaption>Principles of an XSSI</figcaption></figure>



<p>Let&#8217;s follow the example provided by Google. Here is my <strong><span class="has-inline-color has-vivid-cyan-blue-color">private snippet</span></strong> on my home page. This is the &#8220;sensitive information&#8221; that we are going to leak</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-14.png" alt="" class="wp-image-2090" width="252" height="44" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-14.png 468w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-14-300x53.png 300w" sizes="(max-width: 252px) 100vw, 252px" /><figcaption>my private snippet</figcaption></figure>



<p>We can see that the /feed.gtl discloses informations about our private snippet, as already seen earlier in this article</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-13.png" alt="" class="wp-image-2089" width="552" height="81" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-13.png 850w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-13-300x44.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-13-768x113.png 768w" sizes="(max-width: 552px) 100vw, 552px" /><figcaption>private snippet in feed.gtl</figcaption></figure>



<p>The following code will take over my private snippet content and display it in an alert text box, using Javascript. The HTTP adress points to my <strong><span class="has-inline-color has-vivid-cyan-blue-color">local server 127.0.0.1:8008</span></strong> and my private session, as I&#8217;m running Gruyere locally for this XSSI exploit</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-12.png" alt="" class="wp-image-2088" width="508" height="221" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-12.png 908w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-12-300x131.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-12-768x334.png 768w" sizes="(max-width: 508px) 100vw, 508px" /><figcaption>Exploit.html</figcaption></figure>



<p>My <strong><span class="has-inline-color has-vivid-cyan-blue-color">Exploit.html</span></strong> is located in my root Gruyere directory (resources)</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-16.png" alt="" class="wp-image-2093" width="452" height="263" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-16.png 635w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-16-300x175.png 300w" sizes="(max-width: 452px) 100vw, 452px" /></figure>



<p>The content of my private snippet is shown in the alert box. That&#8217;s our sensitive data leak</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-10.png" alt="" class="wp-image-2086" width="219" height="99" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-10.png 378w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-10-300x136.png 300w" sizes="(max-width: 219px) 100vw, 219px" /><figcaption>script alert</figcaption></figure>



<p>Here below some potential <strong><span class="has-inline-color has-vivid-cyan-blue-color">countermeasures</span></strong> :</p>



<ul class="wp-block-list"><li>Use a CSRF token (as discussed earlier), to make sure that JSON results containing confidential data are only returned to your own pages</li><li>JSON response pages should only support POST requests, which prevents the script from being loaded via a script tag</li><li>Make sure that the script is not executable (with sanitizing). The standard way of doing this is to append some non-executable prefix to it. A script running in the same domain can read the contents of the response and strip out the prefix, but scripts running in other domains can&#8217;t</li></ul>



<p>Here are more XSSI examples on the <strong><span class="has-inline-color has-vivid-cyan-blue-color">OWASP</span></strong> site : <a href="https://bit.ly/3kTbBAu" target="_blank" rel="noreferrer noopener">https://bit.ly/3kTbBAu</a></p>



<p>You can also check this video from blackhat Europe that provides more explanations</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Your Scripts In My Page - What Could Possibly Go Wrong?" width="525" height="295" src="https://www.youtube.com/embed/Mnkgg3q51Ps?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<hr class="wp-block-separator"/>



<p><strong><span class="has-inline-color has-vivid-red-color">Path Trasversal</span></strong></p>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">Information disclosure via path travsersal</span></strong></p>



<p>A common attacker technique is Path Traversal to access files outside of the intended directory : <a href="https://bit.ly/3BKWuzF" target="_blank" rel="noreferrer noopener">https://bit.ly/3BKWuzF</a></p>



<p>An attacker may be able to read an unintended file, resulting in information disclosure of sensitive data. Or, an attacker may be able to write to an unintended file, resulting in unauthorized modification of sensitive data or <strong><span class="has-inline-color has-vivid-cyan-blue-color">compromising</span></strong> the server&#8217;s security</p>



<p>Modern web applications and web servers usually contain quite a bit of information in addition to the standard HTML and CSS, including scripts, images, templates, and <strong><span class="has-inline-color has-vivid-cyan-blue-color">configuration files</span></strong>. A web server typically restricts the user from accessing anything higher than the root directory, or web document root, on the server&#8217;s file system</p>



<p>A <strong><span class="has-inline-color has-vivid-cyan-blue-color">secret</span></strong> is an object that contains a small amount of sensitive data such as a password, a token, or a key. Using a secret means that you don&#8217;t need to include confidential data in your application code</p>



<p>A Path Trasversal attack will target stored secrets, among other things</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-17.png" alt="" class="wp-image-2102" width="435" height="460" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-17.png 614w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-17-283x300.png 283w" sizes="(max-width: 435px) 100vw, 435px" /><figcaption><a href="https://bit.ly/3yKphTm" target="_blank" rel="noreferrer noopener">https://bit.ly/3yKphTm</a></figcaption></figure>



<p>Let&#8217;s start Burp Suite and check my Gruyere session <strong><span class="has-inline-color has-vivid-cyan-blue-color">site map</span></strong>. For this the easiest is to use the Burp browser (inside the App), as it will manage the proxy for you, and intercept the HTTP requests. Here is the result :</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-18.png" alt="" class="wp-image-2103" width="277" height="303" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-18.png 353w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-18-274x300.png 274w" sizes="(max-width: 277px) 100vw, 277px" /><figcaption>site map in Burp</figcaption></figure>



<p>We can see that there is a <strong><span class="has-inline-color has-vivid-cyan-blue-color">secret.txt</span></strong> file, that&#8217;s our target. Let&#8217;s see if Gruyere is sensitive to Path Trasversal attacks</p>



<p>Let&#8217;s try with the upload.gtl module. Normally we should not be able to access the code&#8230;but we can !</p>



<p>Here is the result when we enter <strong><span class="has-inline-color has-vivid-cyan-blue-color">/upload.gtl</span></strong> (expected behaviour)</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-20.png" alt="" class="wp-image-2107" width="241" height="88" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-20.png 420w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-20-300x110.png 300w" sizes="(max-width: 241px) 100vw, 241px" /></figure>



<p>Let&#8217;s go down a level and type in <strong><span class="has-inline-color has-vivid-cyan-blue-color">/upload.gtl/test</span></strong>, the result is as follows, as this file &#8220;test&#8221; does not exist in this hierarchy</p>



<figure class="wp-block-image size-full"><img decoding="async" width="1003" height="77" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-21.png" alt="" class="wp-image-2108" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-21.png 1003w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-21-300x23.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-21-768x59.png 768w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" /></figure>



<p>Now, let&#8217;s move one level back with <strong><span class="has-inline-color has-vivid-cyan-blue-color">/upload/test/../</span></strong>, and here is the result. This confirms that Gruyere is vulnerable to Path Trasversal</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-19.png" alt="" class="wp-image-2106" width="561" height="389" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-19.png 798w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-19-300x209.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-19-768x534.png 768w" sizes="(max-width: 561px) 100vw, 561px" /></figure>



<p>Now let&#8217;s find the content of the secret.txt file. I&#8217;m on Chrome, so this may not work exactly the same way on your browser. Chrome does not accept the plain ../ command, but we can easily trick the browser with the <strong><span class="has-inline-color has-vivid-cyan-blue-color">hexadecimal</span></strong> translation of the slash / into 0x2f or %2f</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-23.png" alt="" class="wp-image-2111" width="300" height="125" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-23.png 622w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-23-300x125.png 300w" sizes="(max-width: 300px) 100vw, 300px" /></figure>



<p>Let&#8217;s type in <strong><span class="has-inline-color has-vivid-cyan-blue-color">/secret.txt</span></strong>. This returns the error message as above</p>



<p>Now, let&#8217;s step up with the path <strong><span class="has-inline-color has-vivid-cyan-blue-color">/..%2fsecret.txt</span></strong>. We find the content of the secret.txt file is <strong><span class="has-inline-color has-vivid-cyan-blue-color">Cookie!</span></strong></p>



<figure class="wp-block-image size-full"><img decoding="async" width="857" height="74" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-24.png" alt="" class="wp-image-2112" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-24.png 857w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-24-300x26.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-24-768x66.png 768w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" /></figure>



<p>An additional note : here is a usefull reminder about commands to move in a <strong><span class="has-inline-color has-vivid-cyan-blue-color">file system</span></strong></p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-22.png" alt="" class="wp-image-2109" width="434" height="126" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-22.png 634w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-22-300x88.png 300w" sizes="(max-width: 434px) 100vw, 434px" /><figcaption><a href="https://red.ht/3kVUAFK" target="_blank" rel="noreferrer noopener">https://red.ht/3kVUAFK</a></figcaption></figure>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">Data tampering via path trasversal</span></strong></p>



<p>Now that we have found that Gruyere is vulnerable to path trasversal, we can easily craft a data tampering attack, by changing the content of the secret.txt file. I have chosen &#8220;Path Trasversal&#8221; in my file. First, we must upload the file in our session</p>



<p>Now, let&#8217;s repeat the actions from the previous paragraph, to launch the path trasversal attack :</p>



<p><strong><span class="has-inline-color has-vivid-cyan-blue-color">/secret.txt</span></strong></p>



<p><strong><span class="has-inline-color has-vivid-cyan-blue-color">/..%2fsecret.txt</span></strong></p>



<p>We find that the secret.txt file has been replaced by the new one</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-25.png" alt="" class="wp-image-2113" width="540" height="66" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-25.png 774w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-25-300x37.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-25-768x95.png 768w" sizes="(max-width: 540px) 100vw, 540px" /></figure>



<p>Let&#8217;s conclude this chapter by a few <strong><span class="has-inline-color has-vivid-cyan-blue-color">countermeasures</span></strong></p>



<ul class="wp-block-list"><li>don’t store <strong><span class="has-inline-color has-vivid-cyan-blue-color">sensitive</span></strong> files on your web server. The only files that should be in your document root folder are those that are needed for the site to function properly</li><li>make sure you’re running the latest <strong><span class="has-inline-color has-vivid-cyan-blue-color">versions</span></strong> of your web server</li><li><strong><span class="has-inline-color has-vivid-cyan-blue-color">sanitize</span></strong> any user input. Remove everything but the known good data and filter meta characters from the user input. This will ensure that attackers cannot use commands that try to escape the root directory or violate other access privileges</li><li>remove “<strong><span class="has-inline-color has-vivid-cyan-blue-color">..</span></strong>” and “<strong><span class="has-inline-color has-vivid-cyan-blue-color">../</span></strong>” from any input that is used in a file context</li><li>ensure that your web server is properly <strong><span class="has-inline-color has-vivid-cyan-blue-color">configured</span></strong> to allow public access to only those directories that are needed for the site to function</li></ul>



<hr class="wp-block-separator"/>



<p><strong><span class="has-inline-color has-vivid-red-color">Denial of Service</span></strong></p>



<p>Here we will try some tricks to prevent the Gruyere server from servicing requests, by taking advantage of some server code bugs</p>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">DoS &#8211; Quit the Server</span></strong></p>



<p>As we are logged in as admin (from previous privilege escalation achieved in this article), let&#8217;s check how to request a server quit command. This is to be found in the &#8220;Manage this server&#8221; section</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-29.png" alt="" class="wp-image-2118" width="293" height="99" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-29.png 633w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-29-300x101.png 300w" sizes="(max-width: 293px) 100vw, 293px" /></figure>



<p> We find in the address bar that it is handled by the manage.gtl </p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-30.png" alt="" class="wp-image-2119" width="505" height="368" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-30.png 689w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-30-300x219.png 300w" sizes="(max-width: 505px) 100vw, 505px" /><figcaption>manage.gtl</figcaption></figure>



<p>Now let&#8217;s create a new account without admin rights. We notice that it is still easy to ask the Gruyere server to quit. Just type in <strong><span class="has-inline-color has-vivid-cyan-blue-color">/quitserver </span></strong></p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-27.png" alt="" class="wp-image-2116" width="554" height="65" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-27.png 764w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-27-300x35.png 300w" sizes="(max-width: 554px) 100vw, 554px" /></figure>



<p>Let&#8217;s check how we can achieve this while we are not logged in as <strong><span class="has-inline-color has-vivid-cyan-blue-color">admin</span></strong>. The key question is how Gruyere is preventing this query to achieve its goal</p>



<p>In fact, Gruyere does include some so called &#8220;<strong><span class="has-inline-color has-vivid-cyan-blue-color">Protected URL</span></strong>s&#8221; in the server code</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-31.png" alt="" class="wp-image-2120" width="419" height="72" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-31.png 586w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-31-300x52.png 300w" sizes="(max-width: 419px) 100vw, 419px" /><figcaption>gruyere.py</figcaption></figure>



<p>What is this ? A website is, in general, available to the public. But there could be a need to have a seperate area that is NOT available to the public. That&#8217;s where the Protected URL comes in. It allows to make a certain directory of a site not available to the public, and instead, prompt the visitor for a <strong><span class="has-inline-color has-vivid-cyan-blue-color">username</span></strong> and <strong><span class="has-inline-color has-vivid-cyan-blue-color">password</span></strong></p>



<p>Let&#8217;s solve the bug by adding /quitserver to the Protected URLs</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-32.png" alt="" class="wp-image-2123" width="345" height="86" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-32.png 554w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-32-300x75.png 300w" sizes="(max-width: 345px) 100vw, 345px" /><figcaption>gruyere.py</figcaption></figure>



<p>Because of the below code, Gruyere will send back an &#8220;<strong><span class="has-inline-color has-vivid-cyan-blue-color">invalid request</span></strong>&#8221; message when you try to type in a protected URL</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-33.png" alt="" class="wp-image-2124" width="453" height="59" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-33.png 717w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-33-300x40.png 300w" sizes="(max-width: 453px) 100vw, 453px" /><figcaption>gruyere.py</figcaption></figure>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">DoS &#8211; Overloading the Server</span></strong></p>



<p>We need to find a way to overload the server when a request is processed. For this, we have seen that Gruyere is vulnerable to Path Trasversal attacks</p>



<p>To overload the server, one idea is to use a resource that will put Gruyere in a kind of &#8220;infinite loop&#8221;, with a request repeating without end, whatever we click in our session</p>



<p>We see that the <strong><span class="has-inline-color has-vivid-cyan-blue-color">menubar.gtl</span></strong> file is in every page we navigate, so this makes a good candidate for this attack</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-34.png" alt="" class="wp-image-2126" width="570" height="69" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-34.png 831w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-34-300x37.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-34-768x94.png 768w" sizes="(max-width: 570px) 100vw, 570px" /><figcaption>menubar.gtl</figcaption></figure>



<p>We can create a file named menubar.gtl, that will be replacing the existing one, with the following content</p>



<pre class="wp-block-preformatted">[[include:menubar.gtl]]DoS[[/include:menubar.gtl]]</pre>



<p>We can upload and replace the existing menubar.gtl, using a Path Trasversal attack. We can create a new user called <strong><span class="has-inline-color has-vivid-cyan-blue-color">../resources</span></strong>, then upload the file using this user profile. This will implement the attack on the resources directory and copy-paste the new file in there</p>



<p>Here is the result, this loop repeats itself, each time we perform a refresh or navigate in the site</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-37.png" alt="" class="wp-image-2130" width="271" height="140" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-37.png 526w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-37-300x155.png 300w" sizes="(max-width: 271px) 100vw, 271px" /></figure>



<p>We need to use the &#8220;<strong><span class="has-inline-color has-vivid-cyan-blue-color">reset button</span></strong>&#8221; to stop this loop</p>



<pre class="wp-block-preformatted">https://google-gruyere.appspot.com/resetbutton/session ID</pre>



<p>The potential fix has been described earlier in the Path Trasversal section</p>



<hr class="wp-block-separator"/>



<p><strong><span class="has-inline-color has-vivid-red-color">Code Execution</span></strong></p>



<p>Google tells us to use two previous exploits to execute code. We will therefore use <strong><span class="has-inline-color has-vivid-cyan-blue-color">Path Trasversal</span></strong> and <strong><span class="has-inline-color has-vivid-cyan-blue-color">Denial of Service</span></strong></p>



<p>The general idea here is to take advantage of these vulnerabilities, to attack the Gruyere <strong><span class="has-inline-color has-vivid-cyan-blue-color">infrastructure</span></strong>. How to do that ? The GTL <strong><span class="has-inline-color has-vivid-cyan-blue-color">template language</span></strong> is a target of choice, as GTL is shaping the entire Gruyere web site. Modifying the GTL language can permanently alter the site and put it down. We will leverage this attack using the Path Trasversal and Denial of Service</p>



<p>We are therefore going to replace the &#8220;gtl.py&#8221; file with our own, and &#8220;rewrite&#8221; the site&#8217;s infrastructure and thus &#8220;own&#8221; the application</p>



<p>The content of the GTL file can be anything. I just wrote in an empty file &#8220;Code Execution Challange&#8221; and named it <strong><span class="has-inline-color has-vivid-cyan-blue-color">gtl.py</span></strong></p>



<p>Then I prepared the Path Trasversal attack by creating the <strong><span class="has-inline-color has-vivid-cyan-blue-color">user</span></strong> <strong><span class="has-inline-color has-vivid-cyan-blue-color">..</span></strong>, and uploading my file in this profile</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="195" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-40-1024x195.png" alt="" class="wp-image-2138" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-40-1024x195.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-40-300x57.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-40-768x146.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-40-1536x292.png 1536w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-40.png 1794w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" /></figure>



<p>Then, I restart the server by typing /quitserver. Gruyer puts the following message :  <strong><span class="has-inline-color has-vivid-cyan-blue-color">the server has been 0wnd!</span></strong> I have found a way to attack the infrastructure and &#8220;own&#8221; the server, by replacing the gtl.py file</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-41.png" alt="" class="wp-image-2139" width="241" height="225" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-41.png 434w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-41-300x281.png 300w" sizes="(max-width: 241px) 100vw, 241px" /></figure>



<p>There are several flaws in Gruyer code :</p>



<ul class="wp-block-list"><li>gruyere allows users to upload a file with the .py extension (Python file). This should be blocked by a proper <strong><span class="has-inline-color has-vivid-cyan-blue-color">sanitization</span></strong>, as seen previously</li><li>gruyere should be modified for <strong><span class="has-inline-color has-vivid-cyan-blue-color">path trasversal</span></strong> flaws, as seen above</li><li>gruyere has permission to both read and write files in the gruyere directory. This should not be the case, and gruyere should run <strong><span class="has-inline-color has-vivid-cyan-blue-color">minimal privileges</span></strong> (<a href="https://bit.ly/3typbgB" target="_blank" rel="noreferrer noopener">https://bit.ly/3typbgB</a>)</li><li>more generally and for a real world site, your <strong><span class="has-inline-color has-vivid-cyan-blue-color">infrastructure</span></strong> should be <strong><span class="has-inline-color has-vivid-cyan-blue-color">updated</span></strong> (such as <strong><span class="has-inline-color has-vivid-cyan-blue-color">libraries</span></strong> imported by your code), to avoid typical vulnerabilities</li></ul>



<p>In the Gruyere code, the following code section should be modified to restrict the possibilities to <strong><span class="has-inline-color has-vivid-cyan-blue-color">write file</span></strong></p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-42.png" alt="" class="wp-image-2143" width="539" height="480" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-42.png 790w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-42-300x268.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-42-768x685.png 768w" sizes="(max-width: 539px) 100vw, 539px" /><figcaption>gruyere.py</figcaption></figure>



<hr class="wp-block-separator"/>



<p><strong><span class="has-inline-color has-vivid-red-color">Configuration Vulnerabilities</span></strong></p>



<p>We are going to try leaking datas stored in the Gruyere database. This is a cool challenge as database exposures are such a big thing nowadays</p>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">Information disclosure #1</span></strong></p>



<p>Looking into the file system of Gruyere, we notice an interesting and potentially sensitive file which is <strong><span class="has-inline-color has-vivid-cyan-blue-color">dump.gtl</span></strong></p>



<p>Here is the code</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-44.png" alt="" class="wp-image-2149" width="430" height="318" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-44.png 631w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-44-300x222.png 300w" sizes="(max-width: 430px) 100vw, 430px" /><figcaption>dump.gtl</figcaption></figure>



<p>It really looks like a database dump program. What is this ? </p>



<p>Usually, a <strong><span class="has-inline-color has-vivid-cyan-blue-color">database dump</span></strong> contains a record of the <strong><span class="has-inline-color has-vivid-cyan-blue-color">table structure</span></strong> and/or the <strong><span class="has-inline-color has-vivid-cyan-blue-color">data</span></strong> from a database, and in real life, is usually in the form of a list of <strong><span class="has-inline-color has-vivid-cyan-blue-color">SQL statements</span></strong></p>



<p>A database dump is most often used for <strong><span class="has-inline-color has-vivid-cyan-blue-color">backing up</span></strong> a database so that its contents can be restored in the event of data loss. The database program will allow to extract the database data for backup. It can also be used in situations where you need to <strong><span class="has-inline-color has-vivid-cyan-blue-color">debug</span></strong> the server </p>



<p>To access the dump, just type this address in your session : <strong><span class="has-inline-color has-vivid-cyan-blue-color">/dump.gtl</span></strong></p>



<p>Here is the content of the dump, consistent with the above code</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-43-1024x637.png" alt="" class="wp-image-2148" width="716" height="445" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-43-1024x637.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-43-300x187.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-43-768x478.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-43.png 1128w" sizes="(max-width: 716px) 100vw, 716px" /></figure>



<p>We can see user names and passwords in clear text</p>



<p>There are obviously major flaws here :</p>



<ul class="wp-block-list"><li>first of all, this file should not be stored here</li><li>passwords are not <strong><span class="has-inline-color has-vivid-cyan-blue-color">hashed</span></strong> or encrypted, but stored in clear text</li><li>the dump program should be strictly restricted to <strong><span class="has-inline-color has-vivid-cyan-blue-color">admin</span></strong> rights </li><li>the dump files should be stored in a specific location with a specific access mechanism (IP, port, <strong><span class="has-inline-color has-vivid-cyan-blue-color">authentication</span></strong>)</li></ul>



<p>Here are the <strong><span class="has-inline-color has-vivid-cyan-blue-color">OWASP</span></strong> recommendations for database security : <a href="https://bit.ly/2XtsOsg" target="_blank" rel="noreferrer noopener">https://bit.ly/2XtsOsg</a>. Obviously Gruyere did not implement any of these recommendations</p>



<p>To build further awareness of potential exploitation of <strong><span class="has-inline-color has-vivid-cyan-blue-color">debuggers</span></strong> in real life, I suggest to check this link : <a href="https://bit.ly/2VNQxCO" target="_blank" rel="noreferrer noopener">https://bit.ly/2VNQxCO</a></p>



<p><em><strong>Are such situations common in real life ?</strong></em></p>



<p>Unfortunately, Gruyere is quite representative of what you can find on websites exposed to the Internet. We all know that there are thousands of databases which are ill-configured and exposed to attackers</p>



<p>You can have a first look by typing this query in Google : <strong><span class="has-inline-color has-vivid-cyan-blue-color">intitle:&#8221;index of/&#8221; &#8220;*.sql&#8221;</span></strong></p>



<p>This will just search for <strong><span class="has-inline-color has-vivid-cyan-blue-color">SQL databases</span></strong> in websites root directory, and reveal many exposed databases (some being quite critical from a GDPR point of view)</p>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">Information disclosure #2</span></strong></p>



<p>Unfortunately, deleting the dump.gtl file will not secure Gruyere. One big issue, as we know, is that we can easily upload any kind of file we want. So, we can <strong><span class="has-inline-color has-vivid-cyan-blue-color">upload</span></strong> another dump script and leak the data</p>



<p>There should be protections included in the code (preventing some file formats such as templates, scripts,&#8230;). The following code on the server side permits <strong><span class="has-inline-color has-vivid-cyan-blue-color">unrestricted file uploads</span></strong></p>



<figure class="wp-block-image size-full"><img decoding="async" width="846" height="537" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-45.png" alt="" class="wp-image-2153" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-45.png 846w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-45-300x190.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-45-768x487.png 768w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" /><figcaption>gruyere.py</figcaption></figure>



<p>Here is a valuable <strong><span class="has-inline-color has-vivid-cyan-blue-color">checklist</span></strong> focused on file upload vulnerabilities : <a href="https://bit.ly/3Crw0E2" target="_blank" rel="noreferrer noopener">https://bit.ly/3Crw0E</a>, and also a good video about file upload vulnerability, providing a quite thorough review of the topic</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="15 Technique to Exploit File Upload Pages - Ebrahim Hegazy, HackIT-2017" width="525" height="295" src="https://www.youtube.com/embed/CmF9sEyKZNo?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">Information disclosure #3</span></strong></p>



<p>The target here is to continue leaking the Gruyere database, not using a dump function or upload vulnerability, but relying on the Gruyer code weaknesses</p>



<p>We can try using some functions existing in Python, such as <strong><span class="has-inline-color has-vivid-cyan-blue-color">pprint</span></strong> <strong><span class="has-inline-color has-vivid-cyan-blue-color">&#8211; data pretty printer</span></strong>, to display the database content, and inject this directly into the &#8220;new snippet&#8221; window</p>



<p>The pprint module provides a capability to “pretty-print” Python <strong><span class="has-inline-color has-vivid-cyan-blue-color">data structures</span></strong>. The formatted representation keeps objects on a single line if it can, and breaks them onto multiple lines if they don’t fit within the allowed width</p>



<p>In a template language such as Django, variables look like this : <strong><span class="has-inline-color has-vivid-cyan-blue-color">{{ variable }}</span></strong></p>



<p>When the template engine encounters a variable, it evaluates that variable and replaces it with the result</p>



<p>Reading into the GTL language, we see some explanatations : &#8220;<strong><span class="has-inline-color has-vivid-cyan-blue-color">db</span></strong>&#8221; stands for the database variable in the GTL language and can be used as a special value</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-47.png" alt="" class="wp-image-2157" width="434" height="102" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-47.png 538w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-47-300x70.png 300w" sizes="(max-width: 434px) 100vw, 434px" /><figcaption>gtl.py</figcaption></figure>



<p>So, we can input this variable in the &#8220;new snippet&#8221; window, as the GTL language will interpret the result</p>



<pre class="wp-block-preformatted"><strong><span class="has-inline-color has-vivid-cyan-blue-color">{{_db:pprint}}</span></strong></pre>



<p>Here is our database directly on the &#8220;my snippet&#8221; page</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="712" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-46-1024x712.png" alt="" class="wp-image-2155" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-46-1024x712.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-46-300x209.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-46-768x534.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-46.png 1064w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" /></figure>



<p>There is one flaw in the way the template code parses the variable values</p>



<p><strong><span class="has-inline-color has-vivid-cyan-blue-color">ExpandTemplate</span></strong> calls <strong><span class="has-inline-color has-vivid-cyan-blue-color">_ExpandBlocks</span></strong> followed by <strong><span class="has-inline-color has-vivid-cyan-blue-color">_ExpandVariables</span></strong></p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-48.png" alt="" class="wp-image-2159" width="562" height="618" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-48.png 774w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-48-272x300.png 272w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-48-768x846.png 768w" sizes="(max-width: 562px) 100vw, 562px" /><figcaption>gtl.py</figcaption></figure>



<p><strong><span class="has-inline-color has-vivid-cyan-blue-color">_ExpandBlock</span></strong> calls <strong><span class="has-inline-color has-vivid-cyan-blue-color">ExpandTemplate</span></strong> on nested blocks. So if a variable is expanded inside a nested block and contains something that looks like a variable template, it will get expanded a second time</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-49.png" alt="" class="wp-image-2160" width="562" height="229" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-49.png 755w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-49-300x122.png 300w" sizes="(max-width: 562px) 100vw, 562px" /></figure>



<p>In addition to this design flaw, the template language should not allow arbitrary database access and should narrow down the queries possibilities</p>



<hr class="wp-block-separator"/>



<p><strong><span class="has-inline-color has-vivid-red-color">AJAX vulnerabilities</span></strong></p>



<p>Before starting these last two challenges, let&#8217;s remind what we have seen earlier</p>



<p>Gruyere uses AJAX principles to implement <strong><span class="has-inline-color has-vivid-cyan-blue-color">refresh</span></strong> on the home and snippets page</p>



<p>When clicking the refresh link, Gruyere fetches <strong><span class="has-inline-color has-vivid-cyan-blue-color">feed.gtl</span></strong> which contains refresh data for the current page and then the client-side script uses the browser <strong><span class="has-inline-color has-vivid-cyan-blue-color">DOM API</span></strong> (<strong><span class="has-inline-color has-vivid-cyan-blue-color">Document Object Model</span></strong>) to insert the new snippets into the page</p>



<p>Since AJAX runs code on the client side, this script is <strong><span class="has-inline-color has-vivid-cyan-blue-color">visible to attackers</span></strong> who do not have access to the source code. We can see the code using <strong><span class="has-inline-color has-vivid-cyan-blue-color">Burp Suite</span></strong></p>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">DoS via AJAX</span></strong></p>



<p>First of all, let&#8217;s sign in using my Gruyere account &#8220;Forensicxs&#8221;</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-54.png" alt="" class="wp-image-2168" width="406" height="179" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-54.png 598w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-54-300x132.png 300w" sizes="(max-width: 406px) 100vw, 406px" /><figcaption>Forensicxs</figcaption></figure>



<p>We can see the snippets. Clicking on &#8220;refresh&#8221;, we see the response corresponding to the snippets content</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-53.png" alt="" class="wp-image-2167" width="492" height="405"/><figcaption>Forensicxs</figcaption></figure>



<p>Then, let&#8217;s create a user &#8220;<strong><span class="has-inline-color has-vivid-cyan-blue-color">private_snippet</span></strong>&#8220;, and create several snippets</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-52.png" alt="" class="wp-image-2166" width="307" height="126" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-52.png 499w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-52-300x123.png 300w" sizes="(max-width: 307px) 100vw, 307px" /></figure>



<p>Here is the response. The snippets of the other users have been deleted</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-50.png" alt="" class="wp-image-2164" width="527" height="424" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-50.png 679w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-50-300x242.png 300w" sizes="(max-width: 527px) 100vw, 527px" /><figcaption>private_snippet</figcaption></figure>



<p>The flaw here is the structure of the response. We see the construction here </p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-55.png" alt="" class="wp-image-2169" width="370" height="66" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-55.png 520w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-55-300x53.png 300w" sizes="(max-width: 370px) 100vw, 370px" /><figcaption>showprofile.gtl</figcaption></figure>



<p>And also in the <strong><span class="has-inline-color has-vivid-cyan-blue-color">lib.js</span></strong></p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-57.png" alt="" class="wp-image-2173" width="494" height="329" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-57.png 739w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-57-300x200.png 300w" sizes="(max-width: 494px) 100vw, 494px" /><figcaption>lib.js</figcaption></figure>



<p>This manipulation of the Document Object Model, by injecting code and pushing a data &#8220;offset&#8221;, is somehow similar to a <strong><span class="has-inline-color has-vivid-cyan-blue-color">buffer overflow</span></strong> </p>



<p>Google says that the structure of the response should be as follows, to avoid this &#8220;offset&#8221; of the user snippets by the attacker snippets :</p>



<p><strong><span class="has-inline-color has-vivid-cyan-blue-color">[&lt;private_snippet&gt;, {&lt;user&gt; : &lt;snippet&gt;,&#8230;}]</span></strong></p>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">Phishing via AJAX</span></strong></p>



<p>The target here is to inject in the page some links to a phishing site</p>



<p>I created a user called &#8220;Phishing&#8221;, and I created a snippet with the following text</p>



<pre class="wp-block-preformatted">&lt;a href='https://www.forensicxs.com'&gt;Sign in&lt;/a&gt;
| &lt;a href='https://www.forensicxs.com'&gt;Sign up&lt;/a&gt;</pre>



<p>Here is the result</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-59.png" alt="" class="wp-image-2175" width="298" height="53" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-59.png 401w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-59-300x53.png 300w" sizes="(max-width: 298px) 100vw, 298px" /></figure>



<p>So now, we have on the page additional links to sign in/sign up. A user could be tricked to click on such links and trigger a phishing attack, by forwarding the user to a specially crafted page looking like the Gruyere page, and including some malicious code to take control of the user session</p>



<p>We have seen in these two challenges, that the DOM should be better protected against potential manipulations, for example, by applying a prefix to user values like&nbsp;<code><strong><span class="has-inline-color has-vivid-cyan-blue-color">id="user_"</span></strong></code></p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="292" src="https://www.forensicxs.com/wp-content/uploads/2021/09/image-58-1024x292.png" alt="" class="wp-image-2174" srcset="https://www.forensicxs.com/wp-content/uploads/2021/09/image-58-1024x292.png 1024w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-58-300x86.png 300w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-58-768x219.png 768w, https://www.forensicxs.com/wp-content/uploads/2021/09/image-58.png 1090w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" /><figcaption>home.gtl</figcaption></figure>



<hr class="wp-block-separator"/>



<p><strong><span class="has-inline-color has-vivid-red-color">Conclusion</span></strong></p>



<p>We have seen most of the major web hacking techniques in this article. For learning, Google Gruyere is really a very good platform, as it combines the client side application, but also the server code, together with a well documented walkthrough</p>



<p>I hope this article provides you further help for a good understanding. In any case, <strong><span class="has-inline-color has-vivid-cyan-blue-color">thanks to the Google team for providing this excellent learning platform</span></strong></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.forensicxs.com/google-gruyere/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 
Database Caching 1/55 queries in 0.033 seconds using Disk

Served from: www.forensicxs.com @ 2026-01-07 14:12:29 by W3 Total Cache
-->