㈠ 怎麼樣在PHP中阻止sql注入式攻擊
一、
注入式攻擊的類型
可能存在許多不同類型的攻擊動機,但是乍看上去,似乎存在更多的類型。這是非常真實的-如果惡意用戶發現了一個能夠執行多個查詢的辦法的話。
如果你的腳本正在執行一個SELECT指令,那麼,攻擊者可以強迫顯示一個表格中的每一行記錄-通過把一個例如"1=1"這樣的條件注入到WHERE子句中,如下所示(其中,注入部分以粗體顯示):
SELECT
*
FROM
wines
WHERE
variety
=
'lagrein'
OR
1=1;'
正如我們在前面所討論的,這本身可能是很有用的信息,因為它揭示了該表格的一般結構(這是一條普通的記錄所不能實現的),以及潛在地顯示包含機密信息的記錄。
一條更新指令潛在地具有更直接的威脅。通過把其它屬性放到SET子句中,一名攻擊者可以修改當前被更新的記錄中的任何欄位,例如下面的例子(其中,注入部分以粗體顯示):
UPDATE
wines
SET
type='red','vintage'='9999'
WHERE
variety
=
'lagrein'
通過把一個例如1=1這樣的恆真條件添加到一條更新指令的WHERE子句中,這種修改范圍可以擴展到每一條記錄,例如下面的例子(其中,注入部分以粗體顯示):
UPDATE
wines
SET
type='red','vintage'='9999
WHERE
variety
=
'lagrein'
OR
1=1;'
最危險的指令可能是DELETE-這是不難想像的。其注入技術與我們已經看到的相同-通過修改WHERE子句來擴展受影響的記錄的范圍,例如下面的例子(其中,注入部分以粗體顯示):
DELETE
FROM
wines
WHERE
variety
=
'lagrein'
OR
1=1;'
二、
多個查詢注入
多個查詢注入將會加劇一個攻擊者可能引起的潛在的損壞-通過允許多條破壞性指令包括在一個查詢中。在使用MySQL資料庫時,攻擊者通過把一個出乎意料之外的終止符插入到查詢中即可很容易實現這一點-此時一個注入的引號(單引號或雙引號)標記期望變數的結尾;然後使用一個分號終止該指令。現在,一個另外的攻擊指令可能被添加到現在終止的原始指令的結尾。最終的破壞性查詢可能看起來如下所示:
SELECT
*
FROM
wines
WHERE
variety
=
'lagrein';GRANT
ALL
ON
*.*
TO
'BadGuy@%'
IDENTIFIED
BY
'gotcha';'
這個注入將創建一個新的用戶BadGuy並賦予其網路特權(在所有的表格上具有所有的特權);其中,還有一個"不祥"的口令被加入到這個簡單的
SELECT語句中。如果你遵循我們在以前文章中的建議-嚴格限制該過程用戶的特權,那麼,這應該無法工作,因為Web伺服器守護程序不再擁有你撤回的
GRANT特權。但是從理論上講,這樣的一個攻擊可能給予BadGuy自由權力來實現他對你的資料庫的任何操作。
至於這樣的一個多查詢是否會被MySQL伺服器處理,結論並不唯一。這其中的一些原因可能是由於不同版本的MySQL所致,但是大多數情況卻是由於多查詢存在的方式所致。
MySQL的監視程序完全允許這樣的一個查詢。常用的MySQL
GUI-phpMyAdmin,在最終查詢之前會復制出以前所有的內容,並且僅僅這樣做。
但是,大多數的在一個注入上下文中的多查詢都是由PHP的mysql擴展負責管理的。幸好,默認情況下,它是不允許在一個查詢中執行多個指令的;試圖執行兩個指令(例如上面所示的注入)將會簡單地導致失敗-不設置任何錯誤,並且沒有生成任何輸出信息。在這種情況下,盡管PHP也只是"規規矩矩"地實現其預設行為,但是確實能夠保護你免於大多數簡單的注入式攻擊。
PHP5中的新的mysqli擴展(參考http://php.net/mysqli),就象mysql一樣,內在地也不支持多個查詢,不過卻提供了一個mysqli_multi_query()函數以支持你實現多查詢-如果你確實想這樣做的話。
然而,對於SQLite-與PHP5綁定到一起的可嵌入的SQL資料庫引擎(參考http://sqlite.org/和http:
//php.net/sqlite)情況更為可怕,由於其易於使用而吸引了大量用戶的關注。在有些情況下,SQLite預設地允許這樣的多指令查詢,因為該資料庫可以優化批查詢,特別是非常有效的批INSERT語句處理。然而,如果查詢的結果為你的腳本所使用的話(例如在使用一個SELECT語句檢索記錄的情況下),sqlite_query()函數卻不會允許執行多個查詢。
三、
INVISION
Power
BOARD
SQL注入脆弱性
Invision
Power
Board是一個著名的論壇系統。2005年五月6號,在登錄代碼中發現了一處SQL注入脆弱性。其發現者為GulfTech
Security
Research的James
Bercegay。
這個登錄查詢如下所示:
$DB->query("SELECT
*
FROM
ibf_members
WHERE
id=$mid
AND
password='$pid'");
其中,成員ID變數$mid和口令ID變數$pid被使用下面兩行代碼從my_cookie()函數中檢索出:
$mid
=
intval($std->my_getcookie('member_id'));$pid
=
$std->my_getcookie('pass_hash');
在此,my_cookie()函數使用下列語句從cookie中檢索要求的變數:
return
urldecode($_COOKIE[$ibforums->vars['cookie_id'].$name]);
【注意】從該cookie返回的值根本沒有被處理。盡管$mid在使用於查詢之前被強制轉換成一個整數,但是$pid卻保持不變。因此,它很容易遭受我們前面所討論的注入類型的攻擊。
因此,通過以如下方式修改my_cookie()函數,這種脆弱性就會暴露出來:
if
(
!
in_array(
$name,array('topicsread',
'forum_read','collapseprefs')
)
)
{
return
$this->
clean_value(urldecode($_COOKIE[$ibforums->vars['cookie_id'].$name]));
}
else
{
return
urldecode($_COOKIE[$ibforums->vars['cookie_id'].$name]);
}
經過這樣的改正之後,其中的關鍵變數在"通過"全局clean_value()函數後被返回,而其它變數卻未進行檢查。
現在,既然我們大致了解了什麼是SQL注入,它的注入原理以及這種注入的脆弱程度,那麼接下來,讓我們探討如何有效地預防它。幸好,PHP為我們提供了豐富的資源,因此我們有充分的信心預言,一個經仔細地徹底地使用我們所推薦的技術構建的應用程序將會從你的腳本中根本上消除任何可能性的SQL注入-通過在它可能造成任何損壞之前"清理"你的用戶的數據來實現。
㈡ php如何防止sql注入
額,這是我老師給的答案
答:過濾一些常見的資料庫操作關鍵字,
select ,insert,update,delete,and,*等或通過系統函數addslashes對內容進行過濾
php配置文件中register_globals=off;設置為關閉狀態.(作用將注冊全局變數關閉);如接收POST表單的值使用$_POST['user'],假設設置為ON的話$user才接收值
sql語句書寫的時候盡量不要省略小引號(tab上面那個)和單引號
提高資料庫命名技巧,對於一些重要的欄位根據程序的特點命名,使之不易被猜中
對於常的方法加以封裝,避免直接暴漏SQL語句
開啟PHP安全模式safe_mode=on
打開magic_quotes_gpc來防止SQL注入,默認為關閉,開啟後自動把用戶提交sql查詢語句進行轉換把"'"轉換成"\'"
控制錯誤信息輸出,關閉錯誤信息提示,將錯誤信息寫到系統日誌
使用MYSQLI或PDO預處理
㈢ PHP中如何防止SQL注入
我把問題和贊同最多的答題翻譯了下來。提問:如果用戶的輸入能直接插入到SQL語句中,那麼這個應用就易收到SQL注入的攻擊,舉個例子:$unsafe_variable = $_POST['user_input']; mysqli_query("INSERT INTO table (column) VALUES ('" . $unsafe_variable . "')");用戶可以輸入諸如 : value'); DROP TABLE table;-- ,SQL語句就變成這樣了:INSERT INTO table (column) VALUES('value'); DROP TABLE table;--')(譯者註:這樣做的結果就是把table表給刪掉了) 我們可以做什麼去阻止這種情況呢?回答:使用prepared statements(預處理語句)和參數化的查詢。這些SQL語句被發送到資料庫伺服器,它的參數全都會被單獨解析。使用這種方式,攻擊者想注入惡意的SQL是不可能的。要實現這個主要有兩種方式:1. 使用 PDO:$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name'); $stmt->execute(array(':name' => $name)); foreach ($stmt as $row) { // do something with $row }2. 使用 Mysqli:$stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?'); $stmt->bind_param('s', $name); $stmt->execute(); $result = $stmt->get_result(); while ($row = $result->fetch_assoc()) { // do something with $row }PDO需要注意的是使用PDO去訪問MySQL資料庫時,真正的prepared statements默認情況下是不使用的。為了解決這個問題,你需要禁用模擬的prepared statements。下面是使用PDO創建一個連接的例子:$dbConnection = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'pass'); $dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);上面的例子中,錯誤報告模式並不是強制和必須的,但建議你還是添加它。通過這種方式,腳本在出問題的時候不會被一個致命錯誤終止,而是拋出PDO Exceptions,這就給了開發者機會去捕獲這個錯誤。然而第一行的 setAttribute() 是強制性的,它使得PDO禁用模擬的prepared statements並使用真正的prepared statements。這可以確保這些語句和值在被發送到MySQL伺服器之前不會被PHP解析(這使得攻擊者沒有注入惡意SQL的機會)。盡管你可以使用可選的構造函數參數去設置 charset ,但重點需要注意的是小於5.3.6的PHP版本,DSN(Data Source Name)是默認忽略 charset 參數的。說明當你傳一個SQL語句做預處理時會發生什麼?它被資料庫伺服器解析和編譯了。通過指定參數(通過之前例子中的 ? 或者像 :name 這樣的命名式參數)你告訴資料庫引擎你是想過濾它。接著當你調用 execute() 函數時,prepared statements會和你剛才指定的參數的值結合。在此重要的是,參數的值是和編譯過的語句結合,而非一個SQL字元串。SQL注入就是當創建被發送到資料庫的SQL語句時,通過欺騙的手段讓腳本去引入惡意的字元串。因此當你使用單獨的參數發送真實正確的SQL時,你就限制了被某些不是你真實意圖的事情而搞掛掉的風險。使用prepared statements 傳遞的任何參數都會被當做字元串對待(不過資料庫引擎可能會做一些優化,這些參數最終也可能變成numbers)(譯者註:意思就是把參數當做一個字元串而不會去做額外的行為)。比如在上面的例子中,如果 $name 變數的值是 'Sarah'; DELETE * FROM employees ,產生的結果是會去搜索"'Sarah'; DELETE * FROM employees"這一整個字元串,最終的結果你也就不會面對的是一張空表了。使用prepared statements的另一個好處是,如果你在同一session中再次執行相同的語句,也就不會被再次解析和編譯,這樣你就獲得一些速度上的提升。
㈣ php防止sql注入以及xss跨站腳本攻擊
1.post數據
封裝轉義函數 防sql注入 eag:addslashes($username);addslashes($password);
eag:防止sql注入函數封裝
function deepslashes($data){
#判斷$data的表現形式 並且需要處理空的情況
if(empty($data)){
return($data);
}
#高級簡寫 return is_array($data) ? array_map('deepslashes',$data) : addslashes($data);
#初級寫法
if(is_array($data)){
#遞歸循環遍歷處理多維數組
foreach ($data as $v) {
return deepslashes($v);
}
}else{
#單一變數
return addslashes($data);
}
#初級寫法
}
2.get數據
指url 傳參數導致sql發生改變
解決方案
①強制轉換,使用函數intval 或者 數據類型 的關鍵字int
②隱式轉換,通過運算,只需要+0即可
3.xss跨站腳本攻擊
指惡意攻擊向web頁面插入html、js標簽導致頁面出現錯誤
解決方案
轉義標簽'<' '>'即可,有以下php函數可解決
htmlspecialchars 函數 和 htmlentites函數
eag:
function deepslashes($data){
#判斷$data的表現形式 並且需要處理空的情況
if(empty($data)){
return($data);
}
return is_array($data) ? array_map('deepslashes',$data) : htmlspecialchars ($data);
}
㈤ php防止sql注入簡單分析
本文實例分析了php防止sql注入簡單方法。分享給大家供大家參考。具體如下:
這里只說一個簡單的方法
防止Sql注入的方法有很多,這里要說的其實就是漏洞演練平台Dvwa里的一種方式
直接看high級別的就可以了
$id
=
$_GET['id'];
$id
=
stripslashes($id);
$id
=
mysql_real_escape_string($id);
if
(is_numeric($id)){
$getid
=
"SELECT
first_name,last_name
FROM
users
WHERE
user_id='$id'";
$result
=
mysql_query($getid)
or
die('<pre>'.mysql_error().'</pre>');
$num
=
mysql_numrows($result);
可見它的處理方式是首先通過
stripslashes
函數刪除變數中的反斜杠
\,
然後再使用函數mysql_real_escape_string
轉義特殊字元就行了。
所以當我們編寫類似代碼的時候
$getid="SELECT
first_name,last_name
FROM
users
WHERE
user_id='$id'";
我們最簡單的方法是
直接將變數$id
進行stripslashes
和
mysql_real_escape_string
處理。
注意:
這里並不是說這樣就安全了,
這只是其中一種方式我可沒說這就安全了。
更多的還要依據實際情況進行處理。
希望本文所述對大家的php程序設計有所幫助。
㈥ PHP要怎麼防止SQL注入
防止注入最簡單的辦法就是本地生成html文件,然後上傳到網站空間內,全站的html是無法被注入攻擊的,除非伺服器被幹掉。如果一定要將php代碼放到網站上,那麼需要防止的內容就要做的很多了,其中最重要的一條就是書寫代碼的規范程度,以及對用戶提交的驗證規范。如果用到專門的cms去做網站的話,一定要定時下載升級,並到相關的官方論壇及一些白客站點查看最新漏洞源碼信息,加以改正,可以有效的防止注入攻擊。
在注冊時防止注入,其實最主要的一條就是在寫入、查詢資料庫之前完成對用戶錄入數據的驗證。具體如何驗證可以網路搜索一下
㈦ ThinkPHP如何防止SQL注入
(1)查詢條件盡量使用數組方式,這是更為安全的方式;
(2)如果不得已必須使用字元串查詢條件,使用預處理機制;
(3)使用綁定參數;
(4)強制進行欄位類型驗證,可以對數值數據類型做強制轉換;
(5)使用自動驗證和自動完成機制進行針對應用的自定義過濾;
(6)使用欄位類型檢查、自動驗證和自動完成機制等避免惡意數據的輸入;
(7)做一些過濾。
㈧ 淺談:在PHP中該怎樣防止SQL注入
使用預處理語句和參數化查詢。
禁止使用拼接sql語句,和參數類型驗證,就可以完全避免sql注入漏洞!
預處理語句和參數分別發送到資料庫伺服器進行解析,參數將會被當作普通字元處理。這種方式使得攻擊者無法注入惡意的SQL。 你有兩種選擇來實現該方法:
1、使用PDO:
$stmt=$pdo->prepare('SELECT*FROMemployeesWHEREname=:name');
$stmt->execute(array('name'=>$name));
foreach($stmtas$row){
//dosomethingwith$row
}
2、使用mysqli:
$stmt=$dbConnection->prepare('SELECT*FROMemployeesWHEREname=?');
$stmt->bind_param('s',$name);
$stmt->execute();
$result=$stmt->get_result();
while($row=$result->fetch_assoc()){
//dosomethingwith$row
}
㈨ php如何防止sql注入
額,這是我老師給的答案x0dx0a x0dx0a答:過濾一些常見的資料庫操作關鍵字,x0dx0a select ,insert,update,delete,and,*等或通過系統函數addslashes對內容進行過濾x0dx0aphp配置文件中register_globals=off;設置為關閉狀態.(作用將注冊全局變數關閉);如接收POST表單的值使用$_POST['user'],假設設置為ON的話$user才接收值x0dx0asql語句書寫的時候盡量不要省略小引號(tab上面那個)和單引號x0dx0a提高資料庫命名技巧,對於一些重要的欄位根據程序的特點命名,使之不易被猜中x0dx0a對於常的方法加以封裝,避免直接暴漏SQL語句x0dx0a開啟PHP安全模式safe_mode=onx0dx0a打開magic_quotes_gpc來防止SQL注入,默認為關閉,開啟後自動把用戶提交sql查詢語句進行轉換把"'"轉換成"\'"x0dx0a控制錯誤信息輸出,關閉錯誤信息提示,將錯誤信息寫到系統日誌x0dx0a使用MYSQLI或PDO預處理
㈩ 如何修復SQL注入漏洞
以下是OMG我為大家收集整理的文章,希望對大家有所幫助。
SQL注入是通過把SQL命令插入到Web表單遞交或輸入域名或頁面請求的查詢字元串,最終達到欺騙伺服器執行惡意的SQL命令。其實就是就是提交精心構造的資料庫語句,使其反饋一些有用的數據。說白了就是去欺騙資料庫,假如只有web伺服器的話,是沒法進行SQL注入的。
網上常用的注入手法有兩種,一種是猜測,讓資料庫暴出用戶名、密碼等信息;另一種直接繞過認證,取得許可權。相對應,要想修復此類漏洞,就必須禁止特殊數據的提交或將特殊提交的數據修改。
下面是不同腳本語言下的防注入過濾代碼,其實思想是一致的。
1、 PHP防注入過濾代碼
php 代碼復制內容到剪貼板
<!-- ?php
/*************************
說明: 判斷傳遞的變數中是否含有非法字元 如$_POST、$_GET
功能: 防注入
使用方法: 將下列代碼保存為ak,php,調用方式 在數據提交頁加上include("ak.php");
**************************/
function dowith_sql($str)
//實現將特徵碼兩邊加.
{
$refuse_str="exec|and|or|select|update|from|where|order|by|*|delete||insert|into|values|create|table|
database|set|char|asc|cast|declare| </script|script|iframe|3bomb|c.js|;";>
//定義防注入的字元
$arr=explode("|",$refuse_str);
//將$refuse_str中的值單獨取出
for($i=0;$i<count($arr);$i++) p=""> </count($arr);$i++)>
{
$replace="[".$arr[$i]."]";
$str=str_replace($arr[$i],$replace,$str);
//在變數$str中搜索字元串$arr[$i],並將其替換為字元串[$replace]
}
return $str;
}
foreach ($_GET as $key=>$value)
//遍歷獲GET方法獲得的參數$_GET的值傳給$key,並賦值給$value
{
$_GET[$key]=dowith_sql($value);
//將$value中的特徵碼處理傳個$_GET[$key]
}
foreach ($_POST as $key=>$value)
{
$_POST[$key]=dowith_sql($value);
}
?>
上面的防注入的方法只是防了GET與POST方法提交的數據,但是,WEB伺服器讀取數據的順序是,先取GET中的數據,沒有再去POST中的數據,沒有還會再去COOKIES中的數據,上面的代碼還沒有防cookies注入。防cookies注入就比較簡單了,cookies的id值一般只為阿拉伯數字,但是cookies注入必須得在id中構造代碼,只要在獲得參數UID後,對其進行過濾就可以了,代碼如下:
php 代碼復制內容到剪貼板
<!-- ?php
if($_COOKIE[id]!=null) {
//判斷cookies不為空
foreach ($_COOKIE[id] as $key=>$id){
//讀取cookies中的值
if (is_numeric($id)<0){
echo " ";
}
}
}
?>
將上述代碼保存為hk.php。
所以在平時應用時,在網頁上加上include("ak.php");與include("hk.php");
2、 ASP防注入過濾代碼
<%
--------說明------------------
使用方法: 在需要防注的頁面頭部用 SSI ʱ B>
包含就可以了
友情提示:把代碼復制到CONN.asp(資料庫連接文件) 那麼,只要包含了CONN的所有文件都防注了
-------- ------------------------
Dim xf_Post,xf_Get,xf_In,xf_Inf,xf_Xh,xf_db,xf_dbstr
自定義需要過濾的字串,用 "|" 分隔
xf_In = "|;|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare"
xf_Inf = split(xf_In,"|")
If Request.Form<>"" Then
For Each xf_Post In Request.Form
For xf_Xh=0 To Ubound(xf_Inf)
If Instr(LCase(Request.Form(xf_Post)),xf_Inf(xf_Xh))<>0 Then
Response.Write ""
Response.Write "非法操作!系統做了如下記錄↓
"
Response.Write "操作IP:"&Request.ServerVariables("REMOTE_ADDR")&"
"
Response.Write "操作時間:"&Now&"
"
Response.Write "操作頁面:"&Request.ServerVariables("URL")&"
"
Response.Write "提交方式:POST
"
Response.Write "提交參數:"&xf_Post&"
"
Response.Write "提交數據:"&Request.Form(xf_Post)
Response.End
End If
Next
Next
End If
If Request.QueryString<>"" Then
For Each xf_Get In Request.QueryString
For xf_Xh=0 To Ubound(xf_Inf)
If Instr(LCase(Request.QueryString(xf_Get)),xf_Inf(xf_Xh))<>0 Then
Response.Write ""
Response.Write "非法操作!系統已經給你做了如下記錄↓
"
Response.Write "操作IP:"&Request.ServerVariables("REMOTE_ADDR")&"
"
Response.Write "操作時間:"&Now&"
"
Response.Write "操作頁面:"&Request.ServerVariables("URL")&"
"
Response.Write "提交方式:GET
"
Response.Write "提交參數:"&xf_Get&"
"
Response.Write "提交數據:"&Request.QueryString(xf_Get)
Response.End
End If
Next
Next
End If
%>
同樣,再將cookies防一下,代碼加在數據提交頁。
if(Request.Cookies["uid"]!=null)
{
uid=Request.Cookies["uid"].value;
isnumeric cooidesID = new isnumeric();
//這是一個類
if (cooidesID.reIsnumeric(ruid))
//如果是數字就運行下面的
{
string str="select * from userTable where id="+uid;
...
}
}
3、 JSP防注入過濾代碼