好的,我和一個朋友正在做一個關於PHP安全的小型演示文稿(雖然我沒有真正進入PHP),並且他讓我找到一些易受攻擊的PHP代碼的例子(一個容易出現SQL注入和所有其他類型的攻擊)。我想知道是否有任何網站既有好的也有壞的代碼,顯示你應該怎樣編碼?易受攻擊的PHP代碼示例?
基本上我會把它們放到我們的網站上,他會嘗試破解它,然後我們將顯示「正確」的網站,他會嘗試再次破解它。
好的,我和一個朋友正在做一個關於PHP安全的小型演示文稿(雖然我沒有真正進入PHP),並且他讓我找到一些易受攻擊的PHP代碼的例子(一個容易出現SQL注入和所有其他類型的攻擊)。我想知道是否有任何網站既有好的也有壞的代碼,顯示你應該怎樣編碼?易受攻擊的PHP代碼示例?
基本上我會把它們放到我們的網站上,他會嘗試破解它,然後我們將顯示「正確」的網站,他會嘗試再次破解它。
SQL injection很簡單:
$var = mysql_real_escape_string($_POST['var']);
其他常見的一種是XSS (cross site scripting):
$var = $_POST['var'];
echo "<div>$var</div>\n";
允許你注入正在運行JavaScript
$var = $_POST['var'];
mysql_query("SELECT * FROM sometable WHERE id = $var");
這是很容易解決的從您的網站。沒有與此處理,例如幾個方面:
$var = strip_tags($_POST['var']);
和
$var = filter_var($_POST['var'], FILTER_SANITIZE_STRING);
是的,基本上你永遠不會相信用戶輸入,把它當作惡意輸入,並用'addslashes()','strip_tags()'或'htmlspecialchars()'將其轉義。 – Rob 2009-11-23 13:38:15
'strip_tags'不足以阻止HTML注入(認爲屬性值注入)。用FILTER_SANITIZE_STRING調用請求數組是一個絕對不應該使用的可怕黑客攻擊。相反,通過調用HTML內容中每個字符串的'htmlspecialchars'來避免HTML注入。 – bobince 2009-11-23 13:40:05
你可以用正則表達式解析它... – nickf 2009-11-23 13:42:00
一個SQL注入脆弱的登錄腳本的另一個例子。不幸的是,這在新程序員中很常見。
$username = $_POST["username"];
$password = $_POST["password"];
$query = "SELECT username, password
FROM users
WHERE (username = '{$username}')
AND (password = '{$password}')";
更不用說以明文存儲密碼了。 – 2009-11-23 14:25:24
@ Vilx-除非$ _POST [「password」]被散列在客戶端;)這是不可靠的,因爲客戶端生成的散列不能在不向客戶端透露salt的情況下被醃製。 – 2015-06-28 07:31:21
@ dwarf015 - 嗯,我認爲如果哈希函數本身足夠慢,揭示鹽不會是一個大問題。但我不是專家,所以不要聽我的話。 :) – 2015-06-28 07:50:36
一個真正常見的初學者的錯誤是忘記在重定向後終止腳本執行。
<?php
if ($_SESSION['user_logged_in'] !== true) {
header('Location: /login.php');
}
omg_important_private_functionality_here();
解決辦法:
if ($_SESSION['user_logged_in'] !== true) {
header('Location: /login.php');
exit();
}
這可以在一個正常的瀏覽器進行測試時,因爲瀏覽器通常遵循Location
頭勿使任何腳本的輸出被錯過。
查看Open Web Application Security Project。他們有很多不同種類的攻擊的解釋和例子。 http://www.owasp.org/index.php/Category:Attack
我見過這樣的代碼寫在了過去:
foreach ($_REQUEST as $var => $val) {
$$var = $val;
}
這是模擬中傷register_globals
選項的方式。這意味着你可以訪問你這樣的變量:
$myPostedVar
,而不是非常複雜:
$_POST['myPostedVar']
安全風險的情況下,會彈出這樣的:
$hasAdminAccess = get_user_access();
foreach ($_REQUEST as $var => $val) {
$$var = $val;
}
if ($hasAdminAccess) { ... }
由於所有你需要做的是將?hasAdminAccess=1
添加到網址,然後你就進入了。
這個模擬的功能是'register_globals' – 2009-11-23 13:49:22
啊謝謝!這是我在腦海中阻止的事情之一。恐怖......恐怖...... – nickf 2009-11-23 13:50:21
鮑比表
Bobby Tables是專門描述一個腳本可以通過SQL injection脆弱的各種方式的頁面。這不是PHP獨有的,但是,SQL注入是許多網頁漏洞的原因。
這可能是你想要包含在你的演示文稿中的東西。
XSS漏洞很容易顯示。剛創建提出的GET變量「Q」值某個頁面上的頁面,然後點擊下面的網址:
http://mysite.com/vulnerable_page.php?q%3D%3Cscript%20type%3D%22javascript%22%3Ealert(document.cookie)%3B%3C%2Fscript%3E
這將導致一個警告框將顯示在用戶的cookie。
允許上傳並且不檢查擴展名。觀察:
網站A允許圖像上載並顯示它們。
餅乾人上傳一個文件,並誘使你相信它的圖像文件(通過HTTP mimetypes)。此文件具有PHP擴展名幷包含惡意代碼。然後他試圖看到他的圖像文件,因爲每個PHP extesioned文件都是由PHP執行的,代碼就會運行。他可以做任何apache用戶可以做的事情。
哦,男孩,你不會缺乏實例。只是谷歌PHP tutorial和他們每個人都有足夠的洞來填補阿爾伯特音樂廳。
結果1,w3schools。他們的第一個例子包括用戶輸入?
Welcome <?php echo $_POST["fname"]; ?>!<br />
Bzzt。 HTML注入,在每個示例代碼中重複使用。他們的第一個數據庫查詢是什麼
$sql="INSERT INTO Persons (FirstName, LastName, Age) VALUES ('$_POST[firstname]','$_POST[lastname]','$_POST[age]')";
Bzzt。 SQL注入,你輸了。下一個。
結果2,官方PHP教程。輸出變量的第一個例子是什麼?
echo $_SERVER['HTTP_USER_AGENT'];
Bzzt。 HTML注入。這不是一個容易被利用的問題,但仍然是在php.net的學習資料中重複出現的錯誤練習。
結果3,tizag.com。呼應用戶輸入的第一個例子是什麼?
echo "You ordered ". $quantity . " " . $item . ".<br />";
Bzzt。
結果4,freewebmasterhelp.com。太基本包括很多,但仍然管理:
print "Hello $name"; // Welcome to the user
Bzzt。
結果5,learnphp-tutorial.com。
<title><?= $greeting ?> World!</title>
的Bz ...
我可以繼續下去。
難怪PHP代碼在野外的一般質量是如此災難性的,當這種可怕的垃圾是編程人員正在學習的東西?
「填補阿爾伯特音樂廳的孔」?好的。 +1 – Franz 2009-11-25 20:57:56
你說得對。看到示例代碼非常有趣,它向您展示瞭如何測試代碼以及引入/丟失/遺漏其他漏洞示例...... – Franz 2009-11-25 20:59:06
我最喜歡的是Apress的書「Pro PHP Security」。作者簡要介紹了常見的漏洞,併爲每個漏洞提供瞭解決方案(通常是一種非常不合適的解決方案,例如通過SQL轉義映射POST)。然後在其他解決其他漏洞的例子中,他又錯了,給代碼帶來了上一章剛纔警告我們的漏洞。 XSS章節的例子中甚至存在XSS漏洞,以避免XSS漏洞略有不同。以及使用'eval'和'system'的相當恐怖的部分。 「臨」安全的確如此。 – bobince 2009-11-25 21:32:34
CSRF爲勝利。
<?php
$newEmail = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);
$pdoStatement = $pdoDb->prepare('UPDATE user SET email=:email WHERE ID=:id');
$pdoStatement->execute(array(':email'=>$newEmail, ':id'=>$_SESSION['userId']));
您感覺這類代碼安全。一切都很好,您的用戶可以在不注入SQL的情況下更改他們的電子郵件,因爲您的代碼。 但是,想象一下,在您的網站http://siteA/上有此功能,您的一位用戶已連接。 在相同的瀏覽器,他那張http://siteB/,其中一些AJAX這段代碼相當於:
<form method="post" action="http://site/updateMyAccount.php">
<p>
<input name="email" value="[email protected]"/>
<input type="submit"/>
</p>
</form>
您的用戶剛拿到他的電子郵件改變了沒有他知道它。如果你不認爲這種攻擊是很危險的,ask google about it
爲了幫助防止這種攻擊,您可以:
另一個是會話劫持。其中一種方法是搭載。 如果您的服務器接受非cookie會話,則可以使用像http://siteA/?PHPSESSID=blabla這樣的URL,這意味着您的會話ID是blabla。
攻擊者可以開始會話並記下他的會話ID,然後將鏈接http://siteA/?PHPSESSID=attackerSessionId給予您網站的其他用戶。當這些用戶關注此鏈接時,他們將與攻擊者共享相同的會話:未記錄的會話。所以他們登錄。 如果網站沒有做任何事情,攻擊者和您的用戶仍然共享具有相同權限的同一個會話。糟糕的是,如果用戶是管理員。
要緩解這種情況,當用戶憑據更改(登錄和註銷,進入管理部分等)時,必須使用session_regenerate_id。
if(strstr($username, '**')) {
$admin = 1;
$username = str_replace('**', '', $username);
$_SESSION['admin'] = 1;
} else {
$admin = 0;
}
HTTP響應拆分攻擊
如果Web應用程序存儲在cookie的HTTP請求輸入假設
<?php setcookie("author",$_GET["authorName"]); ?>
這是很容易如果輸入未正確驗證「\ r \ n」字符,則會導致HTTP響應分裂攻擊。
如果攻擊者提交惡意字符串,例如「AuthorName \ r \ nHTTP/1.1 200 OK \ r \ n ..」」,那麼HTTP響應就會被分割成以下形式的兩個響應:
HTTP/1.1 200 OK
...
的Set-Cookie:作者= AUTHORNAME
HTTP/1.1 200 OK ...
明顯地,第二響應完全由攻擊者控制的,並且可以與任何報頭和主體內容,而不是
嗯,我認爲這是PHP版本相關。 PHP 5似乎將所有特殊字符編碼爲百分比編碼。 – Tower 2009-11-24 13:09:19
HTTP響應分裂已經解決了相當長的一段時間。 http://php.net/releases/5_1_2.php – 2009-11-24 17:53:10
Email headerinjection attacks是一個更大的痛苦中來構造那麼你可能會懷疑這個脖子(除非你必須處理它們)。
這是非常糟糕:
$to = '[email protected]';
$subject = $_POST["subject"];
$message = $_POST["message"];
$headers = "From: ".$_POST["from"];
mail($to,$subject,$message,$headers);
(代碼從第二參考上面複製)
基本(常常安全敏感)操作無法正常運行,而不需要程序員使用第二「真正」版本獲得非破壞功能。
的最嚴重的人會在那裏實際操作會受到影響:在「==」操作不工作,正如人們所期望的那樣,而是需要在「===」操作符來獲得真正的平等的比較。
一個大3的PHP論壇程序包是受一個漏洞,它的代碼「保持登錄」。該cookie將包含用戶的ID和他們的密碼哈希。 PHP腳本會讀取和清理ID,用它來查詢用戶在數據庫中的正確哈希值,然後將其與cookie中的哈希值進行比較,以查看它們是否應該自動登錄。
但是,比較結果是與==,所以通過修改cookie,攻擊者使用布爾:真的散列「值」,使得散列比較語句無用。因此攻擊者可以用任何用戶ID來替換而不用密碼登錄。
允許人們上傳的文件,該API是否應該由用戶或不能使用。例如,如果程序將某些文件上傳到服務器,並且該程序將永遠不會上傳壞文件,那沒問題。
但黑客可以跟蹤發送的是什麼,在哪裏。他可以發現它允許文件上傳。
從那裏,他可以輕鬆上傳的PHP文件。一旦完成,遊戲就結束了。他現在可以訪問您的所有數據,並可以銷燬或更改他想要的任何內容。
另一個常見的錯誤是允許氾濫。你應該對你的數據進行一些合理的限制。不要讓用戶輸入無意義的數據。爲什麼用戶名是2MB?這樣的事情會讓有人氾濫數據庫或文件系統變得如此容易,並且由於空間不足而導致系統崩潰。
+1因爲它聽起來很有趣:) – Johan 2009-11-23 15:43:51