zoukankan      html  css  js  c++  java
  • S2-002漏洞分析

    漏洞概述

    Struts2-002是一个 XSS 漏洞,该漏洞发生在 <s:url><s:a>标签中,未对标签内字符进行转义,当标签的属性 includeParams=all 时,即可触发该漏洞。

    漏洞影响版本: Struts 2.0.0 - Struts 2.1.8.1 。更多详情可参考官方通告:https://cwiki.apache.org/confluence/display/WW/S2-002

    环境搭建

    直接在上一次S2-001的环境上做一些修改
    index.jsp中,将上次的form表单删掉,添加一个<s:url>标签

    <%--
      Created by IntelliJ IDEA.
      User: twosmi1e
      Date: 2020/11/19
      Time: 7:32 下午
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page language="java" contentType="text/html"
             pageEncoding="UTF-8"%>
    <%@ taglib prefix="s" uri="/struts-tags" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <title>S2-001</title>
    </head>
    <body>
    <h2>S2-001 Demo</h2>
    <p>link: <a href="https://cwiki.apache.org/confluence/display/WW/S2-001">https://cwiki.apache.org/confluence/display/WW/S2-001</a></p>
    
    <s:url action="login" includeParams="all"></s:url>
    
    
    </body>
    </html>
    

    LoginAction.java中添加url变量,将对用户名密码的处理删掉

    package com.demo.action;
    
    import com.opensymphony.xwork2.ActionSupport;
    
    public class LoginAction extends ActionSupport {
        private String username = null;
        private String password = null;
        private String url = null;
    
        public String getUsername() {
            return this.username;
        }
    
        public String getPassword() {
            return this.password;
        }
    
        public String getUrl(){
            return this.url;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public void setUrl(String url){
            this.url = url;
        }
    
    
    
        public String execute() throws Exception {
    
            return "error";
        }
    }
    

    运行复现漏洞

    成功触发XSS

    漏洞分析

    当在 JSP 文件中遇到 Struts2 标签 <s: 时,程序会先调用 doStartTag ,并将标签中的属性设置到对应标签对象相应属性中。最后,在遇到 /> 结束标签的时候调用 doEndTag 方法。

    跟进component.start函数

    可以看到函数会根据标签includeParams属性不同做不同处理
    all 和 get 的不同只有一个 mergeRequestParameters 方法,在 includeParams 为 all 的情况下会调用 mergeRequestParameters 将 tomcat 处取来的参数:

    这里取到了我们输入的payload,并且保存在parameters

    在 mergeRequestParameters 方法之后,依次是 includeGetParameters、includeExtraParameters 方法。 includeGetParameters 方法主要是将 HttpRequest.getQueryString() 的数据存入 this.parameters 属性,而 includeExtraParameters 方法则用来存入其它数据。

    而在 get 时会调用的两个函数中,includeGetParameters 方法则是先获取请求参数字符串,再进行处理分割:

    而调用 this.req.getQueryString 从 tomcat 处获取的请求参数字符串是经过 URL 编码的,所以无法造成 XSS 漏洞。

    includeExtraParameters 则一般为 null。

    执行完doStartTag后进入doEndTag,调用buildUrl

    然后返回result触发XSS

    漏洞修复

    2.0.11.1 版本修复

    对 s:a 标签的修复如下:

    if (this.href != null) {
        this.addParameter("href", this.ensureAttributeSafelyNotEscaped(this.findString(this.href)));
    }
    

    加上了一个 ensureAttributeSafelyNotEscaped 方法来过滤双引号:

    protected String ensureAttributeSafelyNotEscaped(String val) {
        return val != null ? val.replaceAll(""", "&#34;") : "";
    }
    

    对 s:url 标签的修复如下:

    for(result = link.toString(); result.indexOf("<script>") > 0; result = result.replaceAll("<script>", "script")) {
        ;
    }
    

    在拼接完之后对 script 进行了处理,但是只是简单的将 script 标签的两个尖括号去掉了,所以可以轻松绕过:

    http://localhost:8080/login.action?<script 1>alert(1)</script>=hello

    2.2.1 版本修复

    private static String buildParameterSubstring(String name, String value) {
        StringBuilder builder = new StringBuilder();
        builder.append(translateAndEncode(name));
        builder.append('=');
        builder.append(translateAndEncode(value));
        return builder.toString();
    }
    public static String translateAndEncode(String input) {
        String translatedInput = translateVariable(input);
        String encoding = getEncodingFromConfiguration();
        try {
            return URLEncoder.encode(translatedInput, encoding);
        } catch (UnsupportedEncodingException e) {
            LOG.warn("Could not encode URL parameter '" + input + "', returning value un-encoded");
            return translatedInput;
        }
    }
    

    使用url编码修复了漏洞

    参考

    https://aluvion.gitee.io/2020/07/15/struts2系列漏洞-S2-002/
    https://mochazz.github.io/2020/06/17/Java代码审计之Struts2-002/

  • 相关阅读:
    November 07th, 2017 Week 45th Tuesday
    November 06th, 2017 Week 45th Monday
    November 05th, 2017 Week 45th Sunday
    November 04th, 2017 Week 44th Saturday
    November 03rd, 2017 Week 44th Friday
    Asp.net core 学习笔记 ( Area and Feature folder structure 文件结构 )
    图片方向 image orientation Exif
    Asp.net core 学习笔记 ( Router 路由 )
    Asp.net core 学习笔记 ( Configuration 配置 )
    qrcode render 二维码扫描读取
  • 原文地址:https://www.cnblogs.com/twosmi1e/p/14134511.html
Copyright © 2011-2022 走看看