日曜日の夜、あるグループで突然メッセージが公開され、パゴダパネルのphpmyadminに不正アクセスの脆弱性に関する緊急脆弱性警告が存在し、脆弱性のあるURLが多数公開されました:
そのうちの 1 つをクリックするだけで、認証やログインを必要としない大きな phpmyadmin バックグラウンド管理ページが表示されます。もちろん、その後、あらゆる種類の魔法の絵や神話がソーシャル ネットワークで人気になりました。冷静なセキュリティ研究者としては、もちろん笑い飛ばしましたが、それでもこの脆弱性の原因には非常に興味があります。プロセス全体、インシデントの理由。
1. 私たちの問題は何ですか?
まず最初に結論を述べておきます。この問題は、単に私が削除し忘れた pma ディレクトリや、パゴダ パネルが不注意で間違って設定されただけでは決してありません。ましてや誰かのようなものではありません。一部の人々の陰謀論で言及されているバックドアは意図的なものです。
なぜそんなことを言うのでしょうか?まず、公式声明によると、この脆弱性は次のバージョンにのみ影響します:
Linux 正式バージョン 7.4.2
Linux ベータ版バージョン 7.5.13
Windows 正式バージョン 6.8
このバージョンは、最新バージョン (バグ修正バージョン) の前のバージョンです。つまり、この特定のマイナー バージョンより前のバージョン パネルは影響を受けません。考えてみましょう。それが「バックドア」または公式が削除し忘れたディレクトリである場合、なぜこのバージョンにのみ影響があるのでしょうか?さらに、パゴダパネルは長い間開発され、400万人のユーザーを蓄積しており、システムのセキュリティは比較的成熟しており、そのような劣悪なエラーや「バックドア」があった場合、それらはずっと前に発見されているはずです。
実際にインターネットで事例を確認したり、pagoda パネルを使用している友人に聞いたりしたところ、7.4.2 より前のバージョンには pma ディレクトリがなく、phpmyadmin の認証方法ではアカウントのパスワードを入力する必要があることがわかりました。デフォルト。 。したがって、この脆弱性がパゴダに現れた場合、次の 2 つのことが行われたはずです。
コンテンツ phpmyadmin
yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.shでは、ユーザーにバージョン番号を選択するオプションがありません。公式の Git は長い間更新されていない可能性があります。インストールしますか? 適切なバージョン (7.4.2) はどうですか?
2. 適切なバージョンをインストールします
もちろん、これは私にとって問題ではありません。まず、上記のワンクリック スクリプトを使用して、Pagoda Panel の最新バージョンをインストールしました。 インストールプロセスは当然問題ありませんが、脆弱性が露呈した後、公式がすぐに修復してアップグレードしたため、インストール完了後にシステムに表示されるバージョン番号は最新のバージョン 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 に更新します。 コードを復元する前に、まずサーバーをネットワークから切断するか、パゴダをオフライン モードに設定します。 これの目的は、次のことを防ぐことです。最終的に回復されたコードが自動的にアップグレードされないように、バージョンが更新されます。 Pagoda システム コードはデフォルトで
/www/server/panel にインストールされます。次に、圧縮パッケージ内のパネル ディレクトリをここに直接アップロードし、既存のファイルを上書きします。パゴダを再起動すると、システムのバージョン番号が 7.4.2 に復元されていることがわかります。
/www/server かどうかを直接判断します。 /phpmyadmin/pma が存在します。存在する場合は、直接削除します。したがって、システムのバージョン コードは復元しましたが、削除された pma はもう存在しないため、このディレクトリを復元する必要があります。
/www/server/phpmyadmin に phpmyadmin ディレクトリがあります。このディレクトリを直接コピーできます:
3. 脆弱性とは正確には何ですか
環境に関しては、やはりコードを確認する必要があります。 まず、7.4.2 は脆弱性が導入されたバージョンであるため、7.4.2 の公式アップデート ログを見てみましょう:用beyond compare打开7.4.0和7.4.2的压缩包代码,看看具体增加了哪些代码:
可见,在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 ''' ... #如果是PHP文件 if puri[-4:] == '.php': if request.path.find('/phpmyadmin/') != -1: ... if request.method == 'POST': #登录phpmyadmin if puri in ['index.php','/index.php']: 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('pma_username') if username: password = request.form.get('pma_password') if not self.write_pma_passwd(username,password): return Resp('未安装phpmyadmin') if puri in ['logout.php','/logout.php']: self.write_pma_passwd(None,None) else: ... #如果是静态文件 return send_file(filename)
代码太长,我们不展开分析,只我写出来的部分。在请求的路径是/phpmyadmin/index.php
且存在pma_username
、pma_password
时,则执行self.write_pma_passwd(username,password)
。
跟进self.write_pma_passwd:
def write_pma_passwd(self,username,password): ''' @name 写入mysql帐号密码到配置文件 @author hwliang<2020-07-13> @param username string(用户名) @param password string(密码) @return bool ''' self.check_phpmyadmin_phpversion() pconfig = 'cookie' if username: pconfig = 'config' pma_path = '/www/server/phpmyadmin/' pma_config_file = os.path.join(pma_path,'pma/config.inc.php') conf = public.readFile(pma_config_file) if not conf: return False rep = r"/\* Authentication type \*/(.|\n)+/\* Server parameters \*/" rstr = '''/* Authentication type */ $cfg['Servers'][$i]['auth_type'] = '{}'; $cfg['Servers'][$i]['host'] = 'localhost'; $cfg['Servers'][$i]['port'] = '{}'; $cfg['Servers'][$i]['user'] = '{}'; $cfg['Servers'][$i]['password'] = '{}'; /* Server parameters */'''.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链接,会访问到这样一个路径:
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”按钮,会弹出如下模态框:
これには 2 つのアクセス モードがあり、「Nginx/Apache/OIs を介したアクセス」は旧バージョンのアクセス方法、「パネルを介したセキュア アクセス」は 7.4.2 で新しく追加されたプロキシ モードです。
「パネルを介したアクセスを保護する」をクリックしてパケットをキャプチャします。このようなデータ パケットをキャプチャします:
Pagoda フロントエンドは次のデータ パケットを保存します。 Mysql アカウントのパスワードを入力し、phpmyadmin に直接送信します。また、以前に分析したコードにより、認証不要のロジックを実現するために、アカウントとパスワードがバックグラウンドで phpmyadmin 構成ファイルに直接書き込まれます。
認証されていないユーザーが http://ip:8888/phpmyadmin/index.php
に直接アクセスした場合はどうなりますか?ログイン ページに直接リダイレクトされます:
この場合、このプロセスには脆弱性はありません。しかし、正式な開発者は間違いを犯し、pma アプリケーションを /www/server/phpmyadmin
ディレクトリに配置しました。このディレクトリは、元々は古い phpmyadmin アクセス方法で使用されていた Web ルート ディレクトリでした。
これは、古い 888 ポートの pma ディレクトリを介して新しい phpmyadmin にアクセスでき、新しい phpmyadmin の設定ファイルが正式に変更されていることを意味します。これが最終的に不正アクセスの脆弱性につながります。
#それでは、この問題をどうやって解決すればよいでしょうか?これも非常に簡単で、pma を別のディレクトリに移動するだけです。6. まとめ
では、まとめをしてみましょう。 まず第一に、Pagoda パネルは間違いなく精神薄弱者ではありません。この脆弱性は、単に無許可の PMA を屋外に放置し、削除するのを忘れただけの問題ではありません。これは実際に多くの人の顔を平手打ちすることになるでしょう。なぜなら、ほとんどの人はこれが phpmyadmin の単純な不正アクセスの脆弱性であると考えており、パゴダを否定しますが、実際にその背後に複雑な論理エラーがあるとは予想していなかったからだ。 第二に、ユーザー エクスペリエンスとセキュリティはまったく矛盾しません。セキュリティを確保するためにユーザー エクスペリエンスを骨抜きにするという行為は、私は本当に好きではありません。したがって、パゴダ公式が今回の脆弱性インシデントによってコードを完全にロールバックしないことを祈ります(7.4.3アップデートは一時的な解決策にすぎないと言われています)し、改善すべき点はまだ改善される必要があります。 Linux パネルはここ数年使っていませんでしたが、今回 2020 年に Linux パネルを再体験してみました。個人的には Pagoda はセキュリティに気を配ったシステムのように感じましたパスワード、ユーザー名とパスワードのポリシー、デフォルトの Php セキュリティ構成、自動バージョン更新などは、他の多くの国内商用システムよりも明らかに優れています。ただ、コードを見るとまだまだ改善が必要な部分が多いので、これについてはまた機会があれば詳しく説明したいと思います。 この記事は公開アカウントからのものです: https://mp.weixin.qq.com/s/3ZjwFo5gWlJACSkeYWQLXA以上がPagoda パネルの phpMyAdmin の不正アクセスのセキュリティ脆弱性は、低レベルの間違いですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。