免责申明
本文章仅用于信息安全防御技术分享,因用于其他用途而产生不良后果,作者不承担任何法律责任,请严格遵循中华人民共和国相关法律法规,禁止做一切违法犯罪行为。
一、前言
某次对一个最新版本的某设备进行代码审计,并成功审计得到前台SQL注入漏洞。
二、审计流程
查看项目结构:可以知道是非框架方式。
查看文件目录结构可以看出来不是框架类型的,我们找到相关的鉴权。 这里其实直接可以看出来在chksession方法可以进行鉴权,避开他进行审计。
在文件xxx/xxxx/xxxx.php当中存在一个相关的漏洞。
代码如下:
<?php
include "common.php";
$userinfo = file_get_contents('php://input');
if (empty($userinfo)) {
outputres("no", "NO_USERINFO");
exit;
}
$json = json_decode($userinfo);
$operation_type = $json->syncInfo->operationType;
if (($conn = my_mysql_connect()) == false) {
outputres("no", "MYSQL_CONNECT_ERROR");
exit;
}
$sql = $sql2 = "";
/*
* 创建singleuser表
*/
if ($operation_type == "ADD_USER" || $operation_type == "UPDATE_USER" ||
$operation_type == "DELETE_USER") {
$sql = "create table if not exists palog.singleuser(".
"id int not null auto_increment primary key, ".
"user_id VARCHAR(32) NOT NULL DEFAULT '',".
"account_status varchar(8) not null default '',".
"user_name VARCHAR(200) NOT NULL DEFAULT '',".
"user_pwd varchar(64) NOT NULL DEFAULT '',".
"user_sex varchar(2) NOT NULL DEFAULT '',".
"user_birthday varchar(19) NOT NULL DEFAULT '',".
"user_post varchar(50) NOT NULL DEFAULT '',".
"user_rank varchar(50) NOT NULL DEFAULT '',".
"user_phone varchar(50) NOT NULL DEFAULT '',".
"user_mobilephone varchar(50) NOT NULL DEFAULT '',".
"user_mailaddress varchar(50) NOT NULL DEFAULT '',".
"user_ca varchar(4000) NOT NULL DEFAULT '',".
"user_class varchar(32) NOT NULL DEFAULT '',".
"parent_id varchar(30) NOT NULL DEFAULT '',".
"employee_id varchar(30) NOT NULL DEFAULT '',".
"department_id varchar(30) NOT NULL DEFAULT '',".
"coporation_id varchar(30) NOT NULL DEFAULT '',".
"user_duty varchar(200) NOT NULL DEFAULT '',".
"user_postcode varchar(50) NOT NULL DEFAULT '',".
"user_alias varchar(100) NOT NULL DEFAULT '',".
"user_homeaddress varchar(200) NOT NULL DEFAULT '',".
"user_msn varchar(50) NOT NULL DEFAULT '',".
"user_nt varchar(256) NOT NULL DEFAULT '',".
"bxlx varchar(10) NOT NULL DEFAULT ''".
")ENGINE=MyISAM default charset=utf8";
if (mysql_query($sql) == false) {
outputres("no", mysql_error());
mysql_close();
exit;
}
$user_id = $json->syncInfo->user->userId;
$user_name = $json->syncInfo->user->userName;
$employee_id= $json->syncInfo->user->employeeId;
$department_id = $json->syncInfo->user->departmentId;
$department_name = $json->syncInfo->user->departmentName;
$coporation_id = $json->syncInfo->user->coporationId;
$corporation_name = $json->syncInfo->user->corporationName;
$user_sex = $json->syncInfo->user->userSex;
$user_duty = $json->syncInfo->user->userDuty;
$user_birthday = $json->syncInfo->user->userBirthday;
$user_post = $json->syncInfo->user->userPost;
$user_postCode = $json->syncInfo->user->userPostCode;
$user_alias = $json->syncInfo->user->userAlias;
$user_rank = $json->syncInfo->user->userRank;
$user_phone = $json->syncInfo->user->userPhone;
$user_homeaddress = $json->syncInfo->user->userHomeAddress;
$user_mobilephone = $json->syncInfo->user->userMobilePhone;
$user_mailaddress = $json->syncInfo->user->userMailAddress;
$user_msn = $json->syncInfo->user->userMSN;
$user_nt = $json->syncInfo->user->userNt;
$user_ca = $json->syncInfo->user->userCA;
$user_pwd = $json->syncInfo->user->userPwd;
$user_class = $json->syncInfo->user->userClass;
$parent_id = $json->syncInfo->user->parentId;
$bxlx = $json->syncInfo->user->bxlx;
switch($operation_type) {
case "ADD_USER":
$sql = "insert into palog.singleuser(user_id, user_name, user_pwd, account_status, user_sex, user_birthday, user_post, user_rank, user_phone, user_mobilephone, user_mailaddress, user_ca, user_class, parent_id, employee_id, department_id, coporation_id, user_duty, user_postcode, user_alias, user_homeaddress, user_msn, user_nt, bxlx) values('$user_id', '$user_name', '$user_pwd', '$account_status', '$user_sex', '$user_birthday', '$user_post', '$user_rank', '$user_phone', '$user_mobilephone', '$user_mailaddress', '$user_ca', '$user_class', '$parent_id', '$employee_id', '$department_id', '$coporation_id', '$user_duty', '$user_postcode', '$user_alias', '$user_homeaddress', '$user_msn', '$user_nt', '$bxlx')";
$sql2 = "insert into palog.users(username, password, mod_1)values('$user_id', '$user_pwd', 'Y')";
break;
case "DELETE_USER":
$sql = "delete from palog.singleuser where user_id='$user_id'";
$sql2 = "delete from palog.users where username='$user_id'";
break;
case "UPDATE_USER":
$sql = "update palog.singleuser set user_name='$user_name', user_pwd='$user_pwd', account_status='$account_status', user_sex='$user_sex', user_birthday='$user_birthday', user_post='$user_post', user_rank='$user_rank', user_phone='$user_phone', user_mobilephone='$user_mobilephone', user_mailaddress='$user_mailaddress', user_ca='$user_ca', user_class='$user_class', parent_id='$parent_id', employee_id='$employee_id', department_id='$department_id', coporation_id='$coporation_id', user_duty='$user_duty', user_postcode='$user_postcode', user_alias='$user_alias', user_homeaddress='$user_homeaddress', user_msn='$user_msn', user_nt='$user_nt', bxlx='$bxlx' where user_id='$user_id'";
break;
}
}
else
if ($operation_type == "ADD_ORGAN" || $operation_type == "DELETE_ORGAN" ||
$operation_type == "UPDATE_ORGAN" || $operation_type == "MERGE_ORGAN") {
/*
* 创建表
*/
$sql = "create table if not exists palog.single_organ(id int auto_increment primary key, organ_id varchar(30) not null default '', organ_name varchar(80) not null default '', organ_type varchar(32) not null default '', parent_id varchar(30) not null default '', stru_id varchar(50) not null default '', stru_type varchar(32) not null default '', stru_path varchar(64) not null default '', department_id varchar(30) not null default '', department_name varchar(80) not null default '', coporation_id varchar(30) not null default '', corporation_name varchar(80) not null default '', is_use char(1) not null default '1', is_leaf varchar(1) not null default '')ENGINE=MyISAM DEFAULT charset=utf8";
if (mysql_query($sql) == false) {
outputres("no", mysql_error());
mysql_close();
exit;
}
$stru_id = $json->syncInfo->stru->struId;
$organ_id = $json->syncInfo->stru->organId;
$stru_type = $json->syncInfo->stru->struType;
$parent_id = $json->syncInfo->stru->parentId;
$stru_path = $json->syncInfo->stru->struPath;
$organ_code = $json->syncInfo->stru->organCode;
$organ_name = $json->syncInfo->stru->organName;
$organ_type = $json->syncInfo->stru->organType;
$department_id = $json->syncInfo->stru->departmentId;
$department_name = $json->syncInfo->stru->departmentName;
$corporation_name = $json->syncInfo->stru->corporationName;
$is_leaf = $json->syncInfo->stru->isLeaf;
$is_use = $json->syncInfo->stru->isUse;
switch($operation_type) {
case "ADD_ORGAN":
$sql = "insert into palog.single_organ(organ_id, organ_name, organ_type, parent_id, stru_id, stru_type, stru_path, department_id, department_name, coporation_id, corporation_name, is_use, is_leaf) values('$organ_id', '$organ_name', '$organ_type', '$parent_id', '$stru_id', '$stru_type', '$stru_path', '$department_id', '$department_name', '$coporation_id', '$corporation_name', '$is_use', '$is_leaf')";
break;
case "DELETE_ORGAN":
$sql = "delete from palog.single_organ where organ_id='$organ_id'";
break;
case "UPDATE_ORGAN":
$sql = "update palog.single_organ set organ_name='$organ_name', organ_type='$organ_type', stru_id='$stru_id', stru_type='$stru_type', stru_path='$stru_path', department_id='$department_id', department_name='$department_name', coporation_id='$coporation_id', corporation_name='$corporation_name' where organ_id='$organ_id'";
break;
case "MERGE_ORGAN":
break;
default:
outputres("no", "NO_ACTION");
mysql_close();
exit;
}
}
else {
mysql_close();
outputres("no", "NO_OPERATION_TYPE");
exit;
}
if (mysql_query($sql) == false) {
outputres("no", mysql_error());
mysql_close();
exit;
}
if ($sql2 != "")
mysql_query($sql2);
mysql_close();
outputres("yes", "OK");
exit;
?>
然后将传递当中的syncInfo当中的operationType传递给$operation_type
其实这种方式传递参数就是如下方式:
{
"syncInfo":
{
"operationType":"value"
}
}
以这种方式进行传递参数,刚好在下面可以看到一个信息。
可以看到user_id进行回溯。
$user_id = $json->syncInfo->user->userId;
可以看到是通过$json过来的,看看$json
发现我们的参数可控,然后进行查看要求因为上面有case分支,查看这个分支。
三、漏洞利用
分支也是可控的,所以我们直接可以进行构造数据包进行测试。
这里没办法直接使用sqlmap注入,我们写好了相关POC。
输出还需要小小的优化一下hhhh
这里有一个小的tips就是,正常我们执行语句为select * from user;这种,但是前提要求是指定数据库,然后这个源码当中并未指定相关数据库,所以要查询user需要如下语句:
select * from 数据库.user;方式来进行查询。
原文链接:
没有回复内容