内容简介:开发 WEB 应用的同学应该不少,不知道大家平时开发中,有没有关注过应用开发的「安全问题」。所谓安全问题,就是开发中不要留下漏洞,给入侵者破坏者机会。比如,我们常挂在嘴边的安全问题有 「SQL 注入」,为了防止出现问题,一般都会使用预编译的 SQL,而不是拼接SQL,以此来保证安全。再比如,我们一个允许用户输入的文本框中,会禁用代码的渲染,比如像
开发 WEB 应用的同学应该不少,不知道大家平时开发中,有没有关注过应用开发的「安全问题」。
所谓安全问题,就是开发中不要留下漏洞,给入侵者破坏者机会。
比如,我们常挂在嘴边的安全问题有 「SQL 注入」,为了防止出现问题,一般都会使用预编译的 SQL,而不是拼接SQL,以此来保证安全。再比如,我们一个允许用户输入的文本框中,会禁用代码的渲染,比如像
<script> alert(“hello”);</script> 这种会被做为纯文本对待。
类似需要注意的问题有很多,如果我们不留意,就会容易造成安全问题。
不过有些「洞」,是你我开发中不曾留意的。或者说你只有先意识到有这一类问题需要注意,开发的时候才会把它堵上。
比如最近开发的一个WEB 应用,公司做安全的同事帮忙看了看,就给报了几个问题。
这里简单总结和各位一起分享下,欢迎留言讨论。
同事给指出的问题主要有两个:
- 不安全的 TRACE、OPTIONS 等方法未禁用
- 用户提交的信息里, 可以包含第三方链接,容易出现钓鱼问题 。
问题一:
通过TRACE、OPTIONS 方法,可以暴露不少关键信息。
我们知道,HTTP 请求里可以使用不同的 Method 来实现不同的请求功能, 比如常见的 GET/POST/PUT/DELETE 。除此之外还有一些,比如 TRACE/OPTIONS 等,每种请求简单描述如下。详细描述,可以查看RFC2616(https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html)
GET 请求指定的页面信息,并返回实体主体。 HEAD 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头 POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。 PUT 从客户端向服务器传送的数据取代指定的文档的内容。 DELETE 请求服务器删除指定的页面。 CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。 OPTIONS 允许客户端查看服务器的可用内容。 TRACE 回显服务器收到的请求,主要用于测试或诊断
从上面内容可以看出,TRACE 方法,OPTIONS方法,一般都会返回大量和实际业务处理无关的内容,如果开放会暴露许多服务器的关键信息,可能引出安全问题。
处理方式:
对于传统的web项目, 直接在web.xml 里增加安全限制「security-constraint」即可。
对于 Spring Boot应用,如果是使用 Tomcat做为容器,可以通过声明独立的配置,实现类似web.xml的效果:
web.xml的配置
<security-constraint> <web-resource-collection> <web-resource-name>restricted methods</web-resource-name> <url-pattern>/*</url-pattern> <http-method>PUT</http-method> <http-method>DELETE</http-method> <http-method>HEAD</http-method> <http-method>OPTIONS</http-method> <http-method>TRACE</http-method> </web-resource-collection> <auth-constraint/> </security-constraint>
Spring Boot 应用中的配置
@Configuration public class TomcatCustomizer implements EmbeddedServletContainerCustomizer { @Override public void customize(ConfigurableEmbeddedServletContainer container) { TomcatEmbeddedServletContainerFactory tomcat = (TomcatEmbeddedServletContainerFactory) container; tomcat.setSessionTimeout(8, TimeUnit.HOURS); tomcat.addContextCustomizers(new ContextSecurityCustomizer()); } private static class ContextSecurityCustomizer implements TomcatContextCustomizer { @Override public void customize(Context context) { SecurityConstraint constraint = new SecurityConstraint(); SecurityCollection securityCollection = new SecurityCollection(); securityCollection.setName("restricted_methods"); securityCollection.addPattern("/*"); securityCollection.addOmittedMethod(HttpMethod.POST.toString()); securityCollection.addOmittedMethod(HttpMethod.GET.toString()); constraint.addCollection(securityCollection); constraint.setAuthConstraint(true); context.addConstraint(constraint); } } }
如果使用 Jetty,配置方式也类似。
当然,如果想要做到不与容器依赖紧耦合,还可以自己定义Filter,然后在请求中判断请求头里的 Method 如果是不允许的方法,可以直接返回错误。
问题二:
具体是这样,我们的应用里允许用户上传图片。上传的图片会保存到对象存储中,然后返回一个URL,最后用户完整的信息里,是直接存储了一个URL。但是,我们看到,整个上传到提交的过程,并不是一步完成的,所以,用户可以自行构造这个提交的请求, 并将图片的URL,替换成任意链接 。
这个时候,在页面再次渲染时,是会请求图片URL来展示图片的。如果是一个恶意的第三方钓鱼链接,容易造成盗取用户信息等安全问题。
处理方式:
这个问题,一般在后端对提交的内容进行检验,如果有「不符合规定」的域名,就报错。一般是维护一个白名单,判断URL信息在不在白名单中。
判断一个URL的后缀,你一般用什么方式呢?正则表达式?字符串截取?
这里有个方式供参考,可以直接取出我们预期的域名后缀:
String host = ""; URL fullUrl = null; try { fullUrl = new URL("http://blog.tomcat8080.com/abc=def"); } catch (MalformedURLException e) { e.printStackTrace(); } host = fullUrl.getHost(); InternetDomainName domainName = InternetDomainName.from(host); String top = domainName.topPrivateDomain().toString();
这些安全技术,仿佛是和WEB开发平行的一个领域,属于另一个工种。这些不属于架构,与 设计模式 无关,也不在数据库设计、虚拟机优化的范围内,但是,也是我们不得不去认真了解和重视的。可能不需要安全工程师那么深入,但一些常见的安全问题要了解,类似于一个 「CheatSheet」避免自己开发的时候暴露,保证我们开发的应用安全,不被攻击和泄露数据。对于WEB安全,我还是 too young了,欢迎各位留言述说自己的经验。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 袜子商店应用:一个云原生参照应用
- Android 应用中跳转到应用市场评分
- 授之以渔-运维平台应用模块一(应用树篇)
- OAM(开放应用模型)——定义云原生应用标准的野望
- ChromeOS 终端应用程序暗示其即将支持 Linux 应用
- Android应用之间数据的交互(一)获取系统应用的数据
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。