2011-04-13 77 views
4

我在寫一個由PHP和MySQL支持的動態網站(要在WAMP服務器上運行)。我目前的擔心是關於網站的安全性,但它沒有任何用戶輸入被保存,然後輸出給任何用戶(除了管理員),所以我並不擔心XSS。我主要關注的是針對SQL注入攻擊和保護管理員登錄門戶免受彩虹表/暴力破壞。動態網站安全問題(PHP + MySQL)

1)使用mysql_real_escape_string與sprintf()一起保護您免受SQL注入嗎?例如

$thing = mysql_real_escape_string($_REQUEST['thing']) 
$query = sprintf("SELECT * FROM table WHERE thing='%s'", $thing); 
$result = mysql_query($query); 

這是否足夠安全?當然,沒有系統是完全安全的,但我知道準備好的語句應該是防止SQL注入的最佳方法。但是,如果我的代碼「足夠安全」,那麼我認爲沒有理由進行更改。我在某處讀到,默認情況下,mysql_query只允許每次調用一個MySQL查詢以獲得安全原因,這是否正確?如果是這樣,我不明白我的代碼如何進行任何注入,但請讓我知道我的邏輯是否存在缺陷。

2)我正在爲該網站編寫管理門戶,以便它的所有者可以在網站上以簡單,用戶友好的方式操作MySQL數據庫(從未鏈接到的登錄HTML文件網站上的任何地方)。我對安全性的關注是登錄過程,它由兩個頁面組成。首先,收集用戶登錄信息:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml" lang="en"> 
<head> 
<title>Admin Portal</title> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
<meta name="robots" content="noindex, nofollow"> 
<link rel="stylesheet" type="text/css" href="http://www.anotherdomain.com/my.css"> 
<script type="text/javascript" src="http://www.anotherdomain.com/my.js"></script> 
</head> 
<form method="post" action="admin/login.php"> 
<table align="center"> 
<tr><th>Admin Login Form</th></tr> 
<tr><td>Name</td><td><input type="text" name="Name" size="30" onKeyPress="return aJSFunctionToStopEnterKeyFromWorking(event)"></td></tr> 
<tr><td>Password</td><td><input type="password" name="Password" size="30" onKeyPress="return aJSFunctionToStopEnterKeyFromWorking(event)"></td></tr> 
<tr><td></td><td><input type="reset" value="Clear Form"> <input type="submit" value="Login"></td></tr> 
</table> 
</form> 

其次,實際的登錄腳本:

<?php 
$inputusername = $_POST['Name']; 
$inputpassword = $_POST['Password']; 

$username = "a username that is not obvious"; 
$password = "a password that is at least 10 characters long"; 
$salt = hash('sha512', "a messed up string with weird characters that I wrote"); 

$hashword = hash('sha512', $password . $salt); 
$inputhashword = hash('sha512', $inputpassword . $salt); 

if($username == $inputusername && $hashword == $inputhashword) { 
    session_start(); 
    $_SESSION['valid'] = 1; 
    header('Location: portal.php'); 
    exit; 
} 
else {echo "Invalid username or password";} 
?> 

然後登錄過程後,每個頁面都會有以下以確保管理員在登錄:

<?php 
session_start(); 
if(!$_SESSION['valid']) {header('Location: ../admin.html');} 
?> 
Portal page goes here 

由於沒有建立新的用戶,將有永遠只能是爲門戶網站一個用戶。我只是想知道這種登錄方法對彩虹桌和暴力強制等攻擊有多安全?我認爲,既然我把hashword和salt都設置得非常大,即使用戶名不知爲何,這些攻擊也應該是相當安全的。

我也想知道這是否安全從會話劫持,因爲這是一個術語,我聽說過,但我不知道太多......我知道我從來沒有扔過會話ID周圍或類似的東西,所以它看起來很安全。

3)我應該知道/考慮的任何其他安全問題?

我非常感謝任何幫助!

回答

0

1)使用mysql_real_escape_string與sprintf()一起保護您免受SQL注入嗎?

只要1)你申請此功能串僅和2)使用mysql_set_charset()設置正確的編碼。
對於號碼,你可以簡單地使用%d

我讀的地方,MYSQL_QUERY只允許每個調用默認情況下爲安全起見一個MySQL查詢,是正確的?

你說得對。對於安全來說並不多,但更有可能通過設計。

如果是這樣,我不明白我的代碼如何進行任何打針,但請讓我知道我的邏輯是否存在缺陷。

你錯了。 SQL注入代表在您的查詢中注入SQL代碼,而不僅僅是單個「bobby drop tables」查詢。

我只是想知道這種登錄方法對彩虹桌和暴力強制等攻擊有多安全?

彩虹表在這裏沒有什麼可做,而暴力行爲仍然是一個危險。
雖然我覺得這不是什麼大不了的。不大於以純文本發送密碼。

我想,因爲我做了hashword和鹽分都非常大,應該是相當安全的

這裏比較有意思一點。實際上,這裏所有的哈希/鹽漬混亂都是無用的。它不僅僅比較簡單的密碼更安全。

,我也想知道,如果這是會話劫持安全,

總有一種可能性。如果你非常關心,請使用SSL連接,例如google郵件。

所以我並不是很擔心XSS。

這是非常錯誤的感覺。
就像echo "Requested article: ".$_GET['id']'一樣簡單的事情已經很脆弱。想

+0

哦,沒關係。現在我明白你的意思了。沒關係。基本上你是說他認爲無法進行注入是錯誤的,因爲MySQL只允許每次調用一個查詢。我得到你... – ircmaxell 2011-04-13 15:45:21

1

其他景點約:

1.你是容易猜解

字典攻擊會破解您的密碼。由於絕大多數用戶擁有不安全的密碼,這只是時間問題。使用驗證碼,或記錄無效的條目。或者在密碼不正確的時候添加一些延遲。

正如Shrapnel所說,彩虹表並不是你的問題,因爲當有人有一堆散列並且想破解它們時,就會使用它。鹽被用來抵禦彩虹桌的一些保護,這不是你的情況。

2.以明文

如果有人嗅探登錄(WIFI等)發送的密碼,你註定。有一些JavaScript庫可以使用公鑰加密任何東西。如果您不想使用SSL,請加密登錄名/密碼,發送到服務器,使用私鑰解密,並且您更安全。

3.考慮使用MySQL的預處理語句

使用預處理語句可以有助於防止SQL注入,因爲它可以安全地甚至惡意輸入運行:

$dbc = new mysqli("mysql_server_ip", "mysqluser", "mysqlpass", "dbname"); 
$statement = $db_connection->prepare("SELECT * FROM table WHERE thing='?'"); 
$statement->bind_param("i", $thing); 
$statement->execute(); 

4.不要接力在客戶端驗證

在您的登錄表單上,您將繼續使用JavaScript功能來防止Enter-Key功能。如果我禁用Javascript會怎麼樣?您可以使用隱藏字段(例如,< input type ='hidden'name ='FormIsValid'value ='0'>),使用您的函數來防止Enter鍵,並使用onSubmit()函數將FormIsValid更改爲1發送表單。在您的服務器中,驗證FormIsValid。

5.你很容易受到會話劫持

你會被保存在cookie中,缺省情況下名爲PHPSESSID。如果攻擊者可以獲取該cookie,它可以將其發送到您的服務器並竊取您的會話。爲了防止這種情況,您可以將用戶IP地址和用戶代理保存在會話中,並比較每次請求中從會話接收到的值。如果值不匹配,則用戶IP可能已更改或會話可能已被劫持。

6.您可以很容易受到會話固定

如上所述,如果有人說服你的管理員訪問某些網站,這個網站將請求發送到您的網站與PHPSESSID上的要求,你的網站將創建會話,處理登錄名/密碼,並聲明憑據錯誤。直到現在還不錯。

稍後,您的管理員登錄到您的門戶,會話已存在,登錄名和密碼匹配,並且會話已更新。可變有效現在是1

一旦變量被更新,攻擊者可以完全訪問您的門戶網站,因爲他知道PHPSESSID,您的網站不會阻止會話劫持,或會話固定。

爲避免會話固定和劫持,請參閱#5。

+0

有幾件事。如果以明文形式發送會話ID(這是真正的身份驗證令牌),誰會關心密碼是否爲純文本。您的解決方案仍然是OWASP A9違規。誰在乎cookie的名字是什麼,這並不影響會話固定。要停止會話修復,只需在php.ini中設置'session.use_only_cookies = 1'。 – rook 2011-04-13 17:05:10

+0

此外,您完全錯過了身份驗證繞過漏洞,這比您列出的任何內容嚴重得多。 – rook 2011-04-13 17:07:48

+0

@我只關注身份驗證腳本,而不是管理會話下的所有其他腳本。 – ThoriumBR 2011-04-13 17:44:00

0

看起來像別人都認爲這是分開的。但我有一個更多的補充:

繞過認證:

<?php 
session_start(); 
if(!$_SESSION['valid']) {header('Location: ../admin.html');} 
?> 

當你做一個header("location: ...")腳本仍然執行,你還是要exitdie()。所以實際上,通過這一點代碼,我知道您的所有頁面都可以由未經身份驗證的用戶訪問。

0

更多的改進:

檢查您的參數,你引述他們弄成之前的類型。 (除了文本搜索,這需要更多一點)。缺失的值可能會引發SQL錯誤,攻擊者可以從中學習;)

將反csrf標記放入登錄頁面,並在登錄失敗後進行睡眠嘗試防止暴力攻擊。

登錄https。通過http,你通過網絡推明確的密碼。在中等攻擊的情況下是完美的人(但這很難做:)。

檢查正確的輸入編碼。有一些使用日語多字節字符的UTF-7攻擊,它們的單引號作爲第二個字節。 (這可能會打破mysql_real_escape_string)Veeery棘手的東西。

使用準備好的發言

0

只需添加到這一點,你可以考慮使用一個很好的框架,像笨..即使它不完全是安全的。它有助於採取的一些問題護理,你可能不考慮..:d