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

2023-11-17    分类: 网站建设

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 中的代码是这样写的:

可以看到aaa是文件输入框中的name属性。

我们把这两个文件放在服务器的目录下,或者直接在目录下启动pHp自带的服务器。打开a.html,上传文件后,会得到这样的结果。这里我直接上传了a.html:

array(5) { 
    ["name"]=> 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文件,并在其中写入了一些内容。打开抓包,我们会在请求体中看到类似这样的内容:

------WebKitFormboundaryh4zhLV52OKhf6aJg
Content-Disposition: form-data; name="uploaded"; filename="a.php"
Content-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 注意

新闻标题:网站上传漏洞的前提是了解文件上传这个功能吗?
网页路径:https://www.cdcxhl.com/news48/295048.html

成都网站建设公司_创新互联,为您提供搜索引擎优化电子商务外贸建站用户体验域名注册软件开发

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联