Created 星期一 11 三月 2019
2019年3月11号 状态:饿 心情:饿到痴呆

攻击说明

攻击途径:远程网络
攻击复杂度:低
认证:需要管理员后台权限
机密性:完全地
完整性:受影响,会修改到语言标签
可用性:不受影响

问题产生:

之前以为老哥日了个ecshop的站点,搞到了后台管理员的权限,想拿shell的时候发现之前网上公开的后台getshell的方法现在都不能用了,于是拜托在下再整个后台shell的漏洞出来。分析了两天后,于是有了下面的后台拿shell的方法。

0x01.代码位置:

漏洞代码位置:\admin\edit_languages.php 第96-144行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*------------------------------------------------------ */
//-- 编辑语言项
/*------------------------------------------------------ */
elseif ($_REQUEST['act'] == 'edit')
{
/* 语言项的路径 */
$lang_file = isset($_POST['file_path']) ? trim($_POST['file_path']) : '';

/* 替换前的语言项 */
$src_items = !empty($_POST['item']) ? stripslashes_deep($_POST['item']) : '';

/* 修改过后的语言项 */
$dst_items = array();
$_POST['item_id'] = stripslashes_deep($_POST['item_id']);

for ($i = 0; $i < count($_POST['item_id']); $i++)
{
/* 语言项内容如果为空,不修改 */
if (trim($_POST['item_content'][$i]) == '')
{
unset($src_items[$i]);
}
else
{
$_POST['item_content'][$i] = str_replace('\\\\n', '\\n', $_POST['item_content'][$i]);
// $dst_items[$i] = $_POST['item_id'][$i] .' = '. '"' .$_POST['item_content'][$i]. '";';
$dst_items[$i] = $_POST['item_id'][$i] .' = '. '\'' .$_POST['item_content'][$i]. '\';';
}
}

/* 调用函数编辑语言项 */
$result = set_language_items($lang_file, $src_items, $dst_items);

if ($result === false)
{
/* 修改失败提示信息 */
$link[] = array('text' => $_LANG['back_list'], 'href' => 'javascript:history.back(-1)');
sys_msg($_LANG['edit_languages_false'], 0, $link);
}
else
{
/* 记录管理员操作 */
admin_log('', 'edit', 'languages');

/* 清除缓存 */
clear_cache_files();

/* 成功提示信息 */
$link[] = array('text' => $_LANG['back_list'], 'href' => 'edit_languages.php?act=list');
sys_msg($_LANG['edit_languages_success'], 0, $link);
}
}

再进入函数set_language_items(),看看具体实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/**
* 设置语言项
* @access public
* @param string $file_path 存放语言项列表的文件的绝对路径
* @param array $src_items 替换前的语言项
* @param array $dst_items 替换后的语言项
* @return void 成功就把结果写入文件,失败返回false
*/
function set_language_items($file_path, $src_items, $dst_items)
{
/* 检查文件是否可写(修改) */
if (file_mode_info($file_path) < 2)
{
return false;
}

/* 获取文件内容 */
$line_array = file($file_path);
if (!$line_array)
{
return false;
}
else
{
$file_content = implode('', $line_array);
}

$snum = count($src_items);
$dnum = count($dst_items);
if ($snum != $dnum)
{
return false;
}
/* 对索引进行排序,防止错位替换 */
ksort($src_items);
ksort($dst_items);
for ($i = 0; $i < $snum; $i++)
{
$file_content = str_replace($src_items[$i], $dst_items[$i], $file_content);

}

/* 写入修改后的语言项 */
$f = fopen($file_path, 'wb');
if (!$f)
{
return false;
}
if (!fwrite($f, $file_content))
{
return false;
}
else
{
return true;
}
}

代码分析:
该段代码的逻辑简单解释来说就是拼接用户提交的数据内容,写入到语言项脚本文件中。有一定的数据过滤。

0x02.缺陷利用

直接想使用该漏洞的哥们,以上的分析没什么必要去仔细地研究,直接看下面的利用方法就行了。
1.漏洞位置:模板管理->语言项编辑:
ACs1ts.md.png
2.点击确认修改后抓取数据包,修改数据包中指定的字段,插入php可执行代码:
ACsDhR.md.png
ACsRBD.md.png
3.于是查看一下修改的文件结果:
ACsLDS.png
4.直接url请求这个文件,就达到了代码注入的效果:
ACyp3q.md.png

修复建议

1.不允许用户修改指定参数。