搜尋
首頁專題寶塔面板寶塔面板phpMyAdmin未授權存取安全漏洞是低階錯誤嗎?

週日晚,某群裡突然發布了一則訊息,寶塔面板的phpmyadmin存在未授權存取漏洞的緊急漏洞預警,並給出了一大批存在漏洞的URL:

寶塔面板phpMyAdmin未授權存取安全漏洞是低階錯誤嗎?

隨便點開其中一個,赫然就是一個大大的phpmyadmin後台管理頁面,不需要任何認證與登入。當然,隨後各種神圖神事也都刷爆了社交網絡,作為一個冷靜安全研究者,我對此當然是一笑置之,但是這個漏洞的原因我還是頗感興趣的,所以本文我們就來考證一下整件事情的緣由。

一、我們的問題究竟是什麼?

首先,我先給出一個結論:這件事情絕對不是簡簡單單地有一個pma目錄忘記刪除了,或者寶塔面板疏忽大意進行了錯誤地配置,更不是像某某些陰謀論中說到的官方刻意留白的後門。

我為什麼這麼說?首先,根據官方的說法,這個漏洞只影響如下版本:

  • Linux正式版7.4.2

  • Linux測試版7.5.13

  • Windows正式版6.8

這個版本就是最新版(漏洞修復版)的前一個版本。也就是說,這個確定的小版本之前的版本面板是不受影響的。我們試想一下,如果是「後門」或官方忘記刪除的目錄,為什麼只影響這個版本呢?況且寶塔面板發展了這麼久,累積了400萬用戶,系統安全性也相對比較成熟,如果存在這麼低劣的錯誤或“後門”,也應該早就被發現了。

經過實際查看互聯網上的案例和詢問使用了寶塔面板的朋友,我發現在7.4.2以前的版本中沒有pma這個目錄,並且phpmyadmin默認情況下認證方法是需要輸入帳號密碼的。所以,寶塔出現這個漏洞,一定是做了下面這兩件事:

  • 新增了一個pma目錄,內容phpmyadmin

  • phpmyadmin的設定檔被修改了認證方式

那麼,我們的問題就變成了,官方為什麼要做這兩處修改,目的究竟是什麼?

為了研究這個問題,我們需要先安裝一個寶塔7.4.2版本。但是,寶塔的安裝是一個傻瓜化的一鍵化腳本:

yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh

並沒有給到用戶一個可以選擇版本號的選項,官方的Git也許久沒更新了,我們如何才能安裝到一個合適的版本(7.4.2)呢?

二、安裝一個合適的版本

這當然難不倒我。首先,我安裝了最新版的寶塔面板,用的就是上述一鍵化腳本。

安裝的過程自然沒什麼問題,安裝完成後,系統顯示的版本號是最新版7.4.3,因為在爆出這個漏洞以後,官方迅速進行了修復升級。不過沒關係,我們還是可以找到離線升級套件:

http://download.bt.cn/install/update/LinuxPanel-7.4.0.zip
http://download.bt.cn/install/update/LinuxPanel-7.4.2.zip
http://download.bt.cn/install/update/LinuxPanel-7.4.3.zip

分別是7.4.0/7.4.2/7.4.3的版本,我們分別下載並解壓縮,並嘗試將自己的伺服器版本還原成漏洞版本7.4.2。

在恢復程式碼之前,我們先將伺服器斷網,或是將寶塔設定成離線模式:

寶塔面板phpMyAdmin未授權存取安全漏洞是低階錯誤嗎?

這麼做的目的是防止寶塔進行自動版本更新,避免好不容易恢復的程式碼又自動升級了。

寶塔系統程式碼預設安裝完是在/www/server/panel,接著我們直接將將壓縮包內的panel目錄上傳到這裡來,覆蓋掉現有的檔案。重新啟動下寶塔,即可發現系統版本號碼已經恢復成7.4.2了:

寶塔面板phpMyAdmin未授權存取安全漏洞是低階錯誤嗎?

還沒完,我們使用beyond compare打開7.4.2和7.4.3的壓縮套件程式碼,先看看官方是怎麼修復的漏洞:

寶塔面板phpMyAdmin未授權存取安全漏洞是低階錯誤嗎?

比較粗暴,直接判斷目錄/www/server/phpmyadmin/pma是否存在,如果存在就直接刪掉。所以,我們雖然恢復了系統版本程式碼,但刪掉的pma已經不在了,我們還需要恢復這個目錄。

方法也很簡單,/www/server/phpmyadmin下本身存在一個phpmyadmin目錄,我們直接複製這個目錄即可:

寶塔面板phpMyAdmin未授權存取安全漏洞是低階錯誤嗎?

三、漏洞究竟是怎麼回事

有了環境,我們仍需看看程式碼。

首先,由於7.4.2是引入漏洞的版本,我們來看看官方對7.4.2的更新日誌:

寶塔面板phpMyAdmin未授權存取安全漏洞是低階錯誤嗎?

用beyond compare打开7.4.0和7.4.2的压缩包代码,看看具体增加了哪些代码:

寶塔面板phpMyAdmin未授權存取安全漏洞是低階錯誤嗎?

可见,在7.4.2版本中增加了两个视图,分别对应着phpmyadmin和adminer。视图中用到了panelPHP#start方法,这个方法其实也是新加的:

    def start(self,puri,document_root,last_path = ''):
        '''
            @name 开始处理PHP请求
            @author hwliang<2020-07-11>
            @param puri string(URI地址)
            @return socket or Response
        &#39;&#39;&#39;
        ...
        #如果是PHP文件
        if puri[-4:] == &#39;.php&#39;:
            if  request.path.find(&#39;/phpmyadmin/&#39;) != -1:
                ...
                if request.method == &#39;POST&#39;:
                    #登录phpmyadmin
                    if puri in [&#39;index.php&#39;,&#39;/index.php&#39;]:
                        content = public.url_encode(request.form.to_dict())
                        if not isinstance(content,bytes):
                            content = content.encode()
                        self.re_io = StringIO(content)
                        username = request.form.get(&#39;pma_username&#39;)
                        if username:
                            password = request.form.get(&#39;pma_password&#39;)
                            if not self.write_pma_passwd(username,password):
                                return Resp(&#39;未安装phpmyadmin&#39;)
                if puri in [&#39;logout.php&#39;,&#39;/logout.php&#39;]:
                    self.write_pma_passwd(None,None)
            else:
                ...
      #如果是静态文件
        return send_file(filename)

           

代码太长,我们不展开分析,只我写出来的部分。在请求的路径是/phpmyadmin/index.php且存在pma_usernamepma_password时,则执行self.write_pma_passwd(username,password)

跟进self.write_pma_passwd:

    def write_pma_passwd(self,username,password):
        &#39;&#39;&#39;
            @name 写入mysql帐号密码到配置文件
            @author hwliang<2020-07-13>
            @param username string(用户名)
            @param password string(密码)
            @return bool
        &#39;&#39;&#39;
        self.check_phpmyadmin_phpversion()
        pconfig = &#39;cookie&#39;
        if username:
            pconfig = &#39;config&#39;
        pma_path = &#39;/www/server/phpmyadmin/&#39;
        pma_config_file = os.path.join(pma_path,&#39;pma/config.inc.php&#39;)
        conf = public.readFile(pma_config_file)
        if not conf: return False
        rep = r"/\* Authentication type \*/(.|\n)+/\* Server parameters \*/"
        rstr = &#39;&#39;&#39;/* Authentication type */
$cfg[&#39;Servers&#39;][$i][&#39;auth_type&#39;] = &#39;{}&#39;;
$cfg[&#39;Servers&#39;][$i][&#39;host&#39;] = &#39;localhost&#39;; 
$cfg[&#39;Servers&#39;][$i][&#39;port&#39;] = &#39;{}&#39;;
$cfg[&#39;Servers&#39;][$i][&#39;user&#39;] = &#39;{}&#39;; 
$cfg[&#39;Servers&#39;][$i][&#39;password&#39;] = &#39;{}&#39;; 
/* Server parameters */&#39;&#39;&#39;.format(pconfig,self.get_mysql_port(),username,password)
        conf = re.sub(rep,rstr,conf)
        public.writeFile(pma_config_file,conf)
        return True

这个代码也很好理解了,如果传入了username和password的情况下,宝塔会改写phpmyadmin的配置文件config.inc.php,将认证方式改成config,并写死账号密码。

这就是为什么7.4.2版本中pma可以直接访问的原因。

补个课:

phpmyadmin支持数种认证方法,默认情况下是Cookie认证,此时需要输入账号密码;用户也可以将认证方式修改成Config认证,此时phpmyadmin会使用配置文件中的账号密码来连接mysql数据库,即不用再输入账号密码。

四、官方做这些动作的原因

其实各位看官看到这里肯定脑子里还是一团浆糊,这些代码究竟意味着什么呢?为什么官方要将认证模式改成config模式?

是很多漏洞分析文章的通病,这些文章在出现漏洞后跟一遍漏洞代码,找到漏洞发生点和利用方法就结束了,并没有深入研究开发为什么会这么写,那么下次你还是挖不出漏洞。

所以,这里思考一下,我们现在起码还有下列疑问:

  • 在7.4.2版本以前,用户是如何使用phpmyadmin的?

  • 宝塔为什么要在7.4.2版本增加phpmyadmin有关的视图?

  • 宝塔为什么要将phpmyadmin认证模式改成config?

我们如何复现这个漏洞?

第一个问题,我们其实可以简单找到答案。在正常安装宝塔最新版7.4.3时,我们点击宝塔后台的phpmyadmin链接,会访问到这样一个路径:

寶塔面板phpMyAdmin未授權存取安全漏洞是低階錯誤嗎?

7.4.3版本为了修复这个漏洞,回滚了部分代码,所以这种方式其实就是7.4.2以前版本的phpmyadmin的访问方式:通过888端口下的一个以phpmyadmin_开头的文件夹直接访问phpmyadmin。

这种老的访问方法中,888端口是一个单独的Nginx或Apache服务器,整个东西是安全的,访问也需要输入账号密码。

但是这种访问方法有些麻烦,需要额外开放888端口,而且每次登陆都要重新输入密码。所以,官方开发人员提出了一种新的做法,在宝塔后端的python层面转发用户对phpmyadmin的请求给php-fpm。这样有三个好处:

  • 直接在python层面做用户认证,和宝塔的用户认证进行统一,不需要多次输入mysql密码

  • 也不需要再对外开放888端口了

  • 使用phpmyadmin也不再依赖于Nginx/Apache等服务器中间件了

这就是为什么宝塔要在7.4.2增加phpmyadmin有关的视图的原因,这个视图就是一个phpmyadmin的代理,做的事情就是转发用户的请求给php-fpm。

用户在第一次使用这种方式登录时,系统会自动发送包含了Mysql账号密码的数据包,宝塔后端会捕捉到此时的账号密码,填入phpmyadmin的配置文件,并将认证方式改成config。对于用户来说,感受到的体验就是,不再需要输入任何Mysql密码即可使用phpmyadmin了。

这的确给用户的使用带来了更好的体验。

五、漏洞复现

此时我们应该还有个疑问:既然官方目的是“直接在python层面做用户认证,和宝塔的用户认证进行统一”,那么仍然是有认证的呀?为什么会出现未授权访问漏洞呢?

我们可以来复现一下这个漏洞。首先,我们以系统管理员的身份登录宝塔后台,来到数据库页面,点击“phpMyAdmin”按钮,会弹出如下模态框:

寶塔面板phpMyAdmin未授權存取安全漏洞是低階錯誤嗎?

這裡面有兩種存取模式,「透過Nginx/Apache/OIs存取」是舊版的存取方式,「透過面板安全存取」就是7.4.2新增加的代理模式。

我們點擊“透過面板安全存取”,並抓包,會抓到這樣一個資料包:

寶塔面板phpMyAdmin未授權存取安全漏洞是低階錯誤嗎?

寶塔前端將我們的Mysql帳號密碼填好了直接發給phpmyadmin。又因為我們前面分析過的那段程式碼,後台將帳號密碼直接寫入了phpmyadmin設定文件,來做到免認證的邏輯。

如果一個未經認證的用戶,那麼直接訪問http://ip:8888/phpmyadmin/index.php呢?會直接重定向到登入頁面:

寶塔面板phpMyAdmin未授權存取安全漏洞是低階錯誤嗎?

如果只是這樣,這個過程是不存在漏洞的。但是,官方開發人員犯了一個錯誤,他將pma應用放在了/www/server/phpmyadmin目錄下,而這個目錄原本是老的phpmyadmin訪問方式所使用的Web根目錄。

這意味著,我透過舊的888埠pma目錄,可以存取到新的phpmyadmin,而新的phpmyadmin又被官方修改了設定文件,最終導致了未授權存取漏洞:

寶塔面板phpMyAdmin未授權存取安全漏洞是低階錯誤嗎?

所以,要如何解決這個問題呢?也很簡單,只需要將pma移到其他目錄去。

六、總結

我們來做個總結。

首先,寶塔面板絕對不是弱智,這個漏洞不是簡簡單單的放了一個未授權的pma在外面忘記刪。這其實會打很多人臉,因為大部分人認為這只是個簡單的phpmyadmin未授權存取漏洞,並對寶塔進行了一頓diss,沒有想到這後面其實是一個複雜的邏輯錯誤。

其次,使用者體驗和安全絕對是不衝突的,我十分不喜歡為了保障安全而閹割使用者體驗的做法。所以希望寶塔官方不會因為這次的漏洞事件而徹底將程式碼回溯(據說7.4.3的更新只是臨時解決方案),該改進的地方還是要改進。

我有好幾年不再使用Linux面板了,這次也算重新體驗了一下2020年的Linux面板,個人感覺寶塔看外在其實是一個比較注重安全的系統,比如自動生成的用戶密碼、使用者名稱和密碼的政策、預設的Php安全配置、自動的版本更新等等,相較於許多國內其他的商業系統,絕對屬於有過之而無不及了。但看程式碼其實需要改進的地方還有很多,以後有機會再細說吧。

本文來自公眾編號:https://mp.weixin.qq.com/s/3ZjwFo5gWlJACSkeYWQLXA

以上是寶塔面板phpMyAdmin未授權存取安全漏洞是低階錯誤嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:weixin。如有侵權,請聯絡admin@php.cn刪除

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)