记一次跨站脚本攻击审计过程

admin 2021年5月10日01:25:57评论79 views字数 4327阅读14分25秒阅读模式

前言

  前面的文章分享了一些Java中跨站脚本攻击的审计思路。结合github上某实际的代码环境进行相关的实战,以下记录相关的审计过程。

相关过程

  首先拿到工程代码后,先梳理前后端的处理以及渲染过程。这里可以通过类似关键字快速定位:
<%=
${
<c:out
<c:if
<c:forEach
ModelAndView
ModelMap
Model
request.getParameter
request.setAttribute

  通过关键字快速定位到一个切入点,该接口从用户输入获取occupationid以及questionxl两个参数的值,在存入request域后跳转到list2页面:
java
@RequestMapping(value="/edit")
public String edit(HttpServletRequest request,String occupationid,String questionxl) throws Exception{
request.setAttribte("eq_occupationid",occupationid);
request.setAttribte("eq_questionxl",questionxl);
return "/query/analyse/list2"
}

  追踪到list2页面查看,看看在对应的页面是否对刚刚存入request域的两个参数occupationid以及questionxl进行了展示,如果有的话,是否进行了输出编码处理。
java
<body class="mainContnt">
<jbfs:tile title="分析结果查询" isShowTime="false" isShowJspName="flase"/>
<div id="mainContent">
<%@ include file="/base-page/common/errormsg.jsp"%>
<form method="post" action="<%=webapp>/analyse/edit.act">
<jbfs:hidden property="eq_occupationid"/>
<jbfs:hidden property="eq_questionxl"/>

  可以看到这里使用了jbfs标签进行了对应的展示,跟常见的JSTL、EL表达式有点不相同。在jsp开发时,当jsp内置标签以及JSTL标签库都满足不了需求时,可以根据自己的需求来自定义标签。这时候需要找相关的tld文件查看对应标签的具体实现方法。这里猜测是通过自定义一个标签库,满足一些常见的HTML标签以及对应属性的组装。
  一般tld文件都放在WEB-INF下,这样可以保证客户端访问不到。也可以在web.xml进行配置。
  查看web.xml相关配置,其使用标签来引入自定义标签库,相关配置文件在tld目录下的tag.tld:
xml
<jsp-config>
<taglib>
<taglib-uri>/WEB-INF/tld/tag.tld</taglib-uri>
<taglib-location>/WEB-INF/tld/tag.tld </taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/tld/sgrid.tld</taglib-uri>
<taglib-location>/WEB-INF/tld/sgrid.tld </taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/tld/greport.tld</taglib-uri>
<taglib-location>/WEB-INF/tld/greport.tld </taglib-location>
</taglib>
</jsp-config>

  查看tag.tld文件,刚刚我们在jsp页面看到引用方式是
,搜索hidden关键字,相关内容如下:
xml
<tag>
<name>hidden</name>
<tag-class>
com.jbfs.base.tag.html.HiddenTag
</tag-class>
<attribute>
<name>id</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>
<![CDATA[
<p>标签id</p>
]]>
</description>
</attribute>
<attribute>
<name>property</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<description>
<![CDATA[
<p>标签的property属性</p>
]]>
</description>
</attribute>
<attribute>
<name>name</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>
<![CDATA[
<p>标签name</p>
]]>
</description>
</attribute>
<attribute>
<name>value</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>
<![CDATA[
<p>value属性</p>
]]>
</description>
</attribute>
</tag>

  也就是说该标签的定义方式主要在com.jbfs.base.tag.html包下的HiddenTag.java文件中。
  到com.jbfs.base.tag.html.HiddenTag类下查看具体实现:
```java
package com.jbfs.base.tag.html;
import javax.servlet.jsp.JspException;
import com.jbfs.base.tag.AbstractTagSupport;
/*
* 该类是hidden标签
* @version 2013-06-06
* @author Leibf
/
public class HiddenTag extends AbstractTagSupport
{
private static final long serialVersionUID = 1L;
public HiddenTag()
{
super();
}
public int doStartTag() throws JspException
{
StringBuffer content = new StringBuffer("<input ");

    this.prepareAttribute(content, "type", "hidden");
    this.prepareAttribute(content, "value", this.preValue());
    this.prepareAttributes(content);
    content.append("/>");

    this.write(pageContext, content.toString());

    return (EVAL_BODY_INCLUDE);
}

public int doEndTag() throws JspException
{
    super.doEndTag();
    this.release();
    return EVAL_PAGE;
}
public void release()
{
    super.release();
}

}
&emsp;&emsp;可以看到该类继承了AbstractTagSupport,然后通过prepareAttribute方法对标签进行封装。查看AbstractTagSupport.java中对于prepareAttribute方法的定义:
/*
* 单个属性准备
*
* @param content
* @param name
* @param value
/
protected void prepareAttribute(StringBuffer content, String name, String value)
{
if (value != null)
{
content.append(" ");
content.append(name);
content.append("="");
content.append(this.evalString(name, value));
content.append(""");
}
}
&emsp;&emsp;到这里整个数据交互流程就出来了,也就是说,访问edit接口后,跳转到list2页面,从用户输入获取occupationid以及questionxl最后在页面中的呈现形式应该是这样的:
![814953A2DBA142578425FE9D15FEBD5C.png](/img/sin/M00/00/12/wKg0C15h5mqAEv3nAAA6zIIpefE367.png)
&emsp;&emsp;这里可以看到,整个过程是没有相关的编码操作的,最简单的利用方式就是闭合双引号“,然后写入accesskey以及类似onclick事件,通过组合快捷键触发。例如提交请求如下:

?occupationid="onclick="comfirm(1)"accesskey="x&questionxl="onclick="comfirm(1)"accesskey="x
```
  整理完相关的数据交互流程后,就是看一下是否有相关的安全防护措施了,这里使用了拦截器的方式进行相关的输入拦截,相关规则如下:

记一次跨站脚本攻击审计过程
  可以看到拦截器的规则比较简单,并不能覆盖我们的标签中value属性的xss场景。到这里就成功得到了一个跨站脚本攻击的漏洞接口了。

具体修复

  修复的话主要是两个思路,一个是过滤敏感输入,这里其实已经有了,但是规则太简陋。例如一下JS事件、特殊符号,或者是编码绕过、JS全局变量等场景都需要考虑,其次就是输出编码。输出编码的话主要是要结合浏览器解析考虑特殊的编码场景,例如链接内容、内联的JavaScript代码块等。

相关推荐: 记一次跨站脚本攻击审计过程

前言   前面的文章分享了一些Java中跨站脚本攻击的审计思路。结合github上某实际的代码环境进行相关的实战,以下记录相关的审计过程。 相关过程   首先拿到工程代码后,先梳理前后端的处理以及渲染过程。这里可以通过类…

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年5月10日01:25:57
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   记一次跨站脚本攻击审计过程https://cn-sec.com/archives/246305.html