摘要:用戶提交過(guò)來(lái)的數(shù)據(jù)都是不可信的,所以,在查庫(kù)或入庫(kù)前需要對(duì)提交過(guò)來(lái)的數(shù)據(jù)進(jìn)行過(guò)濾或字符的轉(zhuǎn)換處理,以防止注入或攻擊等問(wèn)題。
一、防止SQL注入用戶提交過(guò)來(lái)的數(shù)據(jù)都是不可信的,所以,在查庫(kù)或入庫(kù)前需要對(duì)提交過(guò)來(lái)的數(shù)據(jù)進(jìn)行過(guò)濾或字符的轉(zhuǎn)換處理,以防止SQL注入或xss攻擊等問(wèn)題。
什么是SQL注入攻擊?
所謂SQL注入,就是通過(guò)把SQL命令插入到Web表單提交或輸入域名或頁(yè)面請(qǐng)求的查詢字符串,最終達(dá)到欺騙服務(wù)器執(zhí)行惡意的SQL命令。
尋找SQL注入的方法:
1.通過(guò)get請(qǐng)求
2.通過(guò)post請(qǐng)求
3.其他http請(qǐng)求,如cookie
常見(jiàn)的SQL注入問(wèn)題:
數(shù)據(jù)庫(kù)查詢參數(shù)的類型轉(zhuǎn)換處理
1. 轉(zhuǎn)義字符處理不當(dāng)Talk is cheap,Show me the code.
多說(shuō)無(wú)益,代碼亮出來(lái)吧!
// 構(gòu)造動(dòng)態(tài)SQL語(yǔ)句 ? $sql = "select * from tbl where field = "$_GET["input"]""; ? // 執(zhí)行SQL語(yǔ)句 ? $res = mysql_query($sql);
測(cè)試:
在下邊的網(wǎng)址后邊加一個(gè)單引號(hào),就會(huì)報(bào)數(shù)據(jù)庫(kù)錯(cuò)誤
http://testphp.vulnweb.com/ar...
// 構(gòu)造動(dòng)態(tài)SQL語(yǔ)句 $sql = "select * from tbl where field = $_GET["user_id"]"; // 執(zhí)行SQL語(yǔ)句 $res = mysql_query($sql);
Mysql內(nèi)置了一個(gè)命令,可以讀取文件
Union all select load_file("/etc/passwd")--
select * from tbl where userid = 1 union all select load_file("etc/passwd")--
該命令會(huì)獲取數(shù)據(jù)庫(kù)管理員的密碼。
處理方法:
需要將客戶端傳過(guò)來(lái)的數(shù)據(jù)進(jìn)行類型強(qiáng)制轉(zhuǎn)換,而后再查詢
$user_id = (int)$_GET["user_id"]; "select * from tbl where userid = {$user_id}";3. 查詢語(yǔ)句組織不當(dāng)
user.php?table=user&
4. 錯(cuò)誤處理不當(dāng)即將站點(diǎn)的錯(cuò)誤信息暴漏給用戶,這樣非常危險(xiǎn)。
// 構(gòu)造動(dòng)態(tài)查詢語(yǔ)句 $getid?=?"select?*?from?tbl?where?userid?>?1"; // 執(zhí)行SQL語(yǔ)句 $res = mysql_query($getid) or die("5. 多個(gè)提交處理不當(dāng)".mysql_error()."");
// 參數(shù)是否是一個(gè)字符串 if(is_string($_GET["param"])){}數(shù)據(jù)入庫(kù)時(shí)將轉(zhuǎn)換單引號(hào)、雙引號(hào)、反斜杠為實(shí)體
在入庫(kù)的時(shí)候如果不過(guò)濾 " ""這樣的東西,這樣會(huì)使數(shù)據(jù)庫(kù)報(bào)錯(cuò),或者注入等問(wèn)題。
先將字符串用htmlspecialchars()轉(zhuǎn)換為實(shí)體后存儲(chǔ)到數(shù)據(jù)庫(kù),然后從數(shù)據(jù)庫(kù)讀出來(lái)時(shí)htmlspecialchars_decode()轉(zhuǎn)為HTML標(biāo)簽。
htmlspecialchars() 函數(shù)把一些預(yù)定義的字符轉(zhuǎn)換為 HTML 實(shí)體。
函數(shù)原型:htmlspecialchars(string,quotestyle,character-set)
預(yù)定義的字符是:
& (和號(hào)) 成為 & ” (雙引號(hào)) 成為 " ‘ (單引號(hào)) 成為 ' < (小于) 成為 < > (大于) 成為 >
htmlspecialchars_decode() 函數(shù)把一些預(yù)定義的 HTML 實(shí)體轉(zhuǎn)換為字符(和htmlspecialchars相反)。
函數(shù)原型:htmlspecialchars_decode(string,quotestyle)
二、防止xss攻擊什么是xss攻擊?
和上邊的sql注入不同的是,xss攻擊是合法的字符串,如經(jīng)過(guò)htmlspecialchars()方法實(shí)體化后,可以保存在數(shù)據(jù)庫(kù)中,但是,當(dāng)訪問(wèn)含有該字符串的內(nèi)容頁(yè)面時(shí),就會(huì)出現(xiàn)問(wèn)題,如字符串里邊還有JavaScript,frame代碼,原來(lái)的頁(yè)面就會(huì)被篡改。
比如你寫個(gè)留言本,有人去留言寫
XSS概念
XSS又稱CSS,全稱Cross SiteScript(跨站腳本攻擊), XSS攻擊類似于SQL注入攻擊,是Web程序中常見(jiàn)的漏洞,XSS屬于被動(dòng)式且用于客戶端的攻擊方式,所以容易被忽略其危害性。其原理是攻擊者向有XSS漏洞的網(wǎng)站中輸入(傳入)惡意的HTML代碼,當(dāng)用戶瀏覽該網(wǎng)站時(shí),這段HTML代碼會(huì)自動(dòng)執(zhí)行,從而達(dá)到攻擊的目的。如,盜取用戶Cookie信息、破壞頁(yè)面結(jié)構(gòu)、重定向到其它網(wǎng)站等。
理論上,只要存在能提供輸入的表單并且沒(méi)做安全過(guò)濾或過(guò)濾不徹底,都有可能存在XSS漏洞。
下面是一些最簡(jiǎn)單并且比較常見(jiàn)的惡意字符XSS輸入:
1.XSS 輸入通常包含 JavaScript 腳本,如彈出惡意警告框:
2.XSS 輸入也可能是 HTML 代碼段,譬如:
(1).網(wǎng)頁(yè)不停地刷新
(2).嵌入其它網(wǎng)站的鏈接
除了通過(guò)正常途徑輸入XSS攻擊字符外,還可以繞過(guò)JavaScript校驗(yàn),通過(guò)修改請(qǐng)求達(dá)到XSS攻擊的目的,如下圖:
了解到XSS攻擊的原理和危害后,其實(shí)要預(yù)防也不難,下面提供一個(gè)簡(jiǎn)單的PHP防止XSS攻擊的函數(shù):
除了通過(guò)正常途徑輸入XSS攻擊字符外,還可以繞過(guò)JavaScript校驗(yàn),通過(guò)修改請(qǐng)求達(dá)到XSS攻擊的目的。
了解到XSS攻擊的原理和危害后,其實(shí)要預(yù)防也不難,下面提供一個(gè)簡(jiǎn)單的PHP防止XSS攻擊的函數(shù):
"; clean_xss($str); //如果你把這個(gè)注釋掉,你就知道xss攻擊的厲害了 echo $str; ?>
避免被XSS:
1.給用戶開(kāi)放的編輯器盡量過(guò)濾掉危險(xiǎn)的代碼
如果是html編輯器,一般的做法是保留大部分代碼,過(guò)濾部分可能存在危險(xiǎn)的代碼,如script, iframe等等
預(yù)處理語(yǔ)句對(duì)于防止 MySQL 注入是非常有用的。
預(yù)處理語(yǔ)句及綁定參數(shù)
預(yù)處理語(yǔ)句用于執(zhí)行多個(gè)相同的 SQL 語(yǔ)句,并且執(zhí)行效率更高。
預(yù)處理語(yǔ)句的工作原理如下:
預(yù)處理:創(chuàng)建 SQL 語(yǔ)句模板并發(fā)送到數(shù)據(jù)庫(kù)。預(yù)留的值使用參數(shù) "?" 標(biāo)記 。例如:
INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)
數(shù)據(jù)庫(kù)解析,編譯,對(duì)SQL語(yǔ)句模板執(zhí)行查詢優(yōu)化,并存儲(chǔ)結(jié)果不輸出。
執(zhí)行:最后,將應(yīng)用綁定的值傳遞給參數(shù)("?" 標(biāo)記),數(shù)據(jù)庫(kù)執(zhí)行語(yǔ)句。應(yīng)用可以多次執(zhí)行語(yǔ)句,如果參數(shù)的值不一樣。
相比于直接執(zhí)行SQL語(yǔ)句,預(yù)處理語(yǔ)句有兩個(gè)主要優(yōu)點(diǎn):
預(yù)處理語(yǔ)句大大減少了分析時(shí)間,只做了一次查詢(雖然語(yǔ)句多次執(zhí)行)。
綁定參數(shù)減少了服務(wù)器帶寬,你只需要發(fā)送查詢的參數(shù),而不是整個(gè)語(yǔ)句。
預(yù)處理語(yǔ)句針對(duì)SQL注入是非常有用的,因?yàn)閰?shù)值發(fā)送后使用不同的協(xié)議,保證了數(shù)據(jù)的合法性。
PDO預(yù)處理機(jī)制
可以使用多種方式實(shí)現(xiàn)預(yù)處理:指的是在綁定數(shù)據(jù)進(jìn)行執(zhí)行的時(shí)候,可以有多種方式。
預(yù)處理語(yǔ)句中為變量
使用數(shù)組指定預(yù)處理變量
1、準(zhǔn)備預(yù)處理語(yǔ)句(發(fā)送給服務(wù)器,讓服務(wù)器準(zhǔn)備預(yù)處理語(yǔ)句) PDOStatement PDO::prepare:類似exec將一條SQL語(yǔ)句發(fā)送給Mysql服務(wù)器 //PDO::prepare 能夠自動(dòng)的準(zhǔn)備一個(gè)預(yù)處理語(yǔ)句,用戶需要準(zhǔn)備的只是預(yù)處理所要執(zhí)行的語(yǔ)句 //需求:往學(xué)生表里循環(huán)插入10條記錄 //PDO的預(yù)處理能夠自動(dòng)的將對(duì)應(yīng)的以:開(kāi)始的變量給記錄下來(lái),實(shí)際發(fā)送給服務(wù)器的是“?” $sql1 = "insert into pro_student values(null,:s_name,:s_num,:s_gender,:s_age,:c_id)"; 2、發(fā)送預(yù)處理語(yǔ)句 $stmt = $pdo->prepare($sql1); 3、給預(yù)處理綁定數(shù)據(jù) $arr = array( ":s_name" => "房祖名", ":s_num" => "itcast0013", ":s_gender" => 0, ":s_age" => 28, ":c_id" => 2 ); 4、執(zhí)行預(yù)處理:將要操作的數(shù)據(jù)發(fā)送給預(yù)處理語(yǔ)句,再執(zhí)行預(yù)處理語(yǔ)句 PDOStatement::execute([$array]):數(shù)組用來(lái)傳遞對(duì)應(yīng)的參數(shù) $stmt->execute($arr); //執(zhí)行預(yù)處理
PDO預(yù)處理原理
PDO的預(yù)防sql注入的機(jī)制也是類似于使用mysql_real_escape_string 進(jìn)行轉(zhuǎn)義,PDO 有兩種轉(zhuǎn)義的機(jī)制,第一種是本地轉(zhuǎn)義,這種轉(zhuǎn)義的方式是使用單字節(jié)字符集(PHP < 5.3.6)來(lái)轉(zhuǎn)義的(單字節(jié)與多字節(jié)),來(lái)對(duì)輸入進(jìn)行轉(zhuǎn)義,但是這種轉(zhuǎn)義方式有一些隱患。隱患主要是:在PHP版本小于5.3.6的時(shí)候,本地轉(zhuǎn)義只能轉(zhuǎn)換單字節(jié)的字符集,大于 5.3.6 的版本會(huì)根據(jù) PDO 連接中指定的 charset 來(lái)轉(zhuǎn)義。
第二種方式是PDO,首先將 sql 語(yǔ)句模板發(fā)送給Mysql Server,隨后將綁定的字符變量再發(fā)送給Mysql server,這里的轉(zhuǎn)義是在Mysql Server做的,它是根據(jù)你在連接PDO的時(shí)候,在charset里指定的編碼格式來(lái)轉(zhuǎn)換的。這樣的轉(zhuǎn)義方式更健全,同時(shí)還可以在又多次重復(fù)查詢的業(yè)務(wù)場(chǎng)景下,通過(guò)復(fù)用模板,來(lái)提高程序的性能。如果要設(shè)置Mysql Server 來(lái)轉(zhuǎn)義的話,就要首先執(zhí)行:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
原始鏈接方法:
setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $dbh->exec("set names utf8"); $title = "我們的愛(ài)情"; $content = "你是/誰(shuí)啊,大幾都"老梁"做做&>women沒(méi)" . " 測(cè)試打印號(hào)"我是單引號(hào)"哈哈"; $user_id = 174742; $add_time = date("Y-m-d H:i:s"); $insert_sql = "insert into post_tbl (title, content, user_id, add_time) values (:x_title, :x_content, :x_user_id, :x_add_time)"; $stmt = $dbh->prepare($insert_sql); $stmt->execute(array("x_title"=>$title,":x_content"=> $content, ":x_user_id" => $user_id, ":x_add_time" => $add_time)); echo $dbh->lastinsertid();
可見(jiàn)這次PHP是將SQL模板和變量是分兩次發(fā)送給MySQL的,由MySQL完成變量的轉(zhuǎn)義處理,既然變量和SQL模板是分兩次發(fā)送的,那么就不存在SQL注入的問(wèn)題了,但需要在DSN中指定charset屬性,如:
$pdo = new PDO("mysql:host=localhost;dbname=test;charset=utf8", "root");
示例:
/** * 插入用戶的Token */ function photo_save_token($user_id, $token) { // 參數(shù)判斷 $user_id = (int)$user_id; $token = trim($token); if(empty($token) || empty($user_id)) return false; $sql = "replace into token_db.app_token_tbl ( user_id, token, t_date, last_open_time) values ( :x_user_id, :x_token, :x_t_date, :x_last_open_time)"; sqlSetParam($sql,"x_user_id",$user_id); sqlSetParam($sql,"x_token",$token); sqlSetParam($sql,"x_t_date",date("Y-m-d H:i:s")); sqlSetParam($sql,"x_last_open_time", time()); return mysql_query($sql); }
總結(jié): 當(dāng)調(diào)用 prepare() 時(shí),查詢語(yǔ)句已經(jīng)發(fā)送給了數(shù)據(jù)庫(kù)服務(wù)器,此時(shí)只有占位符 ? 發(fā)送過(guò)去,沒(méi)有用戶提交的數(shù)據(jù);當(dāng)調(diào)用到 execute()時(shí),用戶提交過(guò)來(lái)的值才會(huì)傳送給數(shù)據(jù)庫(kù),他們是分開(kāi)傳送的,兩者獨(dú)立的,SQL攻擊者沒(méi)有一點(diǎn)機(jī)會(huì)。
相關(guān)文章:
php-PDO預(yù)處理
PHP MySQL 預(yù)處理語(yǔ)句
pdo如何防止 sql注入
①、關(guān)于sql注入可以使用htmlspecialchars()或addslashes()方法,如果連接mysql,可以用mysql_real_escape_string(),還有在php.ini中配置magic_quotes_gpc開(kāi)啟自動(dòng)轉(zhuǎn)義的擴(kuò)展。
PHP環(huán)境打開(kāi)自動(dòng)轉(zhuǎn)義,PHP.INI中查看
當(dāng)magic_quotes_gpc=on 時(shí)將自動(dòng)進(jìn)行轉(zhuǎn)義(默認(rèn)是on),可在程序中用get_magic_quotes_gpc()檢查他的狀態(tài)
程序?yàn)椋?/p>
if (get_magic_quotes_gpc()==1){ $name=stripcslashes($_POST["name"]); }else{ $name=$_POST["name"]; }
②、關(guān)于xss攻擊可以寫一個(gè)去處script,frame等代碼的方法:
直接用這個(gè)函數(shù)editor_safe_replace代替htmlspecialchars,既保證安全又能用大部分html代碼
function editor_safe_replace($content) { $content = trim($content); $tags = array( """is", ""]*?>.*?"is", """is", ""]*?>.*?"is", ""]*?>.*? "is", ""]*?>"is", ""]*?>"is", ); // 1.先過(guò)濾掉含有xss攻擊的代碼 $content = preg_replace($tags, "", $content); // strip_tags過(guò)濾掉全部HTML標(biāo)簽(script,iframe,head,a 等標(biāo)簽)和上邊的正則方法類似 // $content = strip_tags($content); // 2.入庫(kù)時(shí),防止sql注入,轉(zhuǎn)為HTML實(shí)體保存在數(shù)據(jù)庫(kù),單雙引號(hào)都轉(zhuǎn) $content = htmlspecialchars($content, ENT_QUOTES); // 3.替換反斜杠 $content = preg_replace("http://", "\", $content); // 4.替換斜杠 $content = preg_replace("http:///", "/", $content); return $content; }
所以,對(duì)于PHP的安全而言,一定要對(duì)用戶提交的數(shù)據(jù)進(jìn)行過(guò)濾校驗(yàn)處理,即先防止SQL注入,后再進(jìn)行XSS過(guò)濾,這兩個(gè)都需要兩手一起抓,且兩手都要硬,否則,你的網(wǎng)站將會(huì)存在很大的安全風(fēng)險(xiǎn)。
相關(guān)文章:
PHP 安全三板斧:過(guò)濾、驗(yàn)證和轉(zhuǎn)義之轉(zhuǎn)義篇 & Blade模板引擎避免XSS攻擊原理探究
8個(gè)很有用的PHP安全函數(shù),你知道幾個(gè)?
HTML 字符實(shí)體對(duì)照表
PDO使用方法簡(jiǎn)介
利用SQL注入漏洞登錄后臺(tái)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/21855.html
摘要:開(kāi)發(fā)擴(kuò)展是用語(yǔ)言實(shí)現(xiàn)的,流行的很大一個(gè)原因也是因?yàn)橛写罅块_(kāi)發(fā)者通過(guò)擴(kuò)展實(shí)現(xiàn)大量通用的功能供廣大社區(qū)開(kāi)發(fā)者使用。擴(kuò)展化的優(yōu)勢(shì)產(chǎn)品安全性和私密性好系統(tǒng)性能高擴(kuò)展化的劣勢(shì)開(kāi)發(fā)效率低的優(yōu)勢(shì)之一就是開(kāi)發(fā)效率高,需要選擇系統(tǒng)合適的模塊進(jìn)行擴(kuò)展化。 php是解釋性語(yǔ)言,不需要編譯。對(duì)于用php寫的產(chǎn)品,如果需要直接源碼安裝到客戶的運(yùn)行環(huán)境中,則存在很大的安全隱患。客戶甚至可以把你的產(chǎn)品直接做二次部署...
摘要:從最大的同性社交平臺(tái)獲取數(shù)據(jù)好了,言歸正傳,回到題目。烏云密布的爬蟲(chóng)百度網(wǎng)盤這件事,是我不想看到的,這類安全問(wèn)題的一個(gè)共同特點(diǎn)用戶自身確實(shí)存在問(wèn)題。 本文作者:夏之冰雪,i春秋簽約作家 《我在百度網(wǎng)盤上看到上萬(wàn)條車主個(gè)人信息,企業(yè)、政府高官信息、各種數(shù)據(jù)庫(kù)和無(wú)窮無(wú)盡的盜版》,一時(shí)間,這篇文章就火了,火爆程度另百度猝不及防。 其實(shí)呢,這事真不能全怪百度,畢竟用戶分享出去了。之所以引起這么...
摘要:常見(jiàn)的就是,它是一個(gè)完整的目錄。的特點(diǎn)是簡(jiǎn)單,使用一個(gè)中央版本庫(kù)。當(dāng)初公司的日均均超過(guò),所以采用的是方案雙機(jī)熱備集群優(yōu)化架構(gòu)圖上是兩主兩從。 前言 五年前,我在CNBLOG寫的一篇文章,《php+mysql下,對(duì)網(wǎng)站架構(gòu)方面的一些認(rèn)識(shí)(以我維護(hù)的站點(diǎn)為例)》,當(dāng)然,整套架構(gòu)不是做的,而是配合當(dāng)初的運(yùn)維部門,共同完成。那個(gè)時(shí)候我從入行PHP兩年,對(duì)所謂的架構(gòu)也是懵懂。只覺(jué)得很深?yuàn)W,很高大...
閱讀 3290·2021-09-09 11:39
閱讀 1236·2021-09-09 09:33
閱讀 1139·2019-08-30 15:43
閱讀 555·2019-08-29 14:08
閱讀 1740·2019-08-26 13:49
閱讀 2386·2019-08-26 10:09
閱讀 1552·2019-08-23 17:13
閱讀 2290·2019-08-23 12:57