111年高考三級程式設計
二、資料庫是企業組織或政府部門中用以保存大量資料的機制。下圖為資料表的結構,請回答以下各小題。(每小題10分,共20分) (一)請以 SQL 列出某一個人的年度薪資總額,必須顯示 id, first_name, last_name 及總額。 (二)現在的資料查詢服務常見於網頁系統,而 SQL Injection 是最常見的資料庫攻擊方式。請問下列查詢語句是否會有被攻擊的疑慮?若有的話該如何改善?程式碼可以使用 PHP 或 ASP.NET。 SELECT first_name, last_name FROM employee WHERE id = 'A001' |
答:
(一)
employee資料表:
employee_id |
first_name |
last_name |
e001 |
一 |
王 |
e002 |
二 |
張 |
e003 |
三 |
陳 |
salary_slip資料表:
salary_slip_id |
year |
month |
amount |
employee_id |
s001 |
2021 |
1 |
20000 |
e001 |
s002 |
2021 |
2 |
20000 |
e001 |
s003 |
2021 |
3 |
20000 |
e001 |
s004 |
2021 |
4 |
20000 |
e001 |
s005 |
2021 |
5 |
20000 |
e001 |
s006 |
2021 |
1 |
20000 |
e002 |
s007 |
2021 |
2 |
30000 |
e002 |
s008 |
2021 |
3 |
30000 |
e002 |
s009 |
2021 |
4 |
30000 |
e002 |
s010 |
2021 |
1 |
40000 |
e003 |
s011 |
2021 |
2 |
40000 |
e003 |
s012 |
2021 |
3 |
40000 |
e003 |
Select E.employee_id, E.first_name, E.last_name, Sum(amount) As 總額
From employee As E, salary_slip As S
Where E.employee_id = S.employee_id
Group By E.employee_id, E.first_name, E.last_name
執行結果:
employee_id |
first_name |
last_name |
總額 |
e001 |
一 |
王 |
100000 |
e002 |
二 |
張 |
110000 |
e003 |
三 |
陳 |
120000 |
(二)
1.程式碼:
test.html:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <form action="hello.php" method="post"> 員工ID:<input type="text" name="id"><br> <input type="submit" value=" 送出"> </form> |
執行結果:
hello.php:
<?php // 接收員工ID $id = $_REQUEST['id']; echo "<br> 輸入員工ID:".$id ; echo "</br>"; $host = 'localhost'; $dbuser = 'root'; $dbpassword = '12345678'; $dbname = 'test1'; $link = mysqli_connect($host, $dbuser, $dbpassword, $dbname); if($link){ mysqli_query($link, 'SET NAMES uff8'); echo "正確連接資料庫"; } else { echo "不正確連接資料庫</br>" . mysqli_connect_error( ); } // 設置一個空陣列來放資料 $datas = array( ); // sql 語法存在變數中 $sql = "SELECT * FROM `employee` WHERE `employee_id` = '".$id."'"; echo "<br>SQL語法為".$sql; echo "</br>"; // 用 mysqli_query 方法執行 (sql 語法) 將結果存在變數中 $result = mysqli_query($link, $sql); // 如果有資料 if ($result) { // mysqli_num_rows 方法可以回傳我們結果總共有幾筆資料 if (mysqli_num_rows($result) > 0) { // 取得大於0代表有資料 // while 迴圈會根據資料數量,決定跑的次數 // mysqli_fetch_assoc 方法可取得一筆值 while ($row = mysqli_fetch_assoc($result)) { // 每跑一次迴圈就抓一筆值,最後放進 data 陣列中 $datas[ ] = $row; } } // 釋放資料庫查到的記憶體 mysqli_free_result($result); } else { echo "{$sql} 語法執行失敗,錯誤訊息: " . mysqli_error($link); } // 處理完後印出資料 if(!empty($result)){ // 如果結果不為空,就利用 print_r 方法印出資料 print_r($datas); } else { // 為空表示沒資料 echo "查無資料"; } ?> |
執行結果:
輸入員工:ID' or '1 = 1
正確連接資料庫
SQL語法為SELECT * FROM `employee` WHERE `employee_id` = '' or '1 = 1'
Array ( [0] => Array ( [employee_id] => e001 [first_name] => 一 [last_name] => 王 ) [1] => Array ( [employee_id] => e002 [first_name] => 二 [last_name] => 陳 ) )
補充說明:
輸入員工ID:' OR ''='' # (O)
輸入員工ID:' OR 1=1 # (O)
輸入員工ID:' OR '1=1'# (O)
輸入員工ID:' OR '1=1 (O)
原先SQL語法
SELECT * FROM `employee` WHERE `employee_id` = 'e0033' or 1 = 1;
將「'e0033' or 1 = 1」替換成 or 1=1,如下:
SELECT * FROM `employee` WHERE `employee_id` = 'or 1 = 1'; (X)
將「'e0033' or 1 = 1」替換成 'or '1=1,如下:
SELECT * FROM `employee` WHERE `employee_id` = ''or '1 = 1'; (O)
2.被攻擊的疑慮:
在員工 ID 上輸入「ID' or '1 = 1」,可以查詢 employee 資料表的所有內容。
3.改善方式:
(1)透過不同DB的帳號給予不同的權限:
網路上的 Web 系統,會另外開一個 DB 帳號,權限只能讀與寫。
(2)可疑的關鍵字全部都過濾掉:
例如輸入 --、1 = 1、註解符號、單引號、雙引號、<script> 的 HTML 標籤。
(3)SQL指令透過Stored Procedure來執行:
一般的惡意參數會失效,例如:
Select * From Table Where id = ‘user’ And passwd = ‘ab123’
可以將 id 及 passwd 的值修改為 Stored Procedure 的輸入參數,做法如下:
Create Proc sp_SprocName2 @MyInput1 varchar(20), @MyInput2 varchar(20)
As
Select * From Table
Where id = @MyInput1 And passwd = @MyInput2
Go
在 sp_SprocName2 接收到輸入值後,便將它存放在 @MyInput1 及 @MyInput2 變數中,變數使用 @ 符號開頭,如果使用 @@ 符號開頭的則為全域變數,執行如下:
Exec sp_SprocName2 ‘user’, ‘ab123’
※參考資料:
1.http://yes.nctu.edu.tw/sql/StoredProcedure/StoredProcedure.htm
2.https://blog.xuite.net/linriva/blog/41344348-%5B%E9%A0%90%E5%AD%98%E7%A8%8B%E5%BA%8F%5D+%E6%9C%89%E8%BC%B8%E5%85%A5%E5%8F%83%E6%95%B8%E7%9A%84Stored+Procedure
(4)使用已修正過 SQL 資料隱碼問題的資料庫連接元件來連接資料庫,例如 ASP.NET 的 SqlDataSource 物件。
(5)在組合 SQL 字串時,先針對所傳入的參數作字元取代。
(6)透過程式語言中特殊的功能,讓使用者輸入的特殊字串被加上反斜線以去除其功能。
※參考資料:https://ithelp.ithome.com.tw/articles/10254637
留言列表