web安全浅析
就之前本人主持开发的金融产品所遇到的安全问题,设计部分请参见:http://www.cnblogs.com/shenliang123/p/3835072.html
这里就部分web安全防护就简单的交流:
1.1系统安全
1.1.1 客户端脚本安全
(1)跨站脚本攻击(XSS):
XSS攻击,通常指黑客通过“html注入” 篡改了网页,插入了恶意的脚本,从而在用户浏览网页的时候,控制用户浏览器的一种攻击。
最常见的XSS攻击就是通过读取浏览器的Cookie对象,从而发起“cookie劫持”,当前用户的登录凭证存储于服务器的session中,而在浏览器中是以cookie的形式进行存储的,cookie被劫持后,意味着攻击者可以不通过密码而直接登录系统。我们也可以直接在浏览器中输入脚本javascript:alert(document.cookie)来获取当前cookie值。
目前防止“cookie劫持”的方法大致有:a. 输入检查,使用filter来过滤敏感的关键字;b. 将cookie与用户ip地址进行绑定;c. 为cookie植入HttpOnly标识。
本系统采用的是第3种方式:为cookie植入HttpOnly标识。一旦这个HttpOnly被设置,你在浏览器的 document对象中就看不到Cookie了,而浏览器在浏览的时候不受任何影响,因为Cookie会被放在浏览器头中发送出去(包括ajax的时 候),应用程序也一般不会在js里操作这些敏感Cookie的,对于一些敏感的Cookie我们采用HttpOnly,对于一些需要在应用程序中用js操作的cookie我们就不予设置,这样就保障了Cookie信息的安全也保证了应用。
具体代码实现:在web服务器tomcat的配置文件server.xml中添加:
<Context docBase="E:\tomcat\apache-tomcat-6.0.24/webapps/netcredit" path="/netcredit" reloadable="false" useHttpOnly="true"/>
或者在项目的web.xml 配置如下:
<session-config>
<cookie-config>
<http-only>true</http-only>
</cookie-config>
</session-config>

图1-1 浏览器cookie截图
(2)跨站点请求伪造(CSRF):
本系统采用了对抗CSRF最有效的防御方法:验证码。
1.1.2 服务器端应用安全
服务器端的安全相对于客户端来说显的更加的重要,因为服务器端的某个安全漏洞可能带来的是致命的危险。因此我们对服务器端的安全更为的慎重和重视。
(1)SQL注入攻击:
Sql注入的的两个关键条件:第一个是用户能够控制输入;第二个是原本程序要执行的代码,拼接了用户输入的数据。
根据上面两个关键条件,系统为防止sql注入使用了以下方法:
第一:使用预编译语句,这也是防御sql注入最有效的方法,完全摒弃代码的直接拼接所带来的危险。
public List<T> findByPage(final String hql, final Object[] values, final int offset,
final int pageSize) {
List<T> list = getHibernateTemplate().executeFind(new HibernateCallback(){
public Object doInHibernate(Session session)
throws HibernateException, SQLException{
Query query=session.createQuery(hql);
for (int i = 0 ; i < values.length ; i++){
query.setParameter( i, values[i]);
}
if(!(offset==0 && pageSize==0)){
query.setFirstResult(offset).setMaxResults(pageSize);
}
List<T> result = query.list();
return result;
}
});
return list;
}
第二:关闭web服务器的错误回显功能,这样可以防止攻击者对系统进行攻击后,通过回显的详细错误信息对攻击内容进行调整,对攻击者提供极大的便利。我们在项目的web.xml文件中添加以下示例代码:
<error-page>
<error-code>400</error-code>
<location>/error400.jsp</location>
</error-page>
。。。。。
第三:数据库自身使用最小权限原则,系统程序不使用最高权限的root对数据库进行连接,而是使用能满足系统需求的最小权限账户进行数据库连接,而且多个数据库之间使用不同的账户,保证每个数据库都有独立对应的账户。
(2)文件上传漏洞:
文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过脚本文件获得了执行服务器端命令的能力,这样将会导致严重的后果。而本系统内涉及到大量的图片格式文件上传,因此对于上传问题的处理非常谨慎,并尽可能的达到安全标准。
本系统主要通过对上传文件详细的格式验证:
第一步:通过后缀名来简单判断文件的格式。
public static boolean isPicture(String pInput) throws Exception{
// 获得文件后缀名
String tmpName = pInput.substring(pInput.lastIndexOf(".") + 1,
pInput.length());
// 声明图片后缀名数组
String imgeArray [] = { "jpg", "png", "jpeg" };
// 遍历名称数组
for(int i = 0; i<imgeArray.length;i++){
// 判断符合全部类型的场合
if(imgeArray [i].equals(tmpName.toLowerCase())){
return true;
}
}
return false;
}
第二步:通过读取文件的前两个字符进行对比,例如png格式图片的前两个字符为8950,而jpg格式的图片前两个字符为ffd8。
public static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder();
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;//byte to int
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
第三步:如果上传的为图片,则获取相应的高度和宽度,如果存在相应的宽度和高度则可认为上传的是图片。
public static boolean isImage(File imageFile) {
if (!imageFile.exists()) {
return false;
}
Image img = null;
try {
img = ImageIO.read(imageFile);
if (img == null || img.getWidth(null) <= 0 || img.getHeight(null) <= 0) {
return false;
}
return true;
} catch (Exception e) {
return false;
} finally {
img = null;
}
}
如果以上验证都成功通过,本系统在对文件进行存储时会将文件名进行重命名处理,并且设置相应的web服务器,默认不显示目录。因为文件上传如果需要执行代码,则需要用户能够访问到这个文件,因此使用随机数改写了文件名,将极大的增加攻击的成本,甚至根本无法成功实施攻击。
//对文件的名称进行重命名
StringBuilder sb = new StringBuilder().append(new Date().getTime()).append(".").append(fileMsg[1]);
(3)认证与会话管理:
认证实际上就是一个验证凭证的过程,因此我们对登录密码有着严格的规定:密码要求长度在8位以上并且包含字母,数字,符号两种以上的组合。并将密码加密后再进行数据库的存储。为防止一些暴力破解手段,又出于用户体验的考虑,本系统采用用户登录时默认不进行验证码的输入,但密码三次输入失败后需要进行验证码的输入,连续五次输入错误后,该用户的ip地址将被封,可以在一段时间后自动解封或者后台管理员手动解封。涉及到系统资金有关的操作,例如投标,我们还需要用户设置并提供支付密码,而提现等操作我们还配备短信验证码功能。以此来增强验证的可靠性。
当用户登录完成后,在服务器端会创建一个新的会话(Session),会话中保存着用户的状态和相关信息,服务器端维护所有在线用户的Session,而浏览器则是将SessionId加密后保存在cookie中,这里就出现了前面提到了“cookie劫持“问题,本系统通过将cookie中植入HttpOnly成功解决该问题。本系统还给Session设置了一个有效时间,来保证在有效时间后Session将自动销毁,以防止Session长连接所带来的安全隐患。在web.xml文件中添加以下代码:
<session-config>
<session-timeout>30</session-timeout>
</session-config>
(4)访问控制:
访问控制实际上就是建立用户和权限之间的对应关系,本系统采用的是“基于角色的访问控制”,根据相应功能模块的划分相应的权限,并将相应的权限分配给不同的角色,再将角色分配给用户,用户就拥有了该角色所持有的权限。具体的设计与实现分析请见1.2 Annotation和Struts2拦截器实现基于角色的垂直权限管理。
1.2 Annotation和Struts2拦截器实现基于角色的垂直权限管理
1.2.1 模块的设计
以下是本系统的垂直权限管理模块的物理模型设计:

图1-2 权限管理模块物理模型
管理员与角色之间是多对多的关系,这样可以实现为一个管理员分配多个角色进行管理,而角色与权限之间也是多对多的关系,权限是根据功能模块进行划分的,使得角色可以进行细粒度的权限分配。
4.3.2 模块的代码实现
首先声明一个注解类,该注解类是自定义的,根据我们需要的实现的功能进行相应注解的定义,使得在之后需要注释的方法上使用相应注解,代码如下:
@Retention(RetentionPolicy.RUNTIME) //注解的存活时间,整个运行时都存活
@Target(ElementType.METHOD) //此注解表示只能在方法上面有效
public @interface Permission {
/** 模块名 **/
String model();
/** 权限值 **/
String privilegeValue();
/*用于区分当前页面是dialog还是navTab*/
String targetType();
}
然后定义相应的拦截器类,并在struts2的配置文件struts.xml中进行拦截器的配置,为相应需要的类进行拦截验证,定义拦截器部分的核心代码如下:
/**
* 校验控制在方法上的拦截
*/
@SuppressWarnings("unchecked")
public boolean validate(Admin admin, ActionInvocation invocation, List<Role> roleList,
Map session) {
String methodName= "execute"; //定义默认的访问方法
Method currentMethod = null;
methodName = invocation.getProxy().getMethod(); //通过actionProxy,得到当前正在执行的方法名
try {
//利用反射,通过方法名称得到具体的方法
currentMethod = invocation.getProxy().getAction().getClass().getMethod(methodName, new Class[] {});
} catch (Exception e) {
e.printStackTrace();
}
if (currentMethod != null && currentMethod.isAnnotationPresent(Permission.class)) {
//得到方法上的Permission注解
Permission permission = currentMethod.getAnnotation(Permission.class);
//通过Permission注解构造出系统权限
Systemprivilege privilege = new Systemprivilege(new SystemprivilegeId(permission.privilegeValue(), permission.model()));
session.put("targetType", permission.targetType());
//迭代用户所具有的具体权限,如果包含,返回true
for (Role role : roleList) {
RolePrivilege rolePrivilege = new RolePrivilege(privilege, role);
if (role.getRolePrivileges().contains(rolePrivilege)) {
return true;
}
}
return false;
}
return true;
}
本系统需要向权限表中添加相应的功能模块,为了有一个比较细的粒度,模块将根据功能进行划分,而权限则根据按钮来进行细分:

图1-3 数据库截图
在定义了相应的权限后,我们需要在相应的执行方法体上面进行注释,使得拦截器进行拦截验证时能根据注释获取该执行方法体的模块和权限类型:
@Permission(model="recharge", privilegeValue="recharge" ,targetType="dialog")
4.3.3 模块的实现效果
首先添加相应的员工:

然后新增相应的角色,填写角色名称并勾取相应的权限:

然后新增相应的用户,勾选该用户相应的角色,可以选择多个角色,并且选择相应用户对应的员工:

web安全浅析的更多相关文章
- 【Web】浅析JQuery的apply(), call(), bind()方法
原文地址:https://blog.csdn.net/whuzxq/article/details/64166253 由于在理解this的用法的时候多次出现了这几个方法,个人对这几个方法理解的不是很透 ...
- odoo开发笔记 -- odoo web机制浅析
http://blog.csdn.net/M0relia/article/details/39025947
- 移动端web开发 浅析
1. viewport ① viewport在移动端承载网页的区域:具有默认格式 ②设置viewport属性,适配移动端设备 主流设置: <meta name = ”viewport” cont ...
- web全套资料 干货满满 各种文章详解
sql注入l MySqlMySQL False注入及技巧总结MySQL 注入攻击与防御sql注入学习总结SQL注入防御与绕过的几种姿势MySQL偏门技巧mysql注入可报错时爆表名.字段名.库名高级S ...
- ref:web security最新学习资料收集
ref:https://chybeta.github.io/2017/08/19/Web-Security-Learning/ ref:https://github.com/CHYbeta/Web-S ...
- 前端每周清单第 49 期:Webpack 4 Beta 尝鲜,React Windowing 与 setState 分析,Web Worker 实战
前端每周清单专注前端领域内容,以对外文资料的搜集为主,帮助开发者了解一周前端热点:分为新闻热点.开发教程.工程实践.深度阅读.开源项目.巅峰人生等栏目.欢迎关注[前端之巅]微信公众号(ID: fron ...
- odoo11登录之后返回的session信息分析
{ "id": null, "jsonrpc": "2.0", "result": { "web_tours& ...
- Web-Security-Learning
Web Security sql注入 MySql MySQL False 注入及技巧总结 MySQL 注入攻击与防御 sql注入学习总结 SQL注入防御与绕过的几种姿势 MySQL偏门技巧 mysql ...
- http协议和web应用有状态和无状态浅析
http协议和web应用有状态和无状态浅析 (2013-10-14 10:38:06) 转载▼ 标签: it 我们通常说的web应用程序的无状态性的含义是什么呢? 直观的说,“每次的请求都是独立的 ...
随机推荐
- 先说IEnumerable,我们每天用的foreach你真的懂它吗?
我们先思考几个问题: 为什么在foreach中不能修改item的值? 要实现foreach需要满足什么条件? 为什么Linq to Object中要返回IEnumerable? 接下来,先开始我们的正 ...
- Spring基于AOP的事务管理
Spring基于AOP的事务管理 事务 事务是一系列动作,这一系列动作综合在一起组成一个完整的工作单元,如果有任何一个动作执行失败,那么事务 ...
- SuperMap iClient for JavaScript 新手入门
地理信息系统(英语:Geographic Information System,缩写:GIS)是一门综合性学科,结合地理学与地图学,已经广泛的应用在不同的领域,是用于输入.存储.查询.分析和显示地理数 ...
- [OpenGL超级宝典]专栏前言
我小时候的梦想呢,是做宇航员或者科学家或者是做一款属于自己的游戏,后来前面两个梦想都没有实现,于是我就来实现我的第三个梦想了,,,我呢,也算是零基础,因为我的专业是物联网工程,这个专业覆盖面之广,简直 ...
- CSS 3 学习——渐变
通过CSS渐变创建的是一个没有固定比例和固定尺寸的<image>类型,也就是说是一张图片,这张图片的尺寸由所应用的元素的相关信息决定.凡是支持图片类型的CSS属性都可以设置渐变,而支持颜色 ...
- Java类变量和成员变量初始化过程
一.类的初始化 对于类的初始化:类的初始化一般只初始化一次,类的初始化主要是初始化静态成员变量. 类的编译决定了类的初始化过程. 编译器生成的class文件主要对定义在源文件中的类进行了如下的更改: ...
- maven 中snapshot版本和release版本的区别
maven中的仓库分为两种,snapshot快照仓库和release发布仓库.snapshot快照仓库用于保存开发过程中的不稳定版本,release正式仓库则是用来保存稳定的发行版本.定义一个组件/模 ...
- Mysql - 增删改
因为项目原因, mysql用了两年了, 但是一直都未曾去总结过. 最近也是领导让总结项目, 才想起把mysql的使用小结一下. 一. Create 1. 单条插入, sql格式: insert int ...
- Spring MVC重定向和转发以及异常处理
SpringMVC核心技术---转发和重定向 当处理器对请求处理完毕后,向其他资源进行跳转时,有两种跳转方式:请求转发与重定向.而根据要跳转的资源类型,又可分为两类:跳转到页面与跳转到其他处理器.对于 ...
- Eclipse常用设置
用惯了VS,再回过去用Eclipse真是一件痛苦的事.so,在这里记录下使用过程中的一些设置以做备忘. 1.代码自动提示 在我们忘记方法名或者想偷懒时,代码自动提示很管用.不过Eclipse默认是输入 ...