2009-11-23 231 views
21

好的,我和一個朋友正在做一個關於PHP安全的小型演示文稿(雖然我沒有真正進入PHP),並且他讓我找到一些易受攻擊的PHP代碼的例子(一個容易出現SQL注入和所有其他類型的攻擊)。我想知道是否有任何網站既有好的也有壞的代碼,顯示你應該怎樣編碼?易受攻擊的PHP代碼示例?

基本上我會把它們放到我們的網站上,他會嘗試破解它,然後我們將顯示「正確」的網站,他會嘗試再次破解它。

+0

+1因爲它聽起來很有趣:) – Johan 2009-11-23 15:43:51

回答

18

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); 
+1

是的,基本上你永遠不會相信用戶輸入,把它當作惡意輸入,並用'addslashes()','strip_tags()'或'htmlspecialchars()'將其轉義。 – Rob 2009-11-23 13:38:15

+16

'strip_tags'不足以阻止HTML注入(認爲屬性值注入)。用FILTER_SANITIZE_STRING調用請求數組是一個絕對不應該使用的可怕黑客攻擊。相反,通過調用HTML內容中每個字符串的'htmlspecialchars'來避免HTML注入。 – bobince 2009-11-23 13:40:05

+4

你可以用正則表達式解析它... – nickf 2009-11-23 13:42:00

3

一個SQL注入脆弱的登錄腳本的另一個例子。不幸的是,這在新程序員中很常見。

$username = $_POST["username"]; 
$password = $_POST["password"]; 
$query = "SELECT username, password 
      FROM users 
      WHERE (username = '{$username}') 
      AND (password = '{$password}')"; 
+7

更不用說以明文存儲密碼了。 – 2009-11-23 14:25:24

+0

@ Vilx-除非$ _POST [「password」]被散列在客戶端;)這是不可靠的,因爲客戶端生成的散列不能在不向客戶端透露salt的情況下被醃製。 – 2015-06-28 07:31:21

+0

@ dwarf015 - 嗯,我認爲如果哈希函數本身足夠慢,揭示鹽不會是一個大問題。但我不是專家,所以不要聽我的話。 :) – 2015-06-28 07:50:36

17

一個真正常見的初學者的錯誤是忘記在重定向後終止腳本執行。

<?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頭勿使任何腳本的輸出被錯過。

+0

也許對我來說,早上還爲時過早,但這裏的漏洞是什麼? – Jakub 2009-11-23 13:39:47

+3

頭可以被忽略,並且PHP腳本仍在執行。即使用戶未登錄,私有函數仍會執行。 – Ikke 2009-11-23 13:41:57

+1

header()重定向可能不會立即生效,或者可能被故意忽略,從而顯示下面的私有數據。 – 2009-11-23 13:42:10

4

我見過這樣的代碼寫在了過去:

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添加到網址,然後你就進入了。

+2

這個模擬的功能是'register_globals' – 2009-11-23 13:49:22

+0

啊謝謝!這是我在腦海中阻止的事情之一。恐怖......恐怖...... – nickf 2009-11-23 13:50:21

10

鮑比表

alt text

Bobby Tables是專門描述一個腳本可以通過SQL injection脆弱的各種方式的頁面。這不是PHP獨有的,但是,SQL注入是許多網頁漏洞的原因。

這可能是你想要包含在你的演示文稿中的東西。

0

錯誤的方式來做模板。

<?php 

    include("header.php"); 
    include($_GET["source"]); //http://www.mysite.com/page.php?source=index.php 
    include("footer.php"); 

?> 
+4

你還應該展示做模板的最佳方式。 – Ikke 2009-11-23 13:43:35

+0

問題出在易受攻擊的例子,而不是恰當的例子。 – Sampson 2009-11-23 14:51:03

0

XSS漏洞很容易顯示。剛創建提出的GET變量「Q」值某個頁面上的頁面,然後點擊下面的網址:

http://mysite.com/vulnerable_page.php?q%3D%3Cscript%20type%3D%22javascript%22%3Ealert(document.cookie)%3B%3C%2Fscript%3E 

這將導致一個警告框將顯示在用戶的cookie。

0

允許上傳並且不檢查擴展名。觀察:

網站A允許圖像上載並顯示它們。

餅乾人上傳一個文件,並誘使你相信它的圖像文件(通過HTTP mimetypes)。此文件具有PHP擴展名幷包含惡意代碼。然後他試圖看到他的圖像文件,因爲每個PHP extesioned文件都是由PHP執行的,代碼就會運行。他可以做任何apache用戶可以做的事情。

12

哦,男孩,你不會缺乏實例。只是谷歌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代碼在野外的一般質量是如此災難性的,當這種可怕的垃圾是編程人員正在學習的東西?

+0

「填補阿爾伯特音樂廳的孔」?好的。 +1 – Franz 2009-11-25 20:57:56

+0

你說得對。看到示例代碼非常有趣,它向您展示瞭如何測試代碼以及​​引入/丟失/遺漏其他漏洞示例...... – Franz 2009-11-25 20:59:06

+2

我最喜歡的是Apress的書「Pro PHP Security」。作者簡要介紹了常見的漏洞,併爲每個漏洞提供瞭解決方案(通常是一種非常不合適的解決方案,例如通過SQL轉義映射POST)。然後在其他解決其他漏洞的例子中,他又錯了,給代碼帶來了上一章剛纔警告我們的漏洞。 XSS章節的例子中甚至存在XSS漏洞,以避免XSS漏洞略有不同。以及使用'eval'和'system'的相當恐怖的部分。 「臨」安全的確如此。 – bobince 2009-11-25 21:32:34

2

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

爲了幫助防止這種攻擊,您可以:

  • 檢查您的用戶REFERER(遠非完美)
  • 實現一些當你得到你的數據時,你必須使用令牌並檢查他們的存在。

另一個是會話劫持。其中一種方法是搭載。 如果您的服務器接受非cookie會話,則可以使用像http://siteA/?PHPSESSID=blabla這樣的URL,這意味着您的會話ID是blabla。

攻擊者可以開始會話並記下他的會話ID,然後將鏈接http://siteA/?PHPSESSID=attackerSessionId給予您網站的其他用戶。當這些用戶關注此鏈接時,他們將與攻擊者共享相同的會話:未記錄的會話。所以他們登錄。 如果網站沒有做任何事情,攻擊者和您的用戶仍然共享具有相同權限的同一個會話。糟糕的是,如果用戶是管理員。

要緩解這種情況,當用戶憑據更改(登錄和註銷,進入管理部分等)時,必須使用session_regenerate_id

3

Today's DailyWTF

if(strstr($username, '**')) { 

    $admin = 1; 
    $username = str_replace('**', '', $username); 
    $_SESSION['admin'] = 1; 

} else { 

    $admin = 0; 

} 
+0

只需在thedailywtf上閱讀即可。該代碼傷害... – knittl 2009-11-23 14:42:59

+0

...和那個誰稱自己是程序員?! – Strae 2009-12-01 11:00:35

3

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 ...

明顯地,第二響應完全由攻擊者控制的,並且可以與任何報頭和主體內容,而不是

+0

嗯,我認爲這是PHP版本相關。 PHP 5似乎將所有特殊字符編碼爲百分比編碼。 – Tower 2009-11-24 13:09:19

+2

HTTP響應分裂已經解決了相當長的一段時間。 http://php.net/releases/5_1_2.php – 2009-11-24 17:53:10

2

Email headerinjection attacks是一個更大的痛苦中來構造那麼你可能會懷疑這個脖子(除非你必須處理它們)。

這是非常糟糕:

$to = '[email protected]'; 
$subject = $_POST["subject"]; 
$message = $_POST["message"]; 
$headers = "From: ".$_POST["from"]; 
mail($to,$subject,$message,$headers); 

(代碼從第二參考上面複製)

0

基本(常常安全敏感)操作無法正常運行,而不需要程序員使用第二「真正」版本獲得非破壞功能。

的最嚴重的人會在那裏實際操作會受到影響:在「==」操作不工作,正如人們所期望的那樣,而是需要在「===」操作符來獲得真正的平等的比較。

一個大3的PHP論壇程序包是受一個漏洞,它的代碼「保持登錄」。該cookie將包含用戶的ID和他們的密碼哈希。 PHP腳本會讀取和清理ID,用它來查詢用戶在數據庫中的正確哈希值,然後將其與cookie中的哈希值進行比較,以查看它們是否應該自動登錄。

但是,比較結果是與==,所以通過修改cookie,攻擊者使用布爾:真的散列「值」,使得散列比較語句無用。因此攻擊者可以用任何用戶ID來替換而不用密碼登錄。

0

允許人們上傳的文件,該API是否應該由用戶或不能使用。例如,如果程序將某些文件上傳到服務器,並且該程序將永遠不會上傳壞文件,那沒問題。

但黑客可以跟蹤發送的是什麼,在哪裏。他可以發現它允許文件上傳。

從那裏,他可以輕鬆上傳的PHP文件。一旦完成,遊戲就結束了。他現在可以訪問您的所有數據,並可以銷燬或更改他想要的任何內容。

另一個常見的錯誤是允許氾濫。你應該對你的數據進行一些合理的限制。不要讓用戶輸入無意義的數據。爲什麼用戶名是2MB?這樣的事情會讓有人氾濫數據庫或文件系統變得如此容易,並且由於空間不足而導致系統崩潰。

相關問題