一、漏洞描述
复现靶场:通达2017版
漏洞文件:td\webroot\ispirit\interface\gateway.php
漏洞地址: /mac/gateway.php
漏洞POC:json={“url”:“/general/…/…/mysql5/my.ini”}
利用工具:https://github.com/dioos886/Tongda_File_contains
二、原始gateway.php文件代码
<?php
ob_start();
include_once "inc/session.php";
include_once "inc/conn.php";
include_once "inc/utility_org.php";
if ($P != "") {
if (preg_match("/[^a-z0-9;]+/i", $P)) {
echo _("非法参数");
exit();
}
session_id($P);
session_start();
session_write_close();
if (($_SESSION["LOGIN_USER_ID"] == "") || ($_SESSION["LOGIN_UID"] == "")) {
echo _("RELOGIN");
exit();
}
}
if ($json) {
$json = stripcslashes($json);
$json = (array) json_decode($json);
foreach ($json as $key => $val ) {
if ($key == "data") {
$val = (array) $val;
foreach ($val as $keys => $value ) {
$keys = $value;
}
}
if ($key == "url") {
$url = $val;
}
}
if ($url != "") {
if (substr($url, 0, 1) == "/") {
$url = substr($url, 1);
}
if ((strpos($url, "general/") !== false) || (strpos($url, "ispirit/") !== false) || (strpos($url, "module/") !== false)) {
include_once $url;
}
}
exit();
}
?>
根据PHP代码存在以下问题
三、文件包含漏洞:
if ($url != "") {
if (substr($url, 0, 1) == "/") {
$url = substr($url, 1);
}
if ((strpos($url, "general/") !== false) || (strpos($url, "ispirit/") !== false) || (strpos($url, "module/") !== false)) {
include_once $url;
}
}
这部分代码允许从外部传递的JSON数据中提取$url
,然后通过include_once
包含该URL。这样的代码非常危险,因为攻击者可以构造恶意的URL来包含任意文件。解决这个问题的方法是严格限制可以包含的文件,或者使用白名单来验证文件路径。
文件包含代码部分
这段PHP代码的主要目的是包含文件,但它存在安全问题,因为未对输入进行充分验证和过滤,导致文件包含漏洞。让我详细解释这段代码的运行流程和作用:
-
条件检查:代码的第一行是一个条件检查,它检查变量
$url
是否为空字符串。如果$url
不为空(即有值),则会继续执行后续的代码。 -
URL 规范化:接下来,代码使用
substr
函数检查$url
的第一个字符是否是斜杠/
。如果$url
的第一个字符是斜杠,代码将使用substr
函数将斜杠去掉,以规范化$url
,确保它不以斜杠开头。这一步的目的是为了确保$url
的格式符合预期。 -
包含文件:最后,代码使用
strpos
函数检查$url
是否包含子字符串 “general/”、“ispirit/” 或 “module/” 中的任何一个。如果$url
中包含任何一个子字符串,代码将使用include_once
函数来包含$url
指定的文件。- 如果
$url
中包含 “general/”,则会尝试包含名为 “general/” 的文件。 - 如果
$url
中包含 “ispirit/”,则会尝试包含名为 “ispirit/” 的文件。 - 如果
$url
中包含 “module/”,则会尝试包含名为 “module/” 的文件。
- 如果
需要注意的是,如果 $url
中包含多个子字符串(例如 “general/” 和 “ispirit/”),那么将尝试依次包含这些文件,而不会同时包含多个文件。
这段代码的主要问题在于它没有对 $url
进行足够的输入验证和过滤,因此存在文件包含漏洞。攻击者可以构造恶意的 $url
,以尝试包含系统中的敏感文件。为了增加安全性,应该对传入的 $url
进行严格的验证和白名单控制,确保只能包含可信任的文件,同时避免包含恶意文件。
gateway.php文件中的Json未对输入进行充分过滤和验证:
$json = stripcslashes($json);
$json = (array) json_decode($json);
foreach ($json as $key => $val ) {
if ($key == "data") {
$val = (array) $val;
foreach ($val as $keys => $value ) {
$keys = $value;
}
}
if ($key == "url") {
$url = $val;
}
}
这段代码对传入的JSON数据进行了处理,但没有充分验证和过滤输入。恶意用户可以发送恶意JSON数据,导致不可预料的问题。建议对输入数据进行严格的验证和过滤,以防止恶意输入。