我工作的公司最近在我们托管的网站上遇到了许多标头注入和文件上传攻击,虽然我们已经修复了关于标头注入攻击的问题,但我们尚未控制上传漏洞.
我正在尝试设置一个即插即用型的上传脚本系列,以便内部使用,设计人员可以将其复制到他们的网站结构中,修改一些变量,并有一个随时可用的上传表单.他们的网站.我们希望尽可能地限制我们的曝光(我们已经关闭了fopen和shell命令).
我在网站上搜索了最后一小时,发现许多不同的答案处理依赖外部资源的特定方法.您认为什么是最好的仅限脚本的解决方案,具体到足以用作可靠的保护方法?另外,如果可能的话,我想将语言限制为PHP或伪代码.
编辑:我找到了我的答案(在下面发布),虽然它确实使用了shell命令exec(),但是如果阻止脚本文件被上传(这个解决方案做得很好),你就不会遇到任何问题.
仅允许授权用户上载文件.您也可以添加验证码以阻止原始机器人.
首先,设定MAX_FILE_SIZE
在上传表单,并设置最大的文件size
,并count
在服务器上也是如此.
ini_set('post_max_size', '40M'); //or bigger by multiple files ini_set('upload_max_filesize', '40M'); ini_set('max_file_uploads', 10);
通过上传的文件进行大小检查:
if ($fileInput['size'] > $sizeLimit) ; //handle size error here
您应该使用$_FILES
并将move_uploaded_file()
上传的文件放入正确的目录中,或者如果要处理它,请检查is_uploaded_file()
.(存在这些函数以防止由.引起的文件名注入register_globals
.)
$uploadStoragePath = '/file_storage'; $fileInput = $_FILES['image']; if ($fileInput['error'] != UPLOAD_ERR_OK) ; //handle upload error here, see http://php.net/manual/en/features.file-upload.errors.php //size check here $temporaryName = $fileInput['tmp_name']; $extension = pathinfo($fileInput['name'], PATHINFO_EXTENSION); //mime check, chmod, etc. here $name = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM)); //true random id move_uploaded_file($temporaryName, $uploadStoragePath.'/'.$name.'.'.$extension);
始终生成随机ID而不是使用原始文件名.
为上传的文件创建一个新的子域,例如http://static.example.com或至少一个新的目录public_html
.此子域或目录不应执行任何文件.在服务器配置中设置它,或在.htaccess
目录中设置文件.
SetHandler none SetHandler default-handler Options -ExecCGI php_flag engine off
将其设置与chmod()
为好.
$noExecMode = 0644; chmod($uploadedFile, $noExecMode);
也可以chmod()
在新上传的文件上使用并将其设置在目录中.
你应该检查黑客发送的mime类型.您应该创建允许的mime类型的白名单.仅在不需要任何其他格式时才允许图像.任何其他格式都是安全威胁.图像也是,但至少我们有工具来处理它们...... 例如
,损坏的内容:图像文件中的HTML可能会导致具有内容嗅探漏洞的浏览器的XSS.当损坏的内容是PHP代码时,它可以与eval注入漏洞结合使用.
$userContent = '../uploads/malicious.jpg'; include('includes/'.$userContent);
尽量避免这种情况,例如使用class autoloader
而不是手动包含php文件... 首先
处理javascript注入,你必须在浏览器中关闭xss和内容嗅探.内容嗅探问题是老款msie的典型问题,我认为其他浏览器可以很好地过滤它们.无论如何,你可以用一堆标题来防止这些问题.(并非每个浏览器都完全支持,但这是您在客户端可以做的最好的.)
Strict-Transport-Security: max-age={your-max-age} X-Content-Type-Options: nosniff X-Frame-Options: deny X-XSS-Protection: 1; mode=block Content-Security-Policy: {your-security-policy}
您可以检查文件是否已损坏Imagick identify
,但这并不意味着完全保护.
try { $uploadedImage = new Imagick($uploadedFile); $attributes = $uploadedImage->identifyImage(); $format = $image->getImageFormat(); var_dump($attributes, $format); } catch (ImagickException $exception) { //handle damaged or corrupted images }
如果你想提供其他mime类型,你应该总是强迫他们下载,不要把它们包含在网页中,除非你真的知道你在做什么......
X-Download-Options: noopen Content-Disposition: attachment; filename=untrustedfile.html
可以使用包含代码的有效图像文件,例如exif数据.因此,如果图像的内容对您不重要,则必须从图像中清除exif.您可以使用Imagick
或执行此操作GD
,但它们都需要重新打包文件.你可以找到exiftool
一个替代品.我认为清除exif的最简单方法是使用GD加载图像,并将它们保存为具有最高质量的PNG.所以图像不会丢失质量,exif标签将被清除,因为GD无法处理它.将此与上传的图片PNG太......
如果你要提取的EXIF数据,千万不要用preg_replace()
如果pattern
或者replacement
是来自用户,因为这将导致eval射入 ...使用preg_replace_callback()
,而不是eval regex flag
必要时.(复制粘贴代码中的常见错误.)如果您的站点存在eval注入漏洞(例如,如果您在某处使用),则
Exif数据可能会出现问题.include($userInput)
永远不要使用include()
,require()
上传的文件,为他们服务,为静态或使用file_get_contents()
或readfile()
,或任何其他文件阅读功能,如果你想控制访问.
它很少可用,但我认为使用sendfile apache模块的X-Sendfile: {filename}
头文件的最佳方法.通过标题,永远不要使用用户输入而不进行验证或清理,因为这会导致HTTP标头注入.
如果您不需要访问控制(意味着:只有授权用户才能看到上传的文件),请使用您的网络服务器提供文件.它快得多......
如果您有上传的文件,请使用antivir检查上传的文件.
始终使用组合保护,而不仅仅是单一方法.破坏你的防御将更加困难......
最好的解决方案是恕我直言,将包含上传文件的目录放在"web"环境之外,并使用脚本使其可下载.这样,即使某人上传了一个脚本,也无法通过从浏览器中调用它来执行它,也不必检查上传文件的类型.