Home >Topics >Pagoda Panel >Is the unauthorized access security vulnerability of phpMyAdmin in Pagoda Panel a low-level mistake?

Is the unauthorized access security vulnerability of phpMyAdmin in Pagoda Panel a low-level mistake?

coldplay.xixi
coldplay.xixiforward
2020-08-24 14:21:484710browse

On Sunday night, a message was suddenly released in a certain group. An emergency vulnerability warning of unauthorized access vulnerability existed in phpmyadmin of Pagoda Panel, and a large number of URLs with vulnerabilities were given:

Is the unauthorized access security vulnerability of phpMyAdmin in Pagoda Panel a low-level mistake?

Just click on one of them, and it will be a large phpmyadmin background management page, without any authentication and login. Of course, all kinds of magical pictures and myths later became popular on social networks. As a calm security researcher, of course I laughed it off, but I am still quite interested in the cause of this vulnerability, so in this article we will examine the entire process. The reason for the incident.

1. What is our problem?

First of all, let me give a conclusion: This matter is definitely not simply a pma directory that I forgot to delete, or the pagoda panel was carelessly configured incorrectly, let alone something like someone The official backdoor mentioned in some people’s conspiracy theories is deliberate.

Why do I say that? First of all, according to the official statement, this vulnerability only affects the following versions:

  • Linux official version 7.4.2

  • Linux beta version 7.5.13

  • Windows official version 6.8

This version is the previous version of the latest version (bug fix version). In other words, the version panel before this certain minor version is not affected. Let's think about it, if it's a "backdoor" or a directory that the official forgot to delete, why does it only affect this version? Moreover, Pagoda Panel has been developed for so long and has accumulated 4 million users, and the system security is relatively mature. If there were such inferior errors or "backdoors", they should have been discovered long ago.

After actually checking the cases on the Internet and asking friends who used the pagoda panel, I found that there is no pma directory in versions before 7.4.2, and the authentication method of phpmyadmin requires entering the account password by default. . Therefore, if this vulnerability appears in the pagoda, the following two things must have been done:

  • Added a new pma directory with the content phpmyadmin

  • phpmyadmin's configuration file has been modified to change the authentication method

So, our question becomes, why did the official make these two changes, and what is the purpose?

In order to study this problem, we need to install a Pagoda 7.4.2 version first. However, the installation of Pagoda is a fool-proof one-click script:

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

does not give users an option to choose a version number. The official Git may not have been updated for a long time. How can we install it? What about the appropriate version (7.4.2)?

2. Install a suitable version

Of course this is not a problem for me. First, I installed the latest version of Pagoda Panel, using the one-click script mentioned above.

The installation process is naturally no problem. After the installation is completed, the version number displayed by the system is the latest version 7.4.3, because after the vulnerability was exposed, the official quickly repaired and upgraded it. But it doesn’t matter, we can still find the offline upgrade package:

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

are versions 7.4.0/7.4.2/7.4.3 respectively. We download and unzip them respectively, and try to restore our own server version to the vulnerability Version 7.4.2.

Before restoring the code, we first disconnect the server from the network, or set the pagoda to offline mode:

Is the unauthorized access security vulnerability of phpMyAdmin in Pagoda Panel a low-level mistake?

The purpose of this is to prevent the pagoda from automatically The version is updated to prevent the code that was finally recovered from being automatically upgraded.

The Pagoda system code is installed in /www/server/panel by default. Then we will directly upload the panel directory in the compressed package here, overwriting the existing files. Restart the pagoda and you will find that the system version number has been restored to 7.4.2:

Is the unauthorized access security vulnerability of phpMyAdmin in Pagoda Panel a low-level mistake?

It’s not over yet, we use beyond compare to open the compression of 7.4.2 and 7.4.3 Package code, first look at how the official fixes the vulnerability:

Is the unauthorized access security vulnerability of phpMyAdmin in Pagoda Panel a low-level mistake?

is more crude, directly determine whether the directory /www/server/phpmyadmin/pma exists , if it exists, delete it directly. Therefore, although we have restored the system version code, the deleted pma is no longer there, and we still need to restore this directory.

The method is also very simple. There is a phpmyadmin directory under /www/server/phpmyadmin. We can directly copy this directory:

Is the unauthorized access security vulnerability of phpMyAdmin in Pagoda Panel a low-level mistake?

3. What exactly is the vulnerability

With the environment, we still need to look at the code.

First of all, since 7.4.2 is the version that introduces vulnerabilities, let’s take a look at the official update log for 7.4.2:

Is the unauthorized access security vulnerability of phpMyAdmin in Pagoda Panel a low-level mistake?

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

Is the unauthorized access security vulnerability of phpMyAdmin in Pagoda Panel a low-level mistake?

可见,在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链接,会访问到这样一个路径:

Is the unauthorized access security vulnerability of phpMyAdmin in Pagoda Panel a low-level mistake?

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”按钮,会弹出如下模态框:

Is the unauthorized access security vulnerability of phpMyAdmin in Pagoda Panel a low-level mistake?

There are two access modes in this. "Access through Nginx/Apache/OIs" is the access method of the old version, and "Secure access through the panel" is the newly added proxy mode in 7.4.2.

We click "Secure access through the panel" and capture the packet. We will capture such a data packet:

Is the unauthorized access security vulnerability of phpMyAdmin in Pagoda Panel a low-level mistake?

The Pagoda front-end will store our Mysql account password Fill it out and send it directly to phpmyadmin. And because of the code we analyzed earlier, the account and password are directly written into the phpmyadmin configuration file in the background to achieve authentication-free logic.

What if an unauthenticated user directly accesses http://ip:8888/phpmyadmin/index.php? Will be redirected directly to the login page:

Is the unauthorized access security vulnerability of phpMyAdmin in Pagoda Panel a low-level mistake?

If this is the case, there is no vulnerability in this process. However, the official developer made a mistake. He placed the pma application in the /www/server/phpmyadmin directory, which was originally the Web root directory used by the old phpmyadmin access method.

This means that I can access the new phpmyadmin through the old 888 port pma directory, and the new phpmyadmin has the configuration file officially modified, which ultimately leads to the unauthorized access vulnerability:

Is the unauthorized access security vulnerability of phpMyAdmin in Pagoda Panel a low-level mistake?

So, how to solve this problem? It's also very simple, just move the pma to another directory.

6. Summary

Let’s make a summary.

First of all, the Pagoda panel is definitely not mentally retarded. This vulnerability is not simply a matter of leaving an unauthorized pma outside and forgetting to delete it. This will actually slap a lot of people in the face, because most people think this is just a simple unauthorized access vulnerability of phpmyadmin, and they diss the pagoda, but they did not expect that there is actually a complex logic error behind it.

Secondly, user experience and security are absolutely not in conflict. I really don’t like the practice of emasculating user experience in order to ensure security. Therefore, we hope that the Pagoda official will not completely roll back the code due to this vulnerability incident (it is said that the 7.4.3 update is only a temporary solution), and the areas for improvement still need to be improved.

I haven’t used the Linux panel for a few years. This time I have re-experienced the Linux panel in 2020. Personally, I feel that Pagoda looks like a system that pays more attention to security, such as automatically generated users. Passwords, username and password policies, default Php security configuration, automatic version updates, etc. are definitely better than many other domestic commercial systems. But looking at the code, there are still many areas that need improvement. I will elaborate on this later when I have the opportunity.

This article comes from the public account: https://mp.weixin.qq.com/s/3ZjwFo5gWlJACSkeYWQLXA

The above is the detailed content of Is the unauthorized access security vulnerability of phpMyAdmin in Pagoda Panel a low-level mistake?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:weixin. If there is any infringement, please contact admin@php.cn delete