包含语言文件时的本地文件包含漏洞

时间:2016-05-19 09:21:18

标签: php file local exploit inclusion

我的网站有一个PHP代码,一位朋友告诉我,我的代码有一个本地文件包含漏洞,因为即时通讯使用“包含”方法。

有人可以帮我修理或引导我到可以找到帮助的地方吗?我尝试了几种可能的方法来修复它但是没有用。 问题在于在我的代码中包含语言文件。

以下代码更清晰:

<?php 

if(isSet($_GET['lang']))
$lang = $_GET['lang'];
else $lang='en';

include 'languages/'.$lang.'.php'; 
include("header.php");
?>

P.S我只有2个语言文件,它们是英语=“en.php”和阿拉伯语=“ar.php”

如果有人可以提供帮助,我会非常感激。

2 个答案:

答案 0 :(得分:2)

不要相信用户输入!

<?php 

if ( isset($_GET['lang']) && $_GET['lang'] == 'en') {
    $lang = 'en';
} else {
    $lang = 'ar';
}

include 'languages/'.$lang.'.php'; 
include("header.php");

?>

或者,为可能的其他语言做准备,我会这样:

<?php 

$lang = !empty($_GET['lang']) ? $_GET['lang'] : 'en';

switch($lang) {
    default:
    case 'en':
        include 'languages/en.php'; 
        break;
    case 'ar':
        include 'languages/ar.php'; 
        break;
}

include("header.php");

?>

通过这种方式,您可以在以后轻松添加额外的语言,并始终确保只包含所需的文件。

答案 1 :(得分:1)

漏洞是可以在$lang中发送任何类型的相对路径。如果用户可以上传文件并找出他们在服务器上的真实路径,那么这尤其危险。

示例:

  • 黑客可能会使用您网站的某些文件上传功能上传evil.php。黑客可能知道/已经发现/猜测它存储在/var/www/uploads/evil.php,并且您的应用程序在/var/www/html中运行。
  • 现在,如果无法通过HTTP访问/var/www/uploads,通常没有人可以运行此文件。
  • 但是,可以打开http://example.com/index.php?lang=../../uploads/evil然后猜猜它会包括languages/../../uploads/evil.php哪个会解析为/var/www/uploads/evil.php

这当然也可以在没有文件上传的情况下工作,如果有任何其他文件可以通过访问它们并调用它们来利用某些东西,例如通常受密码保护的目录中的文件(例如phpMyAdmin)。

如果你现在认为“这是相当多的假设和'可能'和'如果在那里,你需要非常幸运能够成功”然后注意 - 尽管有一些显而易见的公然开放你做一个URL调用的漏洞,你可以说,超过服务器或删除数据库,最危险的是那些需要多个拼图才能开发工作的漏洞,因为它们长时间未被发现并且它可能很难理解服务器一旦发生就被实际入侵,你自然会有一个更有经验,因此更危险(可能隐身)的黑客在你家门口。如果某人决心找到一个安全漏洞(或者因为他们的实际目标是攻击你的网站或你,或者因为他们只是喜欢拥有可怜的网站管理员来推动他们自己的自我),他们将继续搜索和拼图所需的一切他们想要什么。

有多种解决方案。

根据u_mulder的建议,如果您只有aren,那么只需检查它是否为一个。

如果您有更多语言,您可以创建一个包含允许值列表的数组,并检查发送的语言是否在该数组中,例如:

$languages = ['de', 'en', 'ar', 'jp', 'fr'];
if(in_array($_GET['lang'], $languages)) {
    $selectedLanguage = $_GET['lang'];
} else {
    $selectedLanguage = 'en'; // default
    // Note that you could also show an error "invalid language" instead
}

如果你想通过仅允许文件夹中存在的文件来控制它,你也可以只验证语言只包含字母(或任何你需要的,只要你确保它可能不包含点或斜杠)或者这样):

if(preg_match("/^[a-z]*$/", $_GET['lang'])) { ... }

请注意,使用此方法,您应该明确地检查指定的文件是否存在,否则通过指定无效语言仍然可以拥有无​​语言的站点(特别是因为include不会抛出不存在的文件出错,与require不同。