PHP保護(hù)數(shù)據(jù)庫的具體代碼示例
因?yàn)閿?shù)據(jù)庫管理不善導(dǎo)致數(shù)據(jù)丟失,為自己帶來損失的例子不再少數(shù)。我們這次就要講到PHP保護(hù)數(shù)據(jù)庫的相關(guān)操作代碼,為你的數(shù)據(jù)庫保駕護(hù)航。美國某個州的獄政局在查詢字符串中使用了 SQL 列名,因此泄露了保密數(shù)據(jù)。這次泄露允許惡意用戶選擇需要顯示的列、提交頁面并獲得數(shù)據(jù)。這次泄露顯示了用戶如何能夠以應(yīng)用程序開發(fā)人員無法預(yù)料的方法執(zhí)行輸入,并表明了防御 SQL 注入攻擊的必要性。
#t#下面代碼顯示了運(yùn)行 SQL 語句的示例腳本。在本例中,SQL 語句是允許相同攻擊的動態(tài)語句。此表單的所有者可能認(rèn)為表單是安全的,因?yàn)樗麄円呀?jīng)把列名限定為選擇列表。但是,代碼疏忽了關(guān)于表單欺騙的最后一個習(xí)慣 — 代碼將選項(xiàng)限定為下拉框并不意味著其他人不能夠發(fā)布含有所需內(nèi)容的表單(包括星號 [*])。
- <html>
- <head>
- <title>SQL Injection Example</title>
- </head>
- <body>
- <form id="myFrom" action="<?php echo $_SERVER['PHP_SELF']; ?>"
- method="post">
- <div><input type="text" name="account_number"
- value="<?php echo(isset($_POST['account_number']) ?
- $_POST['account_number'] : ''); ?>" />
- <select name="col">
- <option value="account_number">Account Number</option>
- <option value="name">Name</option>
- <option value="address">Address</option>
- </select>
- <input type="submit" value="Save" name="submit" /></div>
- </form>
- <?php
- if ($_POST['submit'] == 'Save') {
- /* do the form processing */
- $link = mysql_connect('hostname', 'user', 'password') or
- die ('Could not connect' . mysql_error());
- mysql_select_db('test', $link);
- $col = $_POST['col'];
- $select = "SELECT " . $col . " FROM account_data WHERE account_number = "
- . $_POST['account_number'] . ";" ;
- echo '<p>' . $select . '</p>';
- $result = mysql_query($select) or die('<p>' . mysql_error() . '</p>');
- echo '<table>';
- while ($row = mysql_fetch_assoc($result)) {
- echo '<tr>';
- echo '<td>' . $row[$col] . '</td>';
- echo '</tr>';
- }
- echo '</table>';
- mysql_close($link);
- }
- ?>
- </body>
- </html>
因此,要形成PHP保護(hù)數(shù)據(jù)庫的習(xí)慣,請盡可能避免使用動態(tài) SQL 代碼。如果無法避免動態(tài) SQL 代碼,請不要對列直接使用輸入。下面則顯示了除使用靜態(tài)列外,還可以向帳戶編號字段添加簡單驗(yàn)證例程以確保輸入值不是非數(shù)字值。
- <html>
- <head>
- <title>SQL Injection Example</title>
- </head>
- <body>
- <form id="myFrom" action="<?php echo $_SERVER['PHP_SELF']; ?>"
- method="post">
- <div><input type="text" name="account_number"
- value="<?php echo(isset($_POST['account_number']) ?
- $_POST['account_number'] : ''); ?>" /> <input type="submit"
- value="Save" name="submit" /></div>
- </form>
- <?php
- function isValidAccountNumber($number)
- {
- return is_numeric($number);
- }
- if ($_POST['submit'] == 'Save') {
- /* Remember habit #1--validate your data! */
- if (isset($_POST['account_number']) &
- isValidAccountNumber($_POST['account_number'])) {
- /* do the form processing */
- $link = mysql_connect('hostname', 'user', 'password') or
- die ('Could not connect' . mysql_error());
- mysql_select_db('test', $link);
- $select = sprintf("SELECT account_number, name, address " .
- " FROM account_data WHERE account_number = %s;",
- mysql_real_escape_string($_POST['account_number']));
- echo '<p>' . $select . '</p>';
- $result = mysql_query($select) or die('<p>' . mysql_error() . '</p>');
- echo '<table>';
- while ($row = mysql_fetch_assoc($result)) {
- echo '<tr>';
- echo '<td>' . $row['account_number'] . '</td>';
- echo '<td>' . $row['name'] . '</td>';
- echo '<td>' . $row['address'] . '</td>';
- echo '</tr>';
- }
- echo '</table>';
- mysql_close($link);
- } else {
- echo "<span style=\"font-color:red\">" .
- "Please supply a valid account number!</span>";
- }
- }
- ?>
- </body>
- </html>
在這次PHP保護(hù)數(shù)據(jù)庫的例子中還展示了 mysql_real_escape_string() 函數(shù)的用法。此函數(shù)將正確地過濾您的輸入,因此它不包括無效字符。如果您一直依賴于 magic_quotes_gpc,那么需要注意它已被棄用并且將在 PHP V6 中刪除。從現(xiàn)在開始應(yīng)避免使用它并在此情況下編寫安全的 PHP 應(yīng)用程序。此外,如果使用的是 ISP,則有可能您的 ISP 沒有啟用 magic_quotes_gpc。
最后,在改進(jìn)的PHP保護(hù)數(shù)據(jù)庫示例中,您可以看到該 SQL 語句和輸出沒有包括動態(tài)列選項(xiàng)。使用這種方法,如果把列添加到稍后含有不同信息的表中,則可以輸出這些列。如果要使用框架以與數(shù)據(jù)庫結(jié)合使用,則您的框架可能已經(jīng)為您執(zhí)行了 SQL 驗(yàn)證。確保查閱文檔以保證框架的安全性;如果仍然不確定,請進(jìn)行驗(yàn)證以確保穩(wěn)妥。即使使用框架進(jìn)行數(shù)據(jù)庫交互,仍然需要執(zhí)行其他驗(yàn)證。