某bi V 6.0.19 尝试绕过黑名单

admin 2024年9月24日17:21:00评论12 views字数 8317阅读27分43秒阅读模式

Cypher语法

本次使用tabby来分析相关利用链子,会用到Cypher的相关语句,
如以下语句是查询readobject被谁调用,深度为5,查询20条链,

match (source:Method {NAME:"readObject"})
match (sink:Method {NAME:"put", CLASSNAME:"java.util.Hashtable"})<-[:CALL]-(m1:Method)
call apoc.algo.allSimplePaths(source, m1, "ALIAS>|CALL>", 5) yield path
return * limit 20

通过寻找equals函数到toString函数的链子,其中source点可序列化

match (source:Method)<-[:HAS]-(c:Class)-[:INTERFACE|EXTENDS*]->(c1:Class {NAME:"java.io.Serializable"})
where source.NAME in ["equals"]
and source.CLASSNAME in ["com.fr.esd.query.DSQueryEntity"]
match (sink:Method {NAME:"toString"})<-[:CALL]-(m1:Method)
call apoc.algo.allSimplePaths(source, m1, "ALIAS>|CALL>", 2) yield path
return * limit 2

可设置多个source点,然后定义最终的sink点,

match (source:Method) where source.NAME in ["equals","hashCode","compareTo"] 
match (sink:Method {NAME:"toString"})<-[:CALL]-(m1:Method)
call apoc.algo.allSimplePaths(source, m1, "ALIAS>|CALL>", 5) yield path
return * limit 1

分析

在分析过程中,可以根据以下草稿,这里可以利用正则去匹配,不过费时费力,因此可以去使用tabby来分析,

入口hashmaphashtable
hashcode() equals(key) tostring() m.get(key) readobject()

最终调用到tostring

正则表达式 hashcode(((?!public)[sS]){1,1000}[.]toString
readobject(((?!public)[sS]){1,1000}[.](toString|put|compareto|getValue|getkey)

hashcode+tostring
readobject+tostring
get+tostring
equals+tostring

readobject->put

readobject->put
StringComparator
TreeMap.put->compare->compareto+tostring

TreeMap.put->compare->compareto->getValue+tostring

TreeMap.put->compare->compareto->getkey+tostring


(readobject|hashcode|equals)(((?!public)[sS]){1,1000}[.]put(
第二希望在equals找到put
第一希望hashcode->getValue->tostring

查找equals->...->toString,

match (source:Method)<-[:HAS]-(c:Class)-[:INTERFACE|EXTENDS*]->(c1:Class {NAME:"java.io.Serializable"})
where source.NAME in ["equals"]
match (sink:Method {NAME:"toString", CLASSNAME:"java.lang.Object"})<-[:CALL]-(m1:Method)
call apoc.algo.allSimplePaths(source, m1, "ALIAS>|CALL>", 7) yield path
where none(n in nodes(path) where n.CLASSNAME in ["com.fr.esd.query.DSQueryEntity", "com.fr.base.PaperSize", "java.util.EnumMap", "java.time.temporal.WeekFields", "sun.security.util.DerValue", "sun.security.x509.AlgorithmId", "java.util.concurrent.ConcurrentHashMap", "java.util.Hashtable", "com.fr.file.CacheManager$DBKey4Procedure", "com.fr.third.jgroups.stack.RouterStubManager$Target", "javax.security.auth.Subject", "java.lang.String", "sun.security.x509.CertificateExtensions", "com.fr.retry.Predicates$IsEqualToPredicate", "java.text.AttributedCharacterIterator$Attribute", "sun.security.x509.CRLExtensions", "java.util.AbstractMap", "com.fr.plugin.basic.CloseableUtils", "com.fr.data.dao.ClassArrayKey$KEY", "com.fr.base.headerfooter.TextHFElement", "com.fr.stable.version.ProductVersion", "com.fr.cluster.engine.member.persistence.FineClusterNode", "java.util.jar.Attributes$Name", "java.lang.reflect.WeakCache$CacheValue", "java.lang.reflect.WeakCache$LookupValue", "sun.security.x509.OtherName"])
return * limit 20

查找hashCode->...->toString,

match (source:Method)<-[:HAS]-(c:Class)-[:INTERFACE|EXTENDS*]->(c1:Class {NAME:"java.io.Serializable"})
where source.NAME in ["hashCode"]
match (sink:Method {NAME:"toString", CLASSNAME:"java.lang.Object"})<-[:CALL]-(m1:Method)
call apoc.algo.allSimplePaths(source, m1, "ALIAS>|CALL>", 5) yield path
where none(n in nodes(path) where n.CLASSNAME in ["com.fr.esd.query.DSQueryEntity", "java.util.concurrent.ConcurrentHashMap$KeySetView", "sun.security.util.DerValue"])
return * limit 20

查找get->...->toString,

match (source:Method)<-[:HAS]-(c:Class)-[:INTERFACE|EXTENDS*]->(c1:Class {NAME:"java.io.Serializable"})
where source.NAME in ["get"]
match (sink:Method {NAME:"toString", CLASSNAME:"java.lang.Object"})<-[:CALL]-(m1:Method)
call apoc.algo.allSimplePaths(source, m1, "ALIAS>|CALL>", 5) yield path
where none(n in nodes(path) where n.CLASSNAME in ["java.time.LocalDate", "com.fr.esd.query.DSQueryEntity", "java.time.temporal.TemporalAccessor"])
return * limit 20

查找readobject->...->toString,

match (source:Method)<-[:HAS]-(c:Class)-[:INTERFACE|EXTENDS*]->(c1:Class {NAME:"java.io.Serializable"})
where source.NAME in ["readObject"]
match (sink:Method {NAME:"toString", CLASSNAME:"java.lang.Object"})<-[:CALL]-(m1:Method)
call apoc.algo.allSimplePaths(source, m1, "ALIAS>|CALL>", 6) yield path
where none(n in nodes(path) where n.CLASSNAME in ["com.fr.esd.query.DSQueryEntity", "java.security.Provider", "java.security.PermissionsHash", "java.security.Permissions", "java.util.PropertyPermissionCollection", "java.security.BasicPermissionCollection", "java.util.EnumMap", "java.io.FilePermissionCollection", "sun.security.util.DerValue", "java.util.concurrent.ConcurrentHashMap", "java.util.Locale", "com.fr.base.headerfooter.ImageHFElement", "java.lang.StringBuilder", "java.text.DecimalFormatSymbols", "com.fr.swift.adaptor.log.SqlConverter$8", "java.util.Hashtable"])
return * limit 20

以上的limit 20为深度,可从1开始调节,逐渐去排除利用链中不相关的节点,

因此尝试利用tabby来绕某系统的黑名单,最主要是找到一条能触发到toString的链子,
利用tabby查询到中间的这条链子,上面的get肯定是行不通的,

某bi V 6.0.19 尝试绕过黑名单

因此调试以下链能走到hashtable.equals,

package org.example;
import com.fr.base.PaperSize;
import com.fr.base.Parameter;
import com.fr.chart.chartdata.JSONTableData;
import com.fr.esd.query.DSQueryEntity;
import com.fr.json.revise.EncodeException;
import com.fr.script.CalculatorMap;
import com.fr.serialization.JDKSerializer;
import com.fr.third.alibaba.druid.pool.DruidAbstractDataSource;
import com.fr.third.alibaba.druid.pool.DruidDataSource;
import com.fr.third.alibaba.druid.pool.xa.DruidXADataSource;
import com.fasterxml.jackson.databind.node.POJONode;
import com.fr.third.fasterxml.jackson.databind.ObjectMapper;
import com.fr.third.fasterxml.jackson.databind.SerializationFeature;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.org.apache.xpath.internal.objects.XString;
import javassist.*;
import oracle.jdbc.rowset.OracleCachedRowSet;
import org.apache.arrow.vector.util.JsonStringArrayList;
import org.apache.commons.collections4.FunctorException;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.InvokerTransformer;

import javax.swing.UIDefaults;

import javax.management.BadAttributeValueExpException;
import com.fr.json.JSONArray;
import org.jcodings.util.Hash;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.SignedObject;
import java.sql.SQLException;
import java.util.*;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class Main {

public static void main(String[] args) throws NotSerializableException, EncodeException, IllegalAccessException, NoSuchFieldException, NotFoundException, CannotCompileException, IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, SQLException {


HashMap hashmap_c_1 = new HashMap();
hashmap_c_1.put("8", "8");
HashMap hashmap_c_2 = new HashMap();
hashmap_c_2.put("8", "8");
CalculatorMap calculatorMap_1 = CalculatorMap.create(hashmap_c_1);
CalculatorMap calculatorMap_2 = CalculatorMap.create(hashmap_c_2);


Hashtable<Object,Object> hashtable_a = new Hashtable<>();
Hashtable<Object,Object> hashtable_b = new Hashtable<>();
hashtable_a.put(calculatorMap_1, 3);
hashtable_b.put(calculatorMap_2, 3);

HashMap hashmap_1 = new HashMap();
HashMap hashmap_2 = new HashMap();
hashmap_1.put(hashtable_a, hashtable_a);
hashmap_2.put(hashtable_b, hashtable_b);

/*
HashMap hashmap = new HashMap<>();
hashmap.put(calculatorMap_1, 3);
hashmap.put(calculatorMap_2, 3);
*/

Hashtable<Object,Object> hashtable = new Hashtable<>();
hashtable.put(hashmap_1, 3);
hashtable.put(hashmap_2, 3);



ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(hashtable);
byte[] bytes = byteArrayOutputStream.toByteArray();
System.out.println(Arrays.toString(byteArrayOutputStream.toByteArray()));

ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
objectInputStream.readObject();


}
}

不过因为m.get(key)这里的返回值一直为null,没调式出来,
通过触发hashtable的equals函数,

某bi V 6.0.19 尝试绕过黑名单

尝试控制传入equals函数的参数,如果能控制,则能走到t.containskey(key),

某bi V 6.0.19 尝试绕过黑名单

最终走到CalculatorMap的toString函数,

某bi V 6.0.19 尝试绕过黑名单

栈堆如下,

某bi V 6.0.19 尝试绕过黑名单

总结:结果是失败的,不过对Cypher的相关语法更加了解了,也对tabby有了了解,后面更加熟练利用相关审计工具

感谢【tq]

来源:【某bi V 6.0.19 尝试绕过黑名单 - https://xz.aliyun.com/t/15110】

原文始发于微信公众号(船山信安):某bi V 6.0.19 尝试绕过黑名单

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年9月24日17:21:00
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   某bi V 6.0.19 尝试绕过黑名单https://cn-sec.com/archives/3131452.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息