WEB应用安全

作者: wencst 分类: JAVA,架构设计,程序设计 发布时间: 2019-02-19 17:30 阅读: 306 次

开发 WEB 应用的同学应该不少,不知道大家平时开发中,有没有关注过应用开发的「安全问题」。

所谓安全问题,就是开发中不要留下漏洞,给入侵者破坏者机会。

比如,我们常挂在嘴边的安全问题有 「SQL 注入」,为了防止出现问题,一般都会使用预编译的 SQL,而不是拼接SQL,以此来保证安全。再比如,我们一个允许用户输入的文本框中,会禁用代码的渲染,比如像

<script>  alert(“hello”);</script>  这种会被做为纯文本对待。

类似需要注意的问题有很多,如果我们不留意,就会容易造成安全问题。

不过有些「洞」,是你我开发中不曾留意的。或者说你只有先意识到有这一类问题需要注意,开发的时候才会把它堵上。

比如最近开发的一个WEB 应用,公司做安全的同事帮忙看了看,就给报了几个问题。

这里简单总结和各位一起分享下,欢迎留言讨论。

同事给指出的问题主要有两个:

  1. 不安全的 TRACE、OPTIONS 等方法未禁用
  2. 用户提交的信息里,可以包含第三方链接,容易出现钓鱼问题

问题一:

通过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了,欢迎各位留言述说自己的经验。

如果文章对您有用,扫一下支付宝的红包,不胜感激!

kubernetes集群离线安装包, 仅需三步, HA安装:http://store.lameleg.com?referrer=wencst



Leave a Reply