{"id":8357,"date":"2023-01-09T12:00:00","date_gmt":"2023-01-09T10:00:00","guid":{"rendered":"https:\/\/blog.eset.ee\/et\/2023\/01\/09\/cracked-it-highlights-from-kringlecon-5-golden-rings\/"},"modified":"2023-01-09T12:00:00","modified_gmt":"2023-01-09T10:00:00","slug":"cracked-it-highlights-from-kringlecon-5-golden-rings","status":"publish","type":"post","link":"https:\/\/blog.eset.ee\/et\/en\/2023\/01\/09\/cracked-it-highlights-from-kringlecon-5-golden-rings\/","title":{"rendered":"Cracked it! Highlights from KringleCon 5: Golden Rings"},"content":{"rendered":"<p><span><\/p>\n<p><em>UPDATE: At the <a href=\"https:\/\/www.sans.org\/webcasts\/sans-holiday-hack-challenge-2022-closing-ceremonies-winner-announcements\/\">closing ceremonies<\/a> held on January 25<sup>th<\/sup>, 2023, the team behind the SANS Holiday Hack Challenge announced the winners and the enrollment of this report in the <a href=\"https:\/\/www.sans.org\/mlp\/holiday-hack-challenge\/winners-and-answers\/\">Honorable Mentions list<\/a>. Much glory to all the winners and hope to see some of you at KringleCon 6 on six geese a laying!<\/em><\/p>\n<p><\/span><\/p>\n<p>This is my first year participating in the <a href=\"https:\/\/www.sans.org\/mlp\/holiday-hack-challenge\/\">SANS Holiday Hack Challenge<\/a> and it was a blast. Through a series of 16 challenges ranging from easy to difficult, I practiced analyzing suspicious network traffic and PowerShell logs, writing <a href=\"https:\/\/suricata.readthedocs.io\/en\/latest\/\">Suricata rules<\/a>, breaking out of a <a href=\"https:\/\/www.docker.com\/resources\/what-container\/\">Docker container<\/a>, finding leaked keys to exploit a <a href=\"https:\/\/docs.gitlab.com\/ee\/ci\/\">GitLab CI\/CD pipeline<\/a> and an <a href=\"https:\/\/docs.aws.amazon.com\/IAM\/latest\/UserGuide\/id_users.html\">AWS user<\/a>, conducting <a href=\"https:\/\/owasp.org\/www-community\/vulnerabilities\/XML_External_Entity_(XXE)_Processing\">XML External Entity attacks<\/a>, and hacking a smart contract to buy a <a href=\"https:\/\/www.welivesecurity.com\/2022\/07\/25\/nft-new-fangled-trend-new-found-treasure\/\">non-fungible token<\/a>.<\/p>\n<p>The best part of this experience was that it introduced me to new tools and technologies, thus stretching my cybersecurity knowledge that much further. Here, I share a few highlights from solving the challenges.<\/p>\n<h2><strong>Orientation<\/strong><\/h2>\n<p>Every participant receives an avatar to navigate an in-browser video game environment set at the North Pole:<\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Orientation.gif\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"690\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Orientation.gif\" width=\"1506\"><\/a><\/p>\n<p>During orientation, you receive a cryptocurrency wallet that the game uses to award KringleCoins for completing challenges and that you use in the last challenge to hack a smart contract. Interestingly, the game keeps track of all KringleCoin transactions in an Ethereum blockchain, meaning a complete record of your progress is stored in this blockchain too.<\/p>\n<p>On to the first ring of the game.<\/p>\n<h2><strong>1. Tolkien Ring<\/strong><\/h2>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Tolkien-Ring.jpg\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"310\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Tolkien-Ring.jpg\" width=\"1879\"><\/a><\/p>\n<p>Finding the Tolkien Ring required flexing my logs analysis muscles.<\/p>\n<h3><strong>Wireshark phishing<\/strong><\/h3>\n<p>First, I used Wireshark to analyze the provided <span>.pcap<\/span> file that revealed a server at <span>adv.epostoday[.]uk<\/span> downloading the file <span>Ref_Sept24-2020.zip<\/span> to a computer:<\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Wireshark-traffic-analysis.png\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1020\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Wireshark-traffic-analysis.png\" width=\"1920\"><\/a><\/p>\n<p>Peeking inside the ZIP file, I found an executable called <span><a href=\"https:\/\/www.virustotal.com\/gui\/file\/fad001d463e892e7844040cabdcfa8f8431c07e7ef1ffd76ffbd190f49d7693d\">Ref_Sept24-2020.scr<\/a><br \/>\n<\/span>that triggered two detections in ESET Endpoint Security: <span>BAT\/Runner.ES<\/span> and<span> Generik.TAGTBG<\/span>. This malware eventually lead to a malicious executable running in memory called <span>config.dll<\/span> and detected by ESET\u2019s <a href=\"https:\/\/help.eset.com\/glossary\/en-US\/technology_ams.html\">Advanced Memory Scanner<\/a> as <span>Win32\/Dridex.DD<\/span>.<\/p>\n<h3><strong>Windows event logs<\/strong><\/h3>\n<p>Next, I analyzed the provided <span>.evtx<\/span> file containing PowerShell logs with Event Viewer. While there are other tools to analyze PowerShell logs, if attackers know how to use living-off-the-land binaries to stay under the radar, defenders should also be well-versed in the native tools an operating system provides.<\/p>\n<p>Since the logs contained 10,434 events, I grouped the events by date and then ran the Find action to look for any events containing the <span>$<\/span> character. In PowerShell, <span>$<\/span> is used to create and reference <a href=\"https:\/\/learn.microsoft.com\/en-us\/powershell\/module\/microsoft.powershell.core\/about\/about_variables\">variables<\/a>. I found an attack happening on December 24, 2022, when the attacker ran the following script:<\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/PowerShell-logs-analysis.png\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1020\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/PowerShell-logs-analysis.png\" width=\"1920\"><\/a><\/p>\n<p>It looks like the attacker found a secret recipe, switched out the secret ingredient of <span>honey<\/span> for <span>fish oil<\/span>, and then created a new recipe file. This triggered an event with an ID of 4104, which stands for the execution of remote PowerShell commands. So, I filtered the events by this ID, helping me to find additional malicious events more quickly.<\/p>\n<h3><strong>Suricata Regatta<\/strong><\/h3>\n<p>The last exercise for the Tolkien Ring was writing four Suricata rules to monitor network traffic for a Dridex infestation:<\/p>\n<p><span>alert dns $HOME_NET any -&gt; any any (msg:&#8221;Known bad DNS lookup, possible Dridex infection&#8221;; dns.query; content:&#8221;adv.epostoday.uk&#8221;; nocase; sid:1; rev:1;)<\/span><\/p>\n<p><span>alert http 192.185.57.242 any &lt;&gt; any any (msg:&#8221;Investigate suspicious connections, possible Dridex infection&#8221;; sid:2; rev:1;)<\/span><\/p>\n<p><span>alert tls any any -&gt; any any (msg:&#8221;Investigate bad certificates, possible Dridex infection&#8221;; tls.cert_subject; content:&#8221;CN=heardbellith.Icanwepeh.nagoya&#8221;; sid:3; rev:1;)<\/span><\/p>\n<p><span>alert http any any -&gt; any any (msg:&#8221;Suspicious JavaScript function, possible Dridex infection&#8221;; file_data; content:&#8221;let byteCharacters = atob&#8221;; sid:4; rev:1;)<\/span><\/p>\n<p>In order, these rules catch DNS lookups for <span>adv.epostoday[.]uk<\/span>, connections to the IP address <span>192.185.57[.]242<\/span>, the use of the malicious server <span>heardbellith.Icanwepeh[.]nagoya<\/span> identified via the common name (<span>CN<\/span>) in a TLS certificate, and the use of the JavaScript <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/atob\"><span>atob()<\/span><\/a> function to decode a binary string containing base64-encoded data on the client.<\/p>\n<p>Completing these three challenges earned me the Tolkien Ring:<\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Tolkien-Ring-won.png\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"202\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Tolkien-Ring-won.png\" width=\"1116\"><\/a><\/p>\n<p>On to the second ring.<\/p>\n<h2><strong>2. Elfen Ring<\/strong><\/h2>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Elf-House.jpg\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"996\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Elf-House.jpg\" width=\"950\"><\/a><\/p>\n<p>The most prominent challenges for the Elfen Ring were Prison Escape and Jolly CI\/CD.<\/p>\n<h3><strong>Prison Escape<\/strong><\/h3>\n<p>Prison Escape was a stern reminder that granting root privileges to a user in a Docker container is just as good as granting root privileges on the host system. The challenge was to break out of the container. Well, easily done when you are root:<\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Prison-escape-1.png\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1411\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Prison-escape-1.png\" width=\"1201\"><\/a><\/p>\n<p>As the root user, I listed the partition tables for the device and then mounted the host filesystem, granting me full access to the host. Now I could search for the key, which should be located in the home directory as revealed by the in-game hints:<\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Prison-escape-2.png\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1415\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Prison-escape-2.png\" width=\"1201\"><\/a><\/p>\n<h3><strong>Jolly CI\/CD<\/strong><\/h3>\n<p>While that was quick, Jolly CI\/CD took me the longest of any challenge to figure out. First, we were given a Git repository to clone over HTTP:<\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Jolly-CI-CD-1.png\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"882\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Jolly-CI-CD-1.png\" width=\"1721\"><\/a><\/p>\n<p>From the URL, I could see that the name of the repository was <span>wordpress.flag.net.internal<\/span>, so I moved to the repository and found a WordPress website. I checked if the website was live:<\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Jolly-CI-CD-2.png\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"310\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Jolly-CI-CD-2.png\" width=\"1726\"><\/a><\/p>\n<p>Yup, the website was functional. I was curious if there were any leaked keys in the source code history. If yes, I should be able to push edits to the source code. So I ran <span>git log<\/span>:<\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Jolly-CI-CD-3.png\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"499\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Jolly-CI-CD-3.png\" width=\"1731\"><\/a><\/p>\n<p>From the commit messages, it looks like a <a href=\"https:\/\/github.com\/git-guides\/git-commit\">commit<\/a> was made after adding assets to fix a whoops. Time to check out the pre-whoops commit:<\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Jolly-CI-CD-4.png\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"865\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Jolly-CI-CD-4.png\" width=\"1739\"><\/a><\/p>\n<p>Excellent, I found a <span>.ssh<\/span> directory with keys. Let\u2019s copy those keys over and configure an SSH agent and a Git user to see if I can impersonate the owner of those keys:<\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Jolly-CI-CD-5.png\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"350\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Jolly-CI-CD-5.png\" width=\"1724\"><\/a><\/p>\n<p>Now let\u2019s return to the main branch and test if we can push a trivial change to the source code (using nano, I simply added a space to one of the files):<\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Jolly-CI-CD-6.png\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"695\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Jolly-CI-CD-6.png\" width=\"1731\"><\/a><\/p>\n<p>So, I achieved the first part of the challenge by impersonating one of the WordPress developers, but did the website still work after my push?<\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Jolly-CI-CD-7.png\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"350\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Jolly-CI-CD-7.png\" width=\"1726\"><\/a><\/p>\n<p>My push changed something because now the website redirected to port 8080.<\/p>\n<p>Until now, I had ignored the CI\/CD portion of the challenge, which should be the key to completing it. The repository contains a <span><a href=\"https:\/\/docs.gitlab.com\/ee\/ci\/yaml\/gitlab_ci_yaml.html\">.gitlab-ci.yml<\/a><br \/>\n<\/span>file, which provides the configuration for a GitLab CI\/CD pipeline. Every time you push to the repository, the CI\/CD system kicks in, and a <a href=\"https:\/\/docs.gitlab.com\/runner\/\">GitLab Runner<\/a> executes the scripts in this YML file. That\u2019s as good as achieving remote code execution on the server where GitLab Runner is installed, I thought.<\/p>\n<p>Looking closer, I saw an <span><a href=\"https:\/\/linux.die.net\/man\/1\/rsync\">rsync<\/a><br \/>\n<\/span>script copying all the files from the Git repository to the directory on the web server from which the website was being served. At first, I tried to use <span>rsync<\/span> to reverse the data flow by copying all the files from the web server to the Git repository, but without success.<\/p>\n<p>After a lot of hypothesis testing, I eventually had my breakthrough insight: Instead of trying to \u201cfix\u201d the WordPress website or run malicious scripts via the build system, serve a website that leaks information from the web server. Inside <span>index.php<\/span> (located at the top level of the repository), I can comment out the code that loads the WordPress website and run PHP commands that probe the web server.<\/p>\n<p>Indeed, I can even run shell commands with PHP. I found that <a href=\"https:\/\/www.php.net\/manual\/en\/function.passthru.php\"><span>passthru()<\/span><\/a> worked easily.<\/p>\n<p>In <span>index.php<\/span>, I used <span>\/\/<\/span> to comment out two lines and I added <span>passthru(&#8216;ls -la \/&#8217;);<\/span> on the last line. This creates a website that lists all the files in the root directory of the web server:<\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Jolly-CI-CD-8.png\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"473\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Jolly-CI-CD-8.png\" width=\"1024\"><\/a><\/p>\n<p>Then I pushed this change to the Git repository and the GitLab CI\/CD system took care of updating the website for me:<\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Jolly-CI-CD-9-1.png\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"863\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Jolly-CI-CD-9-1.png\" width=\"950\"><\/a><\/p>\n<p>Ah, the Elfen Ring must be in <span>flag.txt<\/span>! I repeated the previous steps, but this time using <span>passthru(&#8216;cat \/flag.txt&#8217;)<\/span>; revealing the Elfen Ring the next time I requested the website:<\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Jolly-CI-CD-10.png\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"980\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Jolly-CI-CD-10.png\" width=\"950\"><\/a><\/p>\n<p>On to the third ring.<\/p>\n<h2><strong>3. Web Ring<\/strong><\/h2>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Web-Ring.jpg\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"692\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Web-Ring.jpg\" width=\"892\"><\/a><\/p>\n<p>The most fun challenge for me was Open Boria Mine Door, although Glamtariel\u2019s Fountain was interesting while also presenting riddles.<\/p>\n<h3><strong>Open Boria Mine Door<\/strong><\/h3>\n<p>In Open Boria Mine Door, we were presented with six pins or mini-challenges to bypass input validation or a <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/CSP\">Content Security Policy<\/a> to connect the entry and exit pipes between the pins, including matching the pipe colors. For most pins, I used HTML to write a list of connecting letter \u2018o\u2019s. Here is my final solution:<\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Boria-Mine-Door.gif\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"886\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Boria-Mine-Door.gif\" width=\"1598\"><\/a><\/p>\n<h4><strong>Pin 1<\/strong><\/h4>\n<p>There was no validation for Pin 1, so it was a simple matter of HTML and inline CSS:<\/p>\n<pre title=\"\"><code>&lt;p style=\"letter-spacing: -4px; margin: 0; padding: 0;\"&gt;oooooooooooooo&lt;\/p&gt;<\/code><\/pre>\n<h4><strong>Pin 2<\/strong><\/h4>\n<p>Pin 2 had a Content Security Policy that disallowed JavaScript but allowed inline CSS, so that was no problem for my method:<\/p>\n<pre title=\"\"><code>&lt;ul style=\"list-style: none; line-height:0.5; letter-spacing: -4px; margin: 0; padding: 0;\"&gt; &lt;li&gt;o&lt;\/li&gt; &lt;li&gt;o&lt;\/li&gt; &lt;li&gt;o&lt;\/li&gt; &lt;li&gt;o&lt;\/li&gt; &lt;li&gt;o&lt;\/li&gt; &lt;li&gt;o&lt;\/li&gt; &lt;li&gt;o&lt;\/li&gt; &lt;li&gt;o&lt;\/li&gt; &lt;li&gt;o&lt;\/li&gt; &lt;li&gt;oooooooooooooo&lt;\/li&gt; &lt;\/ul&gt;<\/code><\/pre>\n<h4><strong>Pin 3<\/strong><\/h4>\n<p>Pin 3 had a Content Security Policy that disallowed CSS but allowed inline JavaScript, so I used JavaScript to change the styles instead:<\/p>\n<pre title=\"\"><code>&lt;script&gt; document.write(\"\" + \"&lt;ul id='o'&gt;\" + \"&lt;li&gt;o&lt;\/li&gt;\" + \"&lt;li&gt;oooooooooooooooooooooo&lt;\/li&gt;\" + \"&lt;li&gt;o&lt;\/li&gt;&lt;li&gt;o&lt;\/li&gt;&lt;li&gt;o&lt;\/li&gt;&lt;li&gt;o&lt;\/li&gt;\" + \"&lt;\/ul&gt;\"); const o = document.getElementById('o'); o.style.color = \"blue\"; o.style.listStyle = \"none\"; o.style.lineHeight = \"0.5\"; o.style.letterSpacing = \"-4px\"; o.style.margin = \"0\"; o.style.padding = \"0\"; &lt;\/script&gt;<\/code><\/pre>\n<h4><strong>Pin 4<\/strong><\/h4>\n<p>Pin 4 had no Content Security Policy, but it had a sanitizeInput function on the client side that would strip double quotes, single quotes, left angle brackets, and right angle brackets. The trick here was to realize that this function wasn\u2019t triggered by submitting the form, but by the <span><a href=\"https:\/\/www.w3schools.com\/jsref\/event_onblur.asp\">onblur<\/a><br \/>\n<\/span>event. In other words, moving the mouse away from the input field triggered the <span>onblur<\/span> event, sanitizing any input. The solution was to submit the form by pressing the <strong>Enter<\/strong> key, while taking care not to move the mouse cursor outside the bounds of the input field:<\/p>\n<pre title=\"\"><code>&lt;ul style=\"list-style: none; line-height:0.5; letter-spacing: -4px; margin: 0; padding: 0;\"&gt; &lt;li&gt;o&lt;\/li&gt; &lt;li&gt;o&lt;\/li&gt; &lt;li&gt;oooooooooooooo&lt;\/li&gt; &lt;li&gt;o&lt;\/li&gt; &lt;li&gt;o&lt;\/li&gt; &lt;li&gt;o&lt;\/li&gt; &lt;li&gt;o&lt;\/li&gt; &lt;li&gt;o&lt;\/li&gt; &lt;li style=\"color: blue;\"&gt;oooooooooooooo&lt;\/li&gt; &lt;\/ul&gt;<\/code><\/pre>\n<h4><strong>Pin 5<\/strong><\/h4>\n<p>Pin 5 had the same<span> sanitizeInput<\/span> function and bypass along with a Content Security Policy forbidding inline CSS, but allowing inline JavaScript:<\/p>\n<pre title=\"\"><code>&lt;script&gt; document.write(\"\" + \"&lt;ul id='o'&gt;\" + \"&lt;li&gt;o&lt;\/li&gt;\" + \"&lt;li&gt;o&lt;\/li&gt;\" + \"&lt;li class='red'&gt;oooooooooooooo&lt;\/li&gt;\" + \"&lt;li&gt;&lt;span class='red'&gt;o&lt;\/span&gt;&lt;\/li&gt;\" + \"&lt;li&gt;&lt;span class='red'&gt;o&lt;\/span&gt;&lt;\/li&gt;\" + \"&lt;li&gt;&lt;span class='red'&gt;o&lt;\/span&gt;\" + \"&lt;span class='blue'&gt; ooooooooooo&lt;\/span&gt;&lt;\/li&gt;\" + \"&lt;li&gt;&lt;span class='red'&gt;o&lt;\/span&gt;\" + \"&lt;span class='blue'&gt; oo&lt;\/span&gt;&lt;\/li&gt;\" + \"&lt;li&gt;&lt;span class='red'&gt;o&lt;\/span&gt;\" + \"&lt;span class='blue'&gt; oo&lt;\/span&gt;&lt;\/li&gt;\" + \"&lt;li&gt;&lt;span class='red'&gt;o&lt;\/span&gt;\" + \"&lt;span class='blue'&gt; oo&lt;\/span&gt;&lt;\/li&gt;\" + \"&lt;li&gt;o&lt;span class='blue'&gt; oo&lt;\/span&gt;&lt;\/li&gt;\" + \"&lt;li&gt;o&lt;span class='blue'&gt; B&lt;\/span&gt;&lt;\/li&gt;\" + \"&lt;\/ul&gt;\"); const o = document.getElementById('o'); o.style.listStyle = \"none\"; o.style.lineHeight = \"0.5\"; o.style.letterSpacing = \"-4px\"; o.style.margin = \"0\"; o.style.padding = \"0\"; o.style.fontSize = \"xx-large\"; const reds = document.getElementsByClassName(\"red\"); for (let red of reds) { red.style.color = \"red\"; } const blues = document.getElementsByClassName(\"blue\"); for (let blue of blues) { blue.style.color = \"blue\"; } &lt;\/script&gt;<\/code><\/pre>\n<h4><strong>Pin 6<\/strong><\/h4>\n<p>Finally, Pin 6 didn\u2019t sanitize the input, but it used a stricter Content Security Policy forbidding both inline CSS and JavaScript. My solution was to use deprecated HTML to get the styles I needed and use a table instead of a list:<\/p>\n<pre title=\"\"><code>&lt;table border=\"0\" frame=\"void\" rules=\"none\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"&gt; &lt;tr bgcolor=\"#00FF00\"&gt; &lt;td&gt;&lt;font color=\"#00FF00\" size=\"7\"&gt;o&lt;\/font&gt;&lt;\/td&gt; &lt;td&gt;&lt;font color=\"#00FF00\" size=\"7\"&gt;o&lt;\/font&gt;&lt;\/td&gt; &lt;td&gt;&lt;font color=\"#00FF00\" size=\"7\"&gt;o&lt;\/font&gt;&lt;\/td&gt; &lt;td&gt;&lt;font color=\"#00FF00\" size=\"7\"&gt;o&lt;\/font&gt;&lt;\/td&gt; &lt;\/tr&gt; &lt;tr bgcolor=\"red\"&gt; &lt;td&gt;&lt;font color=\"red\" size=\"5\"&gt;o&lt;\/font&gt;&lt;\/td&gt; &lt;td&gt;&lt;font color=\"red\" size=\"5\"&gt;o&lt;\/font&gt;&lt;\/td&gt; &lt;td&gt;&lt;font color=\"red\" size=\"5\"&gt;o&lt;\/font&gt;&lt;\/td&gt; &lt;td&gt;&lt;font color=\"red\" size=\"5\"&gt;o&lt;\/font&gt;&lt;\/td&gt; &lt;\/tr&gt; &lt;tr bgcolor=\"blue\"&gt; &lt;td&gt;&lt;font color=\"blue\" size=\"9\"&gt;o&lt;\/font&gt;&lt;\/td&gt; &lt;td&gt;&lt;font color=\"blue\" size=\"9\"&gt;o&lt;\/font&gt;&lt;\/td&gt; &lt;td&gt;&lt;font color=\"blue\" size=\"9\"&gt;o&lt;\/font&gt;&lt;\/td&gt; &lt;td bgcolor=\"red\"&gt;&lt;font color=\"red\" size=\"9\"&gt;o&lt;\/font&gt;&lt;\/td&gt; &lt;\/tr&gt; &lt;tr bgcolor=\"blue\"&gt; &lt;td&gt;&lt;font color=\"blue\" size=\"9\"&gt;o&lt;\/font&gt;&lt;\/td&gt; &lt;td&gt;&lt;font color=\"blue\" size=\"9\"&gt;o&lt;\/font&gt;&lt;\/td&gt; &lt;td&gt;&lt;font color=\"blue\" size=\"9\"&gt;o&lt;\/font&gt;&lt;\/td&gt; &lt;td&gt;&lt;font color=\"blue\" size=\"9\"&gt;o&lt;\/font&gt;&lt;\/td&gt; &lt;\/tr&gt; &lt;\/table&gt;<\/code><\/pre>\n<h3><strong><span lang=\"EN-US\">Glamtariel\u2019s Fountain<\/span><\/strong><\/h3>\n<p><a href=\"https:\/\/glamtarielsfountain.com\/\">Glamtariel\u2019s Fountain<\/a> was an opportunity to practice <a href=\"https:\/\/owasp.org\/www-community\/vulnerabilities\/XML_External_Entity_(XXE)_Processing\">XML External Entity (XXE) attacks<\/a>. Figuring out how to define a custom XML entity, defining an entity that requests a file from the server, and adding that entity as a payload to an HTTP request was not hard. The hardest part was figuring out the in-game riddles to divine the path to the files that the server would leak. Here is the breakthrough request revealing the location of the gold ring:<\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Glamtariels-Fountain-1.jpg\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1020\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Glamtariels-Fountain-1.jpg\" width=\"1920\"><\/a><\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Glamtariels-Fountain-2.jpg\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1020\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Glamtariels-Fountain-2.jpg\" width=\"1920\"><\/a><\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Glamtariels-Fountain-3.jpg\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1020\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Glamtariels-Fountain-3.jpg\" width=\"1920\"><\/a><\/p>\n<p>I would offer two lessons learned from this challenge. First, use the <a href=\"https:\/\/portswigger.net\/bappstore\/db57ecbe2cb7446292a94aa6181c9278\">Content Type Converter<\/a> extension in <a href=\"https:\/\/portswigger.net\/burp\/communitydownload\">Burp<\/a> to convert JSON payloads to XML. Second, try placing the XXE payload in different tags \u2013 it took me a long time to figure out that all I had to do was place the <span>&amp;xxe;<\/span> payload in the <span>reqType<\/span> tag instead of the <span>imgDrop<\/span> tag.<\/p>\n<p>On to the fourth ring.<\/p>\n<h2><strong>4. Cloud Ring<\/strong><\/h2>\n<\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Cloud-Ring.jpg\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"994\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Cloud-Ring.jpg\" width=\"596\"><\/a><\/p>\n<p>Playing for the Cloud Ring was a beginner\u2019s foray into the Amazon Web Services (AWS) Command Line Interface (CLI).<\/p>\n<p>The highlight of this set of challenges was using <a href=\"https:\/\/github.com\/trufflesecurity\/trufflehog\">trufflehog<\/a> to find AWS credentials in a Git repository and then exploiting them to authenticate as an AWS user. An attacker that gets to this position can use <a href=\"https:\/\/docs.aws.amazon.com\/cli\/latest\/reference\/iam\/\">aws iam<\/a> commands to query the policies that apply to the user, and thus which cloud assets can be accessed and abused.<\/p>\n<p>On to the fifth ring.<\/p>\n<h2><strong>5. Burning Ring of Fire<\/strong><\/h2>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Burning-Ring-of-Fire.jpg\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"360\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Burning-Ring-of-Fire.jpg\" width=\"1024\"><\/a><\/p>\n<p>The most instructive part of this set of challenges was learning about <a href=\"https:\/\/decentralizedthoughts.github.io\/2020-12-22-what-is-a-merkle-tree\/\">Merkle Trees<\/a> to exploit a smart contract and <a href=\"https:\/\/boredsporcrowboatsociety.com\/presale.html\">get on the presale list for purchasing a non-fungible token (NFT)<\/a>. Here the challenge was to discover the proof values that, along with my wallet address and the root value of a Merkle Tree, proved my inclusion on the presale list.<\/p>\n<p>After a few unsuccessful attempts to provide proof values, I realized that I would never be able to figure out the proof values for the provided root value because there was no way to know all the leaf values used to calculate it. I needed to change the root value so that I could provide a valid Merkle Tree.<\/p>\n<p>Using <a href=\"https:\/\/github.com\/QPetabyte\/Merkle_Trees\">Professor QPetabyte\u2019s tool<\/a>, I created a Merkle Tree from two leaves consisting of my wallet address and the address for the <span>BSRS_nft<\/span> smart contract, which I found using the in-game Blockchain Explorer in block two of the game\u2019s Ethereum blockchain. The tool generated the root value of this tree and the proof value for my wallet address. Then I used Burp to intercept the request to the server and changed the default root value so that I could submit a valid Merkle Tree. Here is my <a  href=\"https:\/\/boredsporcrowboatsociety.com\/TOKENS\/TOKENIMAGES\/BSRS623.png\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\">NFT sporc<\/a> bought at a fixed price of 100 KringleCoins:<\/p>\n<\/p>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/nft-sporc.png\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"352\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/nft-sporc.png\" width=\"250\"><\/a><\/p>\n<p>An ugly specimen indeed.<\/p>\n<h2><strong>Finale<\/strong><\/h2>\n<p><a  href=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Finale.jpg\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-magnific_type=\"gallery\" title=\"\"><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"538\" src=\"https:\/\/web-assets.esetstatic.com\/wls\/2023\/01\/Finale.jpg\" width=\"1024\"><\/a><\/p>\n<p>A big thank you to the organizers of the SANS Holiday Hack Challenge for stretching my mind in new ways and helping to deepen my cybersecurity knowledge. Not only am I looking forward to next year\u2019s challenge, but I will even be trying out the 2020 and 2021 editions of this challenge. And if you haven\u2019t participated in this challenge before, I hope these highlights have piqued your interest.<\/p>\n<p class=\"wls-source\"><a href=\"https:\/\/www.welivesecurity.com\/2023\/01\/09\/cracked-it-highlights-kringlecon-5-golden-rings\/\" rel=\"nofollow noopener\" target=\"_blank\">Read the full analysis on WeLiveSecurity \u2192<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learning meets fun at the 2022 SANS Holiday Hack Challenge \u2013 strap yourself in for a crackerjack ride at the North Pole as I foil Grinchum&#8217;s foul plan and recover the five golden rings<\/p>\n","protected":false},"author":5,"featured_media":8358,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2880],"tags":[],"class_list":["post-8357","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-digital-security"],"acf":[],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/blog.eset.ee\/et\/en\/wp-json\/wp\/v2\/posts\/8357","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.eset.ee\/et\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.eset.ee\/et\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.eset.ee\/et\/en\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.eset.ee\/et\/en\/wp-json\/wp\/v2\/comments?post=8357"}],"version-history":[{"count":0,"href":"https:\/\/blog.eset.ee\/et\/en\/wp-json\/wp\/v2\/posts\/8357\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.eset.ee\/et\/en\/wp-json\/wp\/v2\/media\/8358"}],"wp:attachment":[{"href":"https:\/\/blog.eset.ee\/et\/en\/wp-json\/wp\/v2\/media?parent=8357"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.eset.ee\/et\/en\/wp-json\/wp\/v2\/categories?post=8357"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.eset.ee\/et\/en\/wp-json\/wp\/v2\/tags?post=8357"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}