网站上传漏洞的前提是了解文件上传这个功能吗?

发布时间:2025-02-26 点击:30
php代码审计:(一)文件上传0x00概览
在网站运行过程中,不可避免地会更新网站的某些页面或内容,这时就需要使用网站上的文件上传功能。如果对上传的文件没有限制,或者绕过了限制,则可能会使用该功能将可执行文件和脚本上传到服务器,从而进一步导致服务器崩溃。
可见php文件上传代码,了解上传漏洞的前提是了解文件上传的功能及其原理。如果只知道有文件上传,而且可能有漏洞,那就和不知道一样。
具体来说,用户上传的一些文件仍然是php脚本。用户可以通过服务器直接访问这些上传到服务器上的php脚本,并且会执行其中包含的一些命令。文件上传功能如此强大,如果您的网站在文件上传方面没有很好的控制,它就会崩溃。
文件上传漏洞的原因有很多,主要包括:
其中开源编辑器漏洞和文件上传漏洞原理相同,只是多了一个编辑器。上传时,我们的脚本仍然会被上传。
松散过滤非常常见,我们将在以下示例中看到。比如大小写问题,网站只验证是否是小写,我们可以把后缀名改成大写。
然后是文件解析漏洞。比如系统会涉及到这种情况:文件名为1.php;.jpg,iis 6.0 可能认为是jpg文件,但是当它执行被执行。我们可以利用这个解析漏洞进行上传。再比如php文件上传代码,有一些未知的后缀,比如a.php.xxx。由于后缀名无法识别,可能会被释放。如果攻击者再次执行该文件,则该网站可能被控制。
最后是路径截断,就是在上传的文件中使用一些特殊的符号,使文件在上传时被截断。比如a.php.jpg,在网站上验证时,后缀会被认为是jpg,但保存到硬盘时,会被截断为a.php,这是一个直接的php文件。
通常用于截断路径的字符有:
这些是可能导致截断的字符。需要注意的是,在实战中,由于网站的编解码规则不同,需要灵活应用。例如,\0 失败可以替换,或者你可以尝试各种编码,例如,或者,多试几次。
0x01 代码
文件上传首先需要一个表单,如下,我们称之为a.html:
这里有几个要素:
接下来是php脚本中的东西。在 php 中,通过 $ 对象读取文件,并使用以下属性:
t.php 中的代码是这样写的:
string(6) a.html [type]=> string(9) text/html [tmp_name]=> string(44) c:\users\asus\appdata\local\temp\php43a1.tmp [error]=> int(0) [size]=> int(133) }
需要说明的是,在处理文件上传的时候,不要相信文件类型的类型,因为浏览器生成后类型是可以改变的。您甚至可以手动构建类型与实际内容不匹配的数据包。
同时,不应信任文件名名称。相反,文件名和扩展名应该分开,并且扩展名应该被列入白名单。文件名根据需要丢弃并重新生成,或过滤并重新使用。
过度相信这些东西会产生一些隐患,我们将在下面看到。
0x02 实战
实战部分,我会用dvwa中的例子来演示。dvwa是一套用php+编写的web漏洞测试程序,用于常规web漏洞教学和检测。包含sql注入、xss、盲注等常见安全漏洞。项目主页在这里,源码也在这里。
下载部署后,我们打开///,这里是上传漏洞部分的源码,可以看到难度分为低、中、高三个级别。
先看低级难度low.php:
if( isset( $_post[ 'upload' ] ) ) { // where are we going to be writing to? $target_path = dvwa_web_page_to_root . hackable/uploads/; $target_path .= basename( $_files[ 'uploaded' ][ 'name' ] ); // can we move the file to the upload folder? if( !move_uploaded_file( $_files[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) { // no $html .= 'your image was not uploaded.
';}else {// 是的!$html .=”
{$target_path} succesfully uploaded!
;}}
可以看到没有过滤,可以直接上传任何文件。
然后是.php:
if( isset( $_post[ 'upload' ] ) ) { // where are we going to be writing to? $target_path = dvwa_web_page_to_root . hackable/uploads/; $target_path .= basename( $_files[ 'uploaded' ][ 'name' ] ); // file information $uploaded_name = $_files[ 'uploaded' ][ 'name' ]; $uploaded_type = $_files[ 'uploaded' ][ 'type' ]; $uploaded_size = $_files[ 'uploaded' ][ 'size' ]; // is it an image? if( ( $uploaded_type == image/jpeg || $uploaded_type == image/png ) && ( $uploaded_size < 100000 ) ) { // can we move the file to the upload folder? if( !move_uploaded_file( $_files[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) { // no $html .= 'your image was not uploaded.
';}else {// 是的!$html .=”
{$target_path} succesfully uploaded!
;}}else {// file$html .= '
your image was not uploaded. we can only accept jpeg or png images.
';}}
注意第10行和第11行,验证类型必须是jpg或png,大小必须小于某个值。后者可以忽略。刚才我说类型不可信,我们可以抓包,改类型,然后提交。
因为我想演示如何突破上传限制,而不是如何使用上传的脚本,所以我直接创建了一个新的php文件,并在其中写入了一些内容。打开抓包,我们会在请求体中看到类似这样的内容:
------webkitformboundaryh4zhlv52okhf6ajgcontent-disposition: form-data; name=uploaded; filename=a.phpcontent-type: application/octet-stream右键单击“发送到”并将该 /- 更改为 /jpeg。点击“前往”发送。
最后,高级high.php:
if( isset( $_post[ 'upload' ] ) ) { // where are we going to be writing to? $target_path = dvwa_web_page_to_root . hackable/uploads/; $target_path .= basename( $_files[ 'uploaded' ][ 'name' ] ); // file information $uploaded_name = $_files[ 'uploaded' ][ 'name' ]; $uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1); $uploaded_size = $_files[ 'uploaded' ][ 'size' ]; $uploaded_tmp = $_files[ 'uploaded' ][ 'tmp_name' ]; // is it an image? if( ( strtolower( $uploaded_ext ) == jpg || strtolower( $uploaded_ext ) == jpeg || strtolower( $uploaded_ext ) == png ) && ( $uploaded_size < 100000 ) && getimagesize( $uploaded_tmp ) ) { // can we move the file to the upload folder? if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) { // no $html .= 'your image was not uploaded.
';}else {// 是的!$html .=”
{$target_path} succesfully uploaded!
;}}else {// file$html .= '
your image was not uploaded. we can only accept jpeg or png images.
';}}
观察同样的位置,这次改用后缀名来判断。这时候我们可以在后缀前插入\0,即a.php\0.jpg。请注意,它不是斜线加零,而是空字符。这样判断的时候,后缀是.jpg,写入磁盘时会被截断为a.php。它可以被上传或执行。
我们还捕获包裹并交付。先把a.php改成a.php.jpg,然后切换到十六进制编辑模式插入空字符。
鼠标拖动的范围是a.php.jpg,在第二个2e网格上右击,点击“byte”,会自动插入一个\0。然后点击“开始”,你就完成了。
注意这里插入的话,会上传成功,但是访问的时候会直接当作图片处理,里面的内容不会被执行。
0x03 解决方案
同目录下还有一个.php,里面有正确的做法。大家可以看看。里面的代码使用了$=md5(().$).'.'。$; 生成独立的文件名,使其不受原文件名中各种截断字符的干扰。
0x04 注意


如何制作时候网站优化推广的网站
企业网站文章怎么写能达到好的seo优化效果?
上海电商网站建设哪些事项不可忽视?
初学者该怎样开展网站建设 这种步骤要确立
竞价知识:打造合理帐户结构
网站Alexa排名下降了怎么办
社交电商的困境和痛点在哪里
虽然一般两个月即可但网站建设花费时间并无固定准则