mysql 可以使用更安全的pdo_mysql接口來處理

成都創(chuàng)新互聯(lián)長期為1000多家客戶提供的網站建設服務,團隊從業(yè)經驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網生態(tài)環(huán)境。為遠安企業(yè)提供專業(yè)的成都做網站、網站建設,遠安網站改版等技術服務。擁有十載豐富建站經驗和眾多成功案例,為您定制開發(fā)。
所有的查詢參數話綁定
$sql = 'select * from table where id=:id';
$pdo-prepare($sql)-bindValue(':id', $id, PDO::PARAM_INT)-excute();
$pdo-fetch(); 來獲取數據 這樣可以很有效的避免被注入
防止Sql注入最簡單的辦法就是讓web層和數據持久層分離。
web層--業(yè)務邏輯層--數據持久層。
所有的數據庫操作都通過業(yè)務邏輯層來操作。
web層就沒有訪問數據庫權限,這是最穩(wěn)妥的辦法。
MySQL SQL 注入
SQL注入可能是目前互聯(lián)網上存在的最豐富的編程缺陷。 這是未經授權的人可以訪問各種關鍵和私人數據的漏洞。 SQL注入不是Web或數據庫服務器中的缺陷,而是由于編程實踐較差且缺乏經驗而導致的。 它是從遠程位置執(zhí)行的最致命和最容易的攻擊之一。
我們永遠不要信任用戶的輸入,我們必須認定用戶輸入的數據都是不安全的,我們都需要對用戶輸入的數據進行過濾處理。
以下實例中,輸入的用戶名必須為字母、數字及下劃線的組合,且用戶名長度為 8 到 20 個字符之間:
讓我們看下在沒有過濾特殊字符時,出現的SQL情況:
以上的注入語句中,我們沒有對 $name 的變量進行過濾,$name 中插入了我們不需要的SQL語句,將刪除 users 表中的所有數據。
在PHP中的 mysqli_query() 是不允許執(zhí)行多個 SQL 語句的,但是在 SQLite 和 PostgreSQL 是可以同時執(zhí)行多條SQL語句的,所以我們對這些用戶的數據需要進行嚴格的驗證。
防止SQL注入,我們需要注意以下幾個要點:
永遠不要信任用戶的輸入。對用戶的輸入進行校驗,可以通過正則表達式,或限制長度;對單引號和 雙”-“進行轉換等。
永遠不要使用動態(tài)拼裝sql,可以使用參數化的sql或者直接使用存儲過程進行數據查詢存取。
.永遠不要使用管理員權限的數據庫連接,為每個應用使用單獨的權限有限的數據庫連接。
不要把機密信息直接存放,加密或者hash掉密碼和敏感的信息。
應用的異常信息應該給出盡可能少的提示,最好使用自定義的錯誤信息對原始錯誤信息進行包裝
sql注入的檢測方法一般采取輔助軟件或網站平臺來檢測,軟件一般采用sql注入檢測工具jsky,網站平臺就有億思網站安全平臺檢測工具。MDCSOFT SCAN等。采用MDCSOFT-IPS可以有效的防御SQL注入,XSS攻擊等。
教程來源:樹懶學堂_一站式數據知識學習平臺_MySQK 防止SQL注入
補充:
對于16進制入侵還沒確切防御手段,只能自己手動查有沒有被入侵這樣
你可以用javascript做客戶端限制輸入數據,治標不治本而已,填用戶名的表單用username做name
function validate(){
var username = $("#username").val();
if (username.match(/[^a-zA-Z0-9]/) || username.length 3)
{
alert('Invalid username: \'' + username+'\'' );
return false;
}
}
-------------------------------------------------------
php 漏洞已經相對很少了,告訴你個簡單的預防單引號的方法
寫下這個function
function sql_quote( $value )
{
if( get_magic_quotes_gpc() )
{
$value = stripslashes( $value );
}
if( function_exists( "mysql_real_escape_string" ) )
{
$value = mysql_real_escape_string( $value );
}
else
{
$value = addslashes( $value );
}
return $value;
}
然后寫sql的時候這么寫
$username = $_POST['username'];
query = "SELECT * FROM users WHERE username='".sql_quote($username) . "'";
如果有注入攻擊的話必定用到單引號
//沒有用sql_quote的sql語言
query = "SELECT * FROM users WHERE username='' OR '1'='1'";
//用了的,單引號就被避免了
query = "SELECT * FROM users WHERE username='\' OR \'1\'=\'1'";
你可以學習一下如何防止MYSQL被注入。
一、SQL注入簡介
SQL注入是比較常見的網絡攻擊方式之一,它不是利用操作系統(tǒng)的BUG來實現攻擊,而是針對程序員編程時的疏忽,通過SQL語句,實現無帳號登錄,甚至篡改數據庫。
二、SQL注入攻擊的總體思路
1.尋找到SQL注入的位置
2.判斷服務器類型和后臺數據庫類型
3.針對不通的服務器和數據庫特點進行SQL注入攻擊
三、SQL注入攻擊實例
比如在一個登錄界面,要求輸入用戶名和密碼:
可以這樣輸入實現免帳號登錄:
用戶名: ‘or 1 = 1 –
密 碼:
點登陸,如若沒有做特殊處理,那么這個非法用戶就很得意的登陸進去了.(當然現在的有些語言的數據庫API已經處理了這些問題)
這是為什么呢? 下面我們分析一下:
從理論上說,后臺認證程序中會有如下的SQL語句:
String sql = "select * from user_table where username=
' "+userName+" ' and password=' "+password+" '";
當輸入了上面的用戶名和密碼,上面的SQL語句變成:
SELECT * FROM user_table WHERE username=
'’or 1 = 1 -- and password='’
分析SQL語句:
條件后面username=”or 1=1 用戶名等于 ” 或1=1 那么這個條件一定會成功;
然后后面加兩個-,這意味著注釋,它將后面的語句注釋,讓他們不起作用,這樣語句永遠都能正確執(zhí)行,用戶輕易騙過系統(tǒng),獲取合法身份。
這還是比較溫柔的,如果是執(zhí)行
SELECT * FROM user_table WHERE
username='' ;DROP DATABASE (DB Name) --' and password=''
….其后果可想而知…
四、應對方法
下面我針對JSP,說一下應對方法:
1.(簡單又有效的方法)PreparedStatement
采用預編譯語句集,它內置了處理SQL注入的能力,只要使用它的setXXX方法傳值即可。
使用好處:
(1).代碼的可讀性和可維護性.
(2).PreparedStatement盡最大可能提高性能.
(3).最重要的一點是極大地提高了安全性.
原理:
sql注入只對sql語句的準備(編譯)過程有破壞作用
而PreparedStatement已經準備好了,執(zhí)行階段只是把輸入串作為數據處理,
而不再對sql語句進行解析,準備,因此也就避免了sql注入問題.
2.使用正則表達式過濾傳入的參數
要引入的包:
import java.util.regex.*;
正則表達式:
private String CHECKSQL = “^(.+)\\sand\\s(.+)|(.+)\\sor(.+)\\s$”;
判斷是否匹配:
Pattern.matches(CHECKSQL,targerStr);
下面是具體的正則表達式:
檢測SQL meta-characters的正則表達式 :
/(\%27)|(\’)|(\-\-)|(\%23)|(#)/ix
修正檢測SQL meta-characters的正則表達式 :/((\%3D)|(=))[^\n]*((\%27)|(\’)|(\-\-)|(\%3B)|(:))/i
典型的SQL 注入攻擊的正則表達式 :/\w*((\%27)|(\’))((\%6F)|o|(\%4F))((\%72)|r|(\%52))/ix
檢測SQL注入,UNION查詢關鍵字的正則表達式 :/((\%27)|(\’))union/ix(\%27)|(\’)
檢測MS SQL Server SQL注入攻擊的正則表達式:
/exec(\s|\+)+(s|x)p\w+/ix
等等…..
3.字符串過濾
比較通用的一個方法:
(||之間的參數可以根據自己程序的需要添加)
public static boolean sql_inj(String str)
{
String inj_str = "'|and|exec|insert|select|delete|update|
count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";
String inj_stra[] = split(inj_str,"|");
for (int i=0 ; i inj_stra.length ; i++ )
{
if (str.indexOf(inj_stra[i])=0)
{
return true;
}
}
return false;
}
4.jsp中調用該函數檢查是否包函非法字符
防止SQL從URL注入:
sql_inj.java代碼:
package sql_inj;
import java.net.*;
import java.io.*;
import java.sql.*;
import java.text.*;
import java.lang.String;
public class sql_inj{
public static boolean sql_inj(String str)
{
String inj_str = "'|and|exec|insert|select|delete|update|
count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";
//這里的東西還可以自己添加
String[] inj_stra=inj_str.split("\\|");
for (int i=0 ; i inj_stra.length ; i++ )
{
if (str.indexOf(inj_stra[i])=0)
{
return true;
}
}
return false;
}
}
5.JSP頁面判斷代碼:
使用javascript在客戶端進行不安全字符屏蔽
功能介紹:檢查是否含有”‘”,”\\”,”/”
參數說明:要檢查的字符串
返回值:0:是1:不是
函數名是
function check(a)
{
return 1;
fibdn = new Array (”‘” ,”\\”,”/”);
i=fibdn.length;
j=a.length;
for (ii=0; ii<i; ii++)
{ for (jj=0; jj<j; jj++)
{ temp1=a.charAt(jj);
temp2=fibdn[ii];
if (tem’; p1==temp2)
{ return 0; }
}
}
return 1;
}
===================================
總的說來,防范一般的SQL注入只要在代碼規(guī)范上下點功夫就可以了。
凡涉及到執(zhí)行的SQL中有變量時,用JDBC(或者其他數據持久層)提供的如:PreparedStatement就可以 ,切記不要用拼接字符串的方法就可以了。
我把問題和贊同最多的答題翻譯了下來。提問:如果用戶的輸入能直接插入到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語句被發(fā)送到數據庫服務器,它的參數全都會被單獨解析。使用這種方式,攻擊者想注入惡意的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創(chuàng)建一個連接的例子:$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,這就給了開發(fā)者機會去捕獲這個錯誤。然而第一行的 setAttribute() 是強制性的,它使得PDO禁用模擬的prepared statements并使用真正的prepared statements。這可以確保這些語句和值在被發(fā)送到MySQL服務器之前不會被PHP解析(這使得攻擊者沒有注入惡意SQL的機會)。盡管你可以使用可選的構造函數參數去設置 charset ,但重點需要注意的是小于5.3.6的PHP版本,DSN(Data Source Name)是默認忽略 charset 參數的。說明當你傳一個SQL語句做預處理時會發(fā)生什么?它被數據庫服務器解析和編譯了。通過指定參數(通過之前例子中的 ? 或者像 :name 這樣的命名式參數)你告訴數據庫引擎你是想過濾它。接著當你調用 execute() 函數時,prepared statements會和你剛才指定的參數的值結合。在此重要的是,參數的值是和編譯過的語句結合,而非一個SQL字符串。SQL注入就是當創(chuàng)建被發(fā)送到數據庫的SQL語句時,通過欺騙的手段讓腳本去引入惡意的字符串。因此當你使用單獨的參數發(fā)送真實正確的SQL時,你就限制了被某些不是你真實意圖的事情而搞掛掉的風險。使用prepared statements 傳遞的任何參數都會被當做字符串對待(不過數據庫引擎可能會做一些優(yōu)化,這些參數最終也可能變成numbers)(譯者注:意思就是把參數當做一個字符串而不會去做額外的行為)。比如在上面的例子中,如果 $name 變量的值是 'Sarah'; DELETE * FROM employees ,產生的結果是會去搜索"'Sarah'; DELETE * FROM employees"這一整個字符串,最終的結果你也就不會面對的是一張空表了。使用prepared statements的另一個好處是,如果你在同一session中再次執(zhí)行相同的語句,也就不會被再次解析和編譯,這樣你就獲得一些速度上的提升。
分享名稱:怎么防止mysql注入 mysql注入的修復方式有哪些
當前地址:http://chinadenli.net/article22/doopsjc.html
成都網站建設公司_創(chuàng)新互聯(lián),為您提供App開發(fā)、微信公眾號、用戶體驗、商城網站、自適應網站、網站維護
聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)