修复HTTP动词篡改导致的认证旁路问题的方法

这篇具有很好参考价值的文章主要介绍了修复HTTP动词篡改导致的认证旁路问题的方法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文于2016年4月完成,发布在个人博客网站上。 考虑个人博客因某种原因无法修复,于是在博客园安家,之前发布的文章逐步搬迁过来。


诡异的问题

分析AppScan扫描报告的时候,发现报告里提示“HTTP动词篡改导致的认证旁路”,一个名字很长,很怪异的问题。咨询度娘没有获取到必要的信息,于是只好按照AppScan报告里给出的重现步骤,实地操作来看看。

AppScan给出的复现步骤很简单,如下:

  1. 使用burpsuite拦截浏览器发出的HTTP请求,如下为样例:

     GET /index.jsp HTTP/1.1
     Host: 127.0.0.1:8080
     Cache-Control: max-age=0
     Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
     Upgrade-Insecure-Requests: 1
     User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36
     Accept-Encoding: gzip, deflate, sdch
     Accept-Language: zh-CN,zh;q=0.8
     Connection: close
    
  2. 修改HTTP方法,比如把GET修改为BOGUS,然后点击Forward,把请求转发给Web服务器。

     BOGUS /index.jsp HTTP/1.1
     Host: 127.0.0.1:8080
     Cache-Control: max-age=0
     Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
     Upgrade-Insecure-Requests: 1
     User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36
     Accept-Encoding: gzip, deflate, sdch
     Accept-Language: zh-CN,zh;q=0.8
     Connection: close
    
  3. 令人大跌眼镜的事情发生了,Web服务器居然返回了HTTP 200,同时正确的返回了页面;

顿时让人有点小郁闷。按照产品线要求,当前所在项目使用的是平台部门基于Apache Tomcat 7.0.x源码做过加固的版本,按理说不该存在类似的安全问题。

对照Tomcat加固要求,重新检查了$CATALINA_BASE/conf/web.xml,确认其中包含了如下配置,这说明已经屏蔽了不安全的HTTP方法,应该是没有问题才对。

<security-constraint>
    <web-resource-collection>
        <http-method>HEAD</http-method>
        <http-method>PUT</http-method>
        <http-method>DELETE</http-method>
        <http-method>OPTIONS</http-method>
        <http-method>TRACE</http-method>
        <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name></role-name>
    </auth-constraint>
</security-constraint>

那么为什么AppScan扫描报告中出现了前述问题,Jackie一时有些想不明白。

项目的技术特点

当前所在项目使用了Spring+Struts2+iBatis,从技术组合上可以说非常传统,但在技术应用上存在很大不同,比如:

  • 浏览器请求页面时,使用通用Action将请求重定向至对应的jsp页面;
  • 页面上使用jQuery提供的ajax对象来加载呈现需要的数据;
  • 为了实现项目国际化的需求,要求所有对jsp的请求都需要经过通用Action的转发;
  • 页面代码使用Struts2的s标签来提取国际化信息;

这样的应用方式其实有不得以的苦衷,项目刚成立的时候,组内全是新人,对Struts2仅有名义上的理解,没有人在项目中实际运用中使用Struts2,另外项目进度压的很紧,没时间给大家去了解和学习;而使用ajax来实现页面与Web服务之间通信,实现和使用都简单,于是一直沿用至今。

Struts2的配置

Struts2在web.xml中的配置如下:

<filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

简化后的struts.xml配置文件,内容如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
	"http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
    <constant name="struts.enable.DynamicMethodInvocation" value="false" />
    <constant name="struts.devMode" value="true" />
    <constant name="struts.action.extension" value="jsp,action"/>
    <constant name="struts.ui.theme" value="java"></constant>
    <constant name="struts.objectFactory" value="spring" />
    <constant name="struts.i18n.encoding" value="UTF-8" />
    <package name="default" namespace="/" extends="struts-default">

        <interceptors>
            <interceptor-stack name="myStack">  
                <interceptor-ref name="basicStack"></interceptor-ref>  
            </interceptor-stack> 
        </interceptors>  
  
        <default-interceptor-ref name="myStack" /> 
        
        <global-results>
            <result name="error">/error.jsp</result>
        </global-results>

        <global-exception-mappings>
            <exception-mapping exception="java.lang.Exception" result="error"/>
        </global-exception-mappings>

        <action name="*" class="MainAction">
            <result name="success">{1}.jsp</result>
        </action>
    </package>
</struts>

通用Action类,简化后的MainAction代码如下

import com.opensymphony.xwork2.ActionSupport;

public class MainAction extends ActionSupport {
	private static final long serialVersionUID = 928135783255954591L;
	@Override
	public String execute() throws Exception {
		return ActionSupport.SUCCESS;
	}
}

从配置上讲,中规中矩,并没有什么特别的地方。

分析过程

访问jsp页面的流程

按照前述配置,当用户在浏览器地址栏里输入后缀为.jsp的url,敲击回车后,发生的事件如下:

  1. 由于在struts.xml文件中有如下配置,用户请求先被Struts2拦截;

     <constant name="struts.action.extension" value="jsp,action"/>
    
  2. 由于在struts.xml中有如下配置,请求会被转发给MainAction来处理;

     <action name="*" class="MainAction">
         <result name="success">{1}.jsp</result>
     </action>
    
  3. 由于MainAction类的execute方法只返回了"success",于是请求又被重定向回了对应的jsp页面;

     @Override
     public String execute() throws Exception {
     	return ActionSupport.SUCCESS;
     }
    
  4. 这时,对jsp页面的访问就由Tomcat接管了;

与9.0.x版本的Tomcat做对比

按照上面的分析,在第4步,如果Tomcat遇到了异常的请求方法,应该拒绝响应才是,不应当返回HTTP 200和页面。那么会不会是Tomcat实现存在问题?

平台发布加固后的Tomcat版本时并没有附带源码,于是从官网获取Tomcat发布的9.0.x版本做对比验证。执行前述的复现步骤,Tomcat 9.0.x版本给浏览器返回了如下响应:

HTTP Status 405 - JSPs only permit GET POST or HEAD
type Status report
message JSPs only permit GET POST or HEAD
description The specified HTTP method is not allowed for the requested resource.

检查9.0.x版本Tomcat生成的servlet代码,发现在_jspService中增加了对HTTP方法有效性的校验,只允许jsp编译生成的servlet响应GET、POST或HEAD方法,如下。

  public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
      throws java.io.IOException, javax.servlet.ServletException {

    final java.lang.String _jspx_method = request.getMethod();
    if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
      response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD");
      return;
    }

生成上述代码的实现位于org.apache.jasper.compiler.Generator类中,如下所示

// Method check
if (!pageInfo.isErrorPage()) {
    out.printil("final java.lang.String _jspx_method = request.getMethod();");
    out.printin("if (!\"GET\".equals(_jspx_method) && !\"POST\".equals(_jspx_method) && !\"HEAD\".equals(_jspx_method) && ");
    out.println("!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {");
    out.pushIndent();
    out.printin("response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, ");
    out.println("\"" + Localizer.getMessage("jsp.error.servlet.invalid.method") + "\");");
    out.printil("return;");
    out.popIndent();
    out.printil("}");
    out.println();
}

分析结论

这说明高版本的Tomcat已经意识到前述问题,并做了修复。

但此时还有一事不明,当请求HTTP请求中的方法不正确时,7.0.x版本的Tomcat依然可以正常返回页面信息。由于手上没有平台加固过的Tomcat的源码,这事情只好不了了之。

解决之道

显而易见,最直接的解决方法是更换Tomcat的版本,直接使用官网上发布的9.0.x版本。但官网发布的Tomcat没有经过安全加固,在项目中使用时需要自行做加固,难度不低,工作量不小。

所以不能换版本,得另想办法。

当前的诉求很简单,只允许Web服务器响应GET和POST请求,如果用户发起了其它请求,则清理会话、并跳转至错误页面。聪明的朋友一定想到了,使用J2EE标准中提供的Filter即可满足。文章来源地址https://www.toymoban.com/news/detail-767689.html

参考资料

关于HTTP方法

  • HTTP方法详解
  • HTTP六种请求方法
  • HTTP请求方法对照表
  • HTTP协议的几种请求方法
  • HTTP请求的方法

其它

  • burpsuite,强大的渗透测试神器
  • switchysharp,Google Chrome浏览器上目前最好用的代理程序
  • Struts2,Struts2官网
  • Filtering Requests and Responses,关于Filter的介绍材料
  • tomcat on GitHub,托管在GitHub上的官方镜像仓库
  • tomcat 7.0.x SVN,7.0.x版本的官方SVN仓库

到了这里,关于修复HTTP动词篡改导致的认证旁路问题的方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 深度解读与快速修复:应对ntdll.dll错误模块导致的程序闪退问题

    在使用Windows操作系统的过程中,遭遇ntdll.dll错误模块引发的程序闪退现象,无疑给用户带来了极大的不便。ntdll.dll作为Windows系统的核心组件之一,其功能的正常与否直接影响着系统的稳定性和应用程序的运行状况。本篇文章将详细解读ntdll.dll错误模块的成因,以及提供一套

    2024年04月12日
    浏览(31)
  • 慢速 HTTP 攻击 Slow HTTP Attack漏洞原理以及修复方法

    漏洞名称 :Slow Http attack、慢速攻击 漏洞描述 :慢速攻击基于HTTP协议,通过精心的设计和构造,这种特殊的请求包会造成服务器延时,而当服务器负载能力消耗过大即会导致拒绝服务。HTTP协议规定,HTTP Request以rnrn(0d0a0d0a)结尾表示客户端发送结束,服务端开始处理。那

    2024年01月19日
    浏览(39)
  • Win11的两个实用技巧系列之内存不足导致永劫无间闪退解决方法、Win11本地安全机构保护误报修复方法

    Win11内存不足导致永劫无间闪退怎么办?其实解决方法很简单,本文就为大家带来了详细的解决方法,感兴趣的朋友一起看看吧 Win11内存不足导致永劫无间闪退怎么办?永劫无间出现闪退的情况可能和很多因素有关,有用户经过排查之后,发现问题的根源是因为自己电脑的运

    2024年02月08日
    浏览(43)
  • nginx开启http2导致的服务验证码不可用问题

    问题描述: 新搭建了一套开源的系统。通过nginx做了https反向代理后无法显示验证码。 具体报错: Uncaught TypeError: Cannot read properties of null (reading ‘property’) 点击报错后跳转到方法: xhr.getAllResponseHeaders() 问题就出在这个方法,但不知识具体原因。 通过做实验方法排除。 新搭建

    2024年02月12日
    浏览(38)
  • 【Android】主线程切换播放视频时,调用http请求,导致页面卡顿问题

    业务场景:当我们在切换视频播放的途中,后台去调用http请求,就导致了主线程被阻塞,页面卡顿的现象,尝试出来的解决方式是开启一个后台线程去加载视频,然后在主线程中更新UI 这段代码是一个私有内部类 LoadVideoTask ,继承自 AsyncTask ,用于在后台线程中加载视频并在主线程中

    2024年02月16日
    浏览(41)
  • 解决浏览器自动将http跳转至https导致无法访问的问题

    目录 解决方式 Chrome浏览器 Safari浏览器 Edge浏览器 注意事项 什么是HSTS? 写在最后         最近在宝塔面板申请免费的SSL证书后,部署证书的80端口下的网站可以通过https正常访问,但其他未部署证书的端口也被强制跳转至https请求,导致浏览器提示不安全从而无法访问。

    2024年02月03日
    浏览(87)
  • 【python修复bug】—— HTTP_2 网站超时问题的解决方案

    在进行网络数据爬取时,使用 Python 程序访问支持 HTTP/2 协议的网站时,有时会遇到超时问题。这可能会导致数据获取不完整,影响爬虫程序的正常运行。 问题描述 在实际操作中,当使用 Python 编写的爬虫程序访问支持 HTTP/2 协议的网站时,可能会遇到超时异常。即使尝试强制

    2024年01月18日
    浏览(38)
  • 【会导致跨域问题的原因】Access to XMLHttpRequest at‘http://localhost:

    错误:` Access to XMLHttpRequest at ‘http://localhost:3000/framework/create’ from origin ‘http://localhost:4200’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.` 1. 如果使用nginx,查看nginx配置文件是否配

    2024年02月11日
    浏览(41)
  • Http 响应头 Transfer-Encoding : chunked 导致 浏览器客户端请求错误问题

    生产环境服务器规划如下 服务器 类型 网络环境 cal.com nginx 外网 192.168.7.15:9200 tomcat 内网 192.168.7.16:9200 tomcat 内网 sdd.com nginx 内网 192.168.7.15:9100 tomcat 内网 192.168.7.16:9100 tomcat 内网 192.168.7.15和192.168.7.16是做个负载均衡。目前的需求是用户访问外网的cal.com 返回 内网 192.168.7.15:9

    2024年02月15日
    浏览(46)
  • 双向SSL认证证书 生成 jks 步骤, java用jks 发送http请求 方法

    ) 1.证书的 cert.pem 文件 2.key文件 3.key的密钥 这里只显示 liunx 命令 ,windows 的同学可自查 这个命令会提示输入3次密码 ,第一次输入xxx.key的密码 , 第二次提示输入导出密码 自己设就行 ,这里用 changeit 注意: 第一次 不是自己设的 需要用 key文件的密钥 这里会用 上一步骤的导

    2024年02月06日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包