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