ローカルホストでSQLインジェクションを試しています。ユーザー名、パスワード、送信ボタンを備えたシンプルなHTMLフォームがあります。送信をクリックすると、ユーザーはlogin.html
からlogin.php
というページにリダイレクトされます。
<form method="post" action="login.php">
以下は私のPHPコードの一部です:
$connect = mysqli_connect($dbhost, $dbuser, $dbpass) or die("Unable to connect to '$dbhost'");
mysqli_select_db($connect,$dbname) or die("Could not open the database '$dbname'");
$message="";
$username = $_POST["uname"];
$pass_raw = $_POST["password"];
$password = md5($pass_raw);
$result = mysqli_query($connect,"SELECT * FROM students WHERE uname='" . $username . "' and password = '". $password."'");
$row = mysqli_fetch_array($result);
if(is_array($row)) {
echo "Congratulations! you have logged in!";
printf("Your First Name %s and Last Name is %s", $row[3], $row[4]);
printf("Your SSN is %s ", $row[5]);
} else {
$message = "Invalid Username or Password!";
echo "invalid user ";
}
正しいユーザーとパスワードを入力すれば、にログインできます。 SQLインジェクションを実行しようとしていますが、実行できません。 ' or ''='
を使用してみましたが、それでもログインできません。 MariaDBにプリインストールされているKaliでこれを試しています。
MariaDBでは、コメントは スペースが後に続く である必要があります。
「-」から行末まで。 2つのダッシュの後のスペースが必要です(MySQLの場合と同様)。
してみてください ' OR 1=1 --[space]
。
ここで最初に注意する点は、ユーザー名のみを挿入でき、パスワードは挿入できないことです。 passwrodに入力したペイロードは、ハッシュで破棄されます。
では、ユーザー名を' OR '' = '
に設定するとどうなりますか?それを書きましょう:
SELECT * FROM students WHERE uname='' OR '' = '' AND password = '$password'
AND
にはSQLのOR
よりも 優先順位が高い があるため、次のように解釈されます。
SELECT * FROM students WHERE uname='' OR ('' = '' AND password = '$password')
ご覧のとおり、OR
の左側と右側は、名前のないユーザーがいないか、既存のパスワードを入力しない限り、常にfalseになります。
代わりに、注入を行って、ユーザー名を指定するかどうかに応じて、次のようなクエリが作成されるようにします。
SELECT * FROM students WHERE uname='' OR uname='admin' -- ' AND password = '$password'
SELECT * FROM students WHERE uname='' OR 1=1 -- ' AND password = '$password'
ここでの教訓は何ですか?インジェクションの結果と思われるクエリを常に書き出してください。それを分析し、SQLが実際に実行したいことを確認してください。
ユーザー名は脆弱なパスワードのようです。
'or 1=1--
を試して、ユーザー名の後にクエリをコメント化します。
SQLインジェクション攻撃で一重引用符を入力すると、ページのコードをエスケープして処理を続行します。最初に' or ''='
を入力した場合、有効なSQLを挿入していないため、データベースが有効な結果を返すことができません。最初の引用符は「username」変数を終了します。これは次と同等です。
$result = mysqli_query($connect,"SELECT * FROM students WHERE uname='
'または' '='' and password = '". $password."'");
代わりに' or 1=1 --
を使用する場合、結果の式は次のようになります:$result = mysqli_query($connect,"SELECT * FROM students WHERE uname='
'または1 = 1-' and password = '". $password."'");
SQLでは、二重ハイフンの後のすべてがコメントであり、無視されるため、技術的にはそれらの後のすべてを省略できます。しかし、意味のある表現は、結局select * from students where uname='' or 1=1
になります。もちろん1 = 1は「true」と評価されるので、select * from students where uname is set
になります。
すべてのレコードが表示されない唯一の理由は、この脆弱なアプリケーションが結果の最初の行を印刷するためです。複数のレコードを収集するには、テストしているSQLサーバーに応じて、注入されたクエリを' or a* --
、' or a% --
などに変更する必要があります。