热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

php安全-PHP如何安全地使用$_GET

本人新手,在《PHP安全编码》中提到“不要直接使用$_GET”,同时又提到“可以尝试在php.ini中开启magic_quotes_gpc,这样对于所有由用户GET、POST、COOKIE中传入的特殊字符都会转义”,我很纠结,是否开启magic_quote...
本人新手,在《PHP安全编码》中提到“不要直接使用$_GET”,同时又提到“可以尝试在php.ini中开启magic_quotes_gpc,这样对于所有由用户GET、POST、COOKIE中传入的特殊字符都会转义”,我很纠结,是否开启magic_quotes_gpc就可以直接使用$_GET?

如下面例子中的代码本人感觉很不安全,因为没有做验证,但又不知道如何改进,希望大神能帮忙,谢谢。

回复内容:

本人新手,在《PHP安全编码》中提到“不要直接使用$_GET”,同时又提到“可以尝试在php.ini中开启magic_quotes_gpc,这样对于所有由用户GET、POST、COOKIE中传入的特殊字符都会转义”,我很纠结,是否开启magic_quotes_gpc就可以直接使用$_GET?

如下面例子中的代码本人感觉很不安全,因为没有做验证,但又不知道如何改进,希望大神能帮忙,谢谢。

你是想要filter_input函数,多看手册:

http://www.w3school.com.cn/php/func_filter_input.asp

纯数字的参数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;
     }

我一般都对$_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拼接是不安全的,如何避免?

例如:

sqlselect * from user where username= "$_GET['username']"

如果用户提交的username 为

sql" 0 or true or username ="

那么就会变成这样:

sqlselect * from user where username = "0" or true  or username=""

那么会返回所有的用户记录。当然这里只是粗暴的举了一个例子。实际上要做XSS要熟知代码或者猜测到运行的逻辑等了解很多东西。

最简单的过滤方法是使用 mysql_real_escape_string 函数

至于 magic_quotes,是php最失败的一个改进,现已废弃,就算是低版本的PHP也一定要关闭它。

如果 $_GET
首先判断是否为空
然后对值进行判断
举个例子:
只接受数字 那就使用 php自带函数 is_numeric

一般 GET 也只是传递某个标识
总之在数据库或其他操作之前 先验证 传过来的变量 是否为自己预期的值

可以先对post或者get请求过滤,php有内置函数进行过滤,然后在使用

同意二楼的要有一个过滤,不过只是系统自带的肯定不行,最好自己再根据情况做一个过滤等之类的处理。

防止XSS攻击,最简单粗暴的做法就是用htmlspecialchars把特殊字符(&,",',<,>)转换为HTML实体(&"&#039;<>)后输出.

防止XSS攻击,最复杂的就是自己写正则过滤,不过还好有HTMLPurifier库,除了能过滤XSS代码,还能把不完整的标签补全或者去掉.Yii框架也用到了这个XSS过滤库.
http://htmlpurifier.org/download

purify($html);

上面说的是防御XSS,下面说防御SQL注入:
PDO和MySQLi等都提供有绑定参数查询的功能,而绑定参数的目的就是防止SQL注入.
http://php.net/manual/zh/pdo.prepared-statements.php

很多更成熟的数据库都支持预处理语句的概念.
什么是预处理语句?可以把它看作是想要运行的SQL的一种编译过的模板,它可以使用变量参数进行定制.
预处理语句可以带来两大好处:
1.查询仅需解析(或预处理)一次,但可以用相同或不同的参数执行多次.
当查询准备好后,数据库将分析/编译/优化执行该查询的计划.
对于复杂的查询,此过程要花费较长的时间,如果需要以不同参数多次重复相同的查询,那么该过程将大大降低应用程序的速度.
通过使用预处理语句,可以避免重复分析/编译/优化周期.
简言之,预处理语句占用更少的资源,因而运行得更快.
2.提供给预处理语句的参数不需要用引号括起来,驱动程序会自动处理.
如果应用程序只使用预处理语句,可以确保不会发生SQL注入.
然而,如果查询的其他部分是由未转义的输入来构建的,则仍存在SQL注入的风险.

预处理语句如此有用,以至于它们唯一的特性是在驱动程序不支持的时候,PDO将模拟处理.
这样可以确保不管数据库是否具有这样的功能,都可以确保应用程序可以用相同的数据访问模式.

prepare('SELECT name, colour, calories FROM fruit WHERE calories <:calories AND colour = :colour');
$sth->bindParam(':calories', $calories, PDO::PARAM_INT);
$sth->bindParam(':colour', $colour, PDO::PARAM_STR, 12);
$sth->execute();

上面参与查询的变量$calories被绑定为整型,$colour被绑定为长度为12个字符的字符串型.
MySQLi里同样提供有像PDO bindParam一样的bind_param,这时就不需要用addslashes,mysqli_real_escape_string之类的函数了,也不需要依赖magic_quotes_gpc配置了(该配置从PHP5.4开始已经被移除).
用PDO操作MySQL时注意禁用模拟预处理,这样才会使用真正的预处理,这样才能确保程序先发送SQL模板给MySQL编译,然后再传参数过去执行,这样可以确保这些参数不被SQL注入.MySQLi扩展的预处理默认就是真正的预处理.

$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

这些都可以通过MySQL的general_log日志或者WireShark观察到.

prepare('SELECT * FROM users WHERE username = ?');
$stmt->bind_param('s', $_GET['username']); //s表示用户名被绑定为字符串型,整型用i.
$stmt->execute();

对于一些要求是整型的参数,其实还可以直接用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注入问题:

$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 ();

或者使用?号占位符来达到相同的效果:

$stmt  =  $dbh -> prepare ( "INSERT INTO REGISTRY (name, value) VALUES (?, ?)" );

防不住xss。这个说的是$_GET这个方法,你要是封装好了了那还说这个干嘛?

推荐阅读
  • 背景应用安全领域,各类攻击长久以来都危害着互联网上的应用,在web应用安全风险中,各类注入、跨站等攻击仍然占据着较前的位置。WAF(Web应用防火墙)正是为防御和阻断这类攻击而存在 ... [详细]
  • 浅解XXE与Portswigger Web Sec
    XXE与PortswiggerWebSec​相关链接:​博客园​安全脉搏​FreeBuf​XML的全称为XML外部实体注入,在学习的过程中发现有回显的XXE并不多,而 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 延迟注入工具(python)的SQL脚本
    本文介绍了一个延迟注入工具(python)的SQL脚本,包括使用urllib2、time、socket、threading、requests等模块实现延迟注入的方法。该工具可以通过构造特定的URL来进行注入测试,并通过延迟时间来判断注入是否成功。 ... [详细]
  • 本文介绍了绕过WAF的XSS检测机制的方法,包括确定payload结构、测试和混淆。同时提出了一种构建XSS payload的方法,该payload与安全机制使用的正则表达式不匹配。通过清理用户输入、转义输出、使用文档对象模型(DOM)接收器和源、实施适当的跨域资源共享(CORS)策略和其他安全策略,可以有效阻止XSS漏洞。但是,WAF或自定义过滤器仍然被广泛使用来增加安全性。本文的方法可以绕过这种安全机制,构建与正则表达式不匹配的XSS payload。 ... [详细]
  • 本文介绍了一个免费的asp.net控件,该控件具备数据显示、录入、更新、删除等功能。它比datagrid更易用、更实用,同时具备多种功能,例如属性设置、数据排序、字段类型格式化显示、密码字段支持、图像字段上传和生成缩略图等。此外,它还提供了数据验证、日期选择器、数字选择器等功能,以及防止注入攻击、非本页提交和自动分页技术等安全性和性能优化功能。最后,该控件还支持字段值合计和数据导出功能。总之,该控件功能强大且免费,适用于asp.net开发。 ... [详细]
  • 本文介绍了互联网思维中的三个段子,涵盖了餐饮行业、淘品牌和创业企业的案例。通过这些案例,探讨了互联网思维的九大分类和十九条法则。其中包括雕爷牛腩餐厅的成功经验,三只松鼠淘品牌的包装策略以及一家创业企业的销售额增长情况。这些案例展示了互联网思维在不同领域的应用和成功之道。 ... [详细]
  • 弹性云服务器ECS弹性云服务器(ElasticCloudServer)是一种可随时自助获取、可弹性伸缩的云服务器,帮助用户打造可靠、安全、灵活、高效的应用环境 ... [详细]
  • 跨站的艺术XSS Fuzzing 的技巧
    作者|张祖优(Fooying)腾讯云云鼎实验室对于XSS的漏洞挖掘过程,其实就是一个使用Payload不断测试和调整再测试的过程,这个过程我们把它叫做F ... [详细]
  • 2月4日每日安全热点节日期间某企远程办公遭XRed攻击 ... [详细]
  • JVM(三)虚拟机栈 多合一总述
    虚拟机栈概述虚拟机栈出现背景:由于跨平台性的设计,Java的指令都是根据栈来设计的。不同CPU架构不同,所以不能设计为基于寄存器的跨平台的优点:指令集小,编译器容易实现,缺点是性能 ... [详细]
  • 通过存储型XSS漏洞获取目标用户本地私钥信息
    运维|安全存储型XSS漏洞,目标用户,本地,私钥信息运维-安全舍得网源码,vscode代码检查工具,ubuntu壁纸修改,tomcat网页部署项目,爬虫枯木,php采集文件,马鞍山 ... [详细]
author-avatar
霹靂一頁書_629
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有