php安全 - PHP如何安全地使用$_GET
本人新手,在《PHP安全编码》中提到“不要直接使用$_GET”,同时又提到“可以尝试在php.ini中开启magic_quotes_gpc,这样对于所有由用户GET、POST、COOKIE中传入的特殊字符都会转义”,我很纠结,是否开启magic_quotes_gpc就可以直接使用$_GET?
如下面例子中的代码本人感觉很不安全,因为没有做验证,但又不知道如何改进,希望大神能帮忙,谢谢。
<code><?php $name = $_GET["name"]; $user = $_GET["user"]; mysql_query("SELECT $name FROM $user"); </code></code>
回复内容:
本人新手,在《PHP安全编码》中提到“不要直接使用$_GET”,同时又提到“可以尝试在php.ini中开启magic_quotes_gpc,这样对于所有由用户GET、POST、COOKIE中传入的特殊字符都会转义”,我很纠结,是否开启magic_quotes_gpc就可以直接使用$_GET?
如下面例子中的代码本人感觉很不安全,因为没有做验证,但又不知道如何改进,希望大神能帮忙,谢谢。
<code><?php $name = $_GET["name"]; $user = $_GET["user"]; mysql_query("SELECT $name FROM $user"); </code></code>
你是想要filter_input函数,多看手册:
http://www.w3school.com.cn/php/func_filter_input.asp
<code>纯数字的参数intval强制取整 其他参数值进行过滤或者转义 protected function zaddslashes($string, $force = 0, $strip = FALSE) { if (!defined('MAGIC_QUOTES_GPC')) { define('MAGIC_QUOTES_GPC', ''); } if (!MAGIC_QUOTES_GPC || $force) { if (is_array($string)) { foreach ($string as $key => $val) { $string[$key] = $this->zaddslashes($val, $force, $strip); } } else { $string = ($strip ? stripslashes($string) : $string); $string = htmlspecialchars($string); } } return $string; } </code>
我一般都对$_POST $_GET都使用zaddslashes,然后整数的参数值进行取整,防止XSS和SQL注入
HTTP头信息:IP、浏览器信息、等也进行转义过滤防止HTTP头注入
magic_quotes_gpc开启后会影响图片上传等,自动将内容引号转义
注意PHP5.5包括之后已经将magic_quotes_gpc配置废弃
除此之外,最好在服务器方面也做关键词过滤,Mysql为业务使用到的库创建用户和赋权
可以把自己应用放服务器上,装个sqlmap注入下自己试试,以上几点做到一般情况下不会被搞,至少不会被getshell
乌云白帽子路过...
1. 像用户名这种有格式的东西,应该取到之后马上用正则表达式验证,比如preg_match('/\A\w{6,14}\z/', $user)
就验证了它是不是6~14位的数字字母下划线。不要使用系统自带的filter,那个管不了什么用。
2. 不要使用mysql
开头的函数,要使用mysqli
,而且最好进行参数化查询而不是addslashes
,后者会有编码问题。
3. 输出html的时候,默认使用htmlspecialchars
,这个函数可以指定编码。或者你可以用现成的模板引擎。
4. 比较字符串的时候,强制使用strcmp
,不要使用双等号。
5. 不要使用$_REQUEST
。
这样可以防掉95%。至于magic_quotes_gpc
,应该早就废了吧。
现在市面上这些书真的害人不浅,随便下结论或者是楼主没有仔细读。为什么直接使用 $_GET $_POST 不安全?
看了楼主的例子,应该是直接将$_GET 用在拼接SQL上,这样肯定是不安全的,所以核心信息应该是:直接将 $_GET/$_POST等用户输入的内容用于SQL拼接是不安全的,如何避免?
例如:
<code>sql</code><code>select * from user where username= "$_GET['username']" </code>
如果用户提交的username 为
<code>sql</code><code>" 0 or true or username =" </code>
那么就会变成这样:
<code>sql</code><code>select * from user where username = "0" or true or username="" </code>
那么会返回所有的用户记录。当然这里只是粗暴的举了一个例子。实际上要做XSS要熟知代码或者猜测到运行的逻辑等了解很多东西。
最简单的过滤方法是使用 mysql_real_escape_string 函数
至于 magic_quotes,是php最失败的一个改进,现已废弃,就算是低版本的PHP也一定要关闭它。
如果 $_GET
首先判断是否为空
然后对值进行判断
举个例子:
只接受数字 那就使用 php自带函数 is_numeric
一般 GET 也只是传递某个标识
总之在数据库或其他操作之前 先验证 传过来的变量 是否为自己预期的值
可以先对post或者get请求过滤,php有内置函数进行过滤,然后在使用
同意二楼的要有一个过滤,不过只是系统自带的肯定不行,最好自己再根据情况做一个过滤等之类的处理。
防止XSS攻击,最简单粗暴的做法就是用htmlspecialchars把特殊字符(&,",',
)转换为HTML实体(&"'<>
)后输出.
<code><?php echo htmlspecialchars($html, ENT_QUOTES, 'UTF-8'); </code></code>
防止XSS攻击,最复杂的就是自己写正则过滤,不过还好有HTMLPurifier库,除了能过滤XSS代码,还能把不完整的标签补全或者去掉.Yii框架也用到了这个XSS过滤库.
http://htmlpurifier.org/download
<code><?php require dirname(__FILE__).'/htmlpurifier/library/HTMLPurifier.auto.php'; $purifier = new HTMLPurifier(); echo $purifier->purify($html); </code>
上面说的是防御XSS,下面说防御SQL注入:
PDO和MySQLi等都提供有绑定参数查询的功能,而绑定参数的目的就是防止SQL注入.
http://php.net/manual/zh/pdo.prepared-statements.php
很多更成熟的数据库都支持预处理语句的概念.
什么是预处理语句?可以把它看作是想要运行的SQL的一种编译过的模板,它可以使用变量参数进行定制.
预处理语句可以带来两大好处:
1.查询仅需解析(或预处理)一次,但可以用相同或不同的参数执行多次.
当查询准备好后,数据库将分析/编译/优化执行该查询的计划.
对于复杂的查询,此过程要花费较长的时间,如果需要以不同参数多次重复相同的查询,那么该过程将大大降低应用程序的速度.
通过使用预处理语句,可以避免重复分析/编译/优化周期.
简言之,预处理语句占用更少的资源,因而运行得更快.
2.提供给预处理语句的参数不需要用引号括起来,驱动程序会自动处理.
如果应用程序只使用预处理语句,可以确保不会发生SQL注入.
然而,如果查询的其他部分是由未转义的输入来构建的,则仍存在SQL注入的风险.
预处理语句如此有用,以至于它们唯一的特性是在驱动程序不支持的时候,PDO将模拟处理.
这样可以确保不管数据库是否具有这样的功能,都可以确保应用程序可以用相同的数据访问模式.
<code><?php $sth = $dbh->prepare('SELECT name, colour, calories FROM fruit WHERE calories bindParam(':calories', $calories, PDO::PARAM_INT); $sth->bindParam(':colour', $colour, PDO::PARAM_STR, 12); $sth->execute(); </code>
上面参与查询的变量$calories被绑定为整型,$colour被绑定为长度为12个字符的字符串型.
MySQLi里同样提供有像PDO bindParam一样的bind_param,这时就不需要用addslashes,mysqli_real_escape_string之类的函数了,也不需要依赖magic_quotes_gpc配置了(该配置从PHP5.4开始已经被移除).
用PDO操作MySQL时注意禁用模拟预处理,这样才会使用真正的预处理,这样才能确保程序先发送SQL模板给MySQL编译,然后再传参数过去执行,这样可以确保这些参数不被SQL注入.MySQLi扩展的预处理默认就是真正的预处理.
<code>$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); </code>
这些都可以通过MySQL的general_log日志或者WireShark观察到.
<code><?php $stmt = $mysqli->prepare('SELECT * FROM users WHERE username = ?'); $stmt->bind_param('s', $_GET['username']); //s表示用户名被绑定为字符串型,整型用i. $stmt->execute(); </code>
对于一些要求是整型的参数,其实还可以直接用intval($calories)
拿到整型值.
如果你要验证和过滤一些用户输入的数据,又不想自己写正则表达式,那就可以用filter_input/filter_var函数,比如验证邮箱,IP等:
http://php.net/manual/zh/filter.filters.php
我来回答个无关的:
Are PDO prepared statements sufficient to prevent SQL injection?
PDO是否可以防住SQL注入。
建议你先看看
joomla-framework的input类库,地址在这里
或者先把joomla-framework的input类库在你的代码中使用(前期就不要考虑性能之类的问题),先搞明白对于$_GET(包括$_POST、$_FILES、$_COOKIE等)要进行怎样的处理,然后在以后的使用过程中自己选择是否实现简单版本。
为什么这么普遍的问题,php不能做一个统一的控制呢 :(
为什么不用PDO?
防止注入的话PDO就可以了,防止XSS的话建议使用安全厂商提供的一些XSS过滤脚本在输出时过滤.
我觉得数据类型要控制好,另外就是防止SQL注入攻击了。
还有就是最好用Session保存,别一样的内容总提交做SQL。
什么是$_GET? $_GET是一类通过 URL 参数传递给当前脚本的变量的数组。而$HTTP_GET_VARS 包含相同的信息, 但它不是一个超全局变量。 (注意 $HTTP_GET_VARS 和 $_GET 是不同的变量,PHP 处理它们的方式不同).
那么$_GET()的安全考虑主要是在获取值的时候进行的安全考虑的,在进行数据的过滤时防止XSS攻击,PDO攻击中的SQL注入等安全问题,这些都是通过$_GET()传递值来威胁到系统安全的,还有敏感数据最好进行加密处理,不要太过于明显的暴露,以防被劫持利用等危险。
那么一些简单的数据过滤的方式有:
对于XXS攻击(跨站脚本攻击)都是由于对用户的输入没有进行严格的过滤造成的,所以我们必须在所有数据进入我们的网站和数据库之前把可能的危险拦截。针对非法的HTML代码包括单双引号等,可以使用htmlentities()来进行数据过滤。 但是要注意一点,htmlentities()默认编码为 ISO-8859-1,如果你的非法脚本编码为其它,那么可能无法过滤掉,同时浏览器却可以识别和执行。
对于PDO攻击中的SQL注入,在php编写程序中,我们可以使用类似如下的PDO预处理绑定语句来有效的防止sql注入问题:
<code>$stmt = $dbh -> prepare ( "INSERT INTO REGISTRY (name, value) VALUES (:name, :value)" ); $stmt -> bindParam ( ':name' , $name ); $stmt -> bindParam ( ':value' , $value ); $name = 'one' ; $value = 1 ; $stmt -> execute (); </code>
或者使用?号占位符来达到相同的效果:
<code>$stmt = $dbh -> prepare ( "INSERT INTO REGISTRY (name, value) VALUES (?, ?)" ); </code>
防不住xss。这个说的是$_GET这个方法,你要是封装好了了那还说这个干嘛?

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

會話劫持可以通過以下步驟實現:1.獲取會話ID,2.使用會話ID,3.保持會話活躍。在PHP中防範會話劫持的方法包括:1.使用session_regenerate_id()函數重新生成會話ID,2.通過數據庫存儲會話數據,3.確保所有會話數據通過HTTPS傳輸。

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

PHP在電子商務、內容管理系統和API開發中廣泛應用。 1)電子商務:用於購物車功能和支付處理。 2)內容管理系統:用於動態內容生成和用戶管理。 3)API開發:用於RESTfulAPI開發和API安全性。通過性能優化和最佳實踐,PHP應用的效率和可維護性得以提升。

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

PHP仍然具有活力,其在現代編程領域中依然佔據重要地位。 1)PHP的簡單易學和強大社區支持使其在Web開發中廣泛應用;2)其靈活性和穩定性使其在處理Web表單、數據庫操作和文件處理等方面表現出色;3)PHP不斷進化和優化,適用於初學者和經驗豐富的開發者。

在PHP8 中,match表達式是一種新的控制結構,用於根據表達式的值返回不同的結果。 1)它類似於switch語句,但返回值而非執行語句塊。 2)match表達式使用嚴格比較(===),提升了安全性。 3)它避免了switch語句中可能的break遺漏問題,增強了代碼的簡潔性和可讀性。

XSS是一種通過注入惡意腳本在用戶瀏覽器中執行的攻擊。在PHP中使用htmlspecialchars函數可以有效防範XSS攻擊:1)htmlspecialchars將特殊字符轉換為HTML實體,防止瀏覽器將其解釋為代碼;2)在HTML屬性中使用時,需使用ENT_QUOTES標誌轉義引號;3)結合其他安全措施,如輸入驗證和輸出編碼,形成多層次防護。
