标题: FastjsonTypenameHash4.java
创建: 2020-07-31 16:17
更新:
链接: https://scz.617.cn/web/202007311617.txt
leadroyal在github上有个项目,维护了迄今为止最全的Fastjson黑名单列表:
https://github.com/LeadroyaL/fastjson-blacklist
今天有个其他目的需要写点代码,其中关于遍历目录寻找jar包以及遍历jar包寻找
class的部分是一种共性需求,就顺手按自己习惯写了个暴力穷举猜检Fastjson黑名
单的程序。
用起来很简单:
$ java FastjsonTypenameHash4
在指定目录下深度优先遍历所有jar包并搜寻黑名单命中情况。输出大概是这个样子:
$ java FastjsonTypenameHash4 .
./tomcat-dbcp-7.0.99.jar
-7966123100503199569 0x9172a53f157930af org.apache.tomcat
./ojdbc10-19.3.0.0.jar
-6316154655839304624 0xa85882ce1044c450 oracle.net.
-3319207949486691020 0xd1efcdf4b3316d34 oracle.jdbc.
./commons-collections-3.1.jar
-2192804397019347313 0xe1919804d5bf468f org.apache.commons.collections.comparators.
-2364987994247679115 0xdf2ddff310cdb375 org.apache.commons.collections.Transformer
7442624256860549330 0x6749835432e0f0d2 org.apache.commons.collections.functors
./rt.jar
5347909877633654828 0x4a3797b30328202c java.util.logging.
9140416208800006522 0x7ed9481d28bf417a java.awt.i
5751393439502795295 0x4fd10ddc6d13821f java.net.Socket
3256258368248066264 0x2d308dbbc851b0d8 java.lang.UNIXProcess
4147696707147271408 0x398f942e01920cf0 com.sun.
...
可以将输出转向到文本文件再做后期处理,看自己需求了,我本意不是为这事。
单就Fastjson黑名单而言,请移步leadroyal的项目,我这程序没啥特别,未做任何
针对性处理。
--------------------------------------------------------------------------
/*
* javac -encoding GBK -g FastjsonTypenameHash4.java
* java FastjsonTypenameHash4 .
*/
import java.io.*;
import java.util.*;
import java.util.stream.Stream;
import java.util.jar.*;
import java.nio.file.*;
public class FastjsonTypenameHash4
{
/*
* 每次升级后更新此处的私有哈希值
*
* from 1.2.70
*
* com.alibaba.fastjson.parser.ParserConfig
*/
private static long[] denyHashCodes = new long[]
{
0x80D0C70BCC2FEA02L,
0x86FC2BF9BEAF7AEFL,
0x87F52A1B07EA33A6L,
0x8EADD40CB2A94443L,
0x8F75F9FA0DF03F80L,
0x9172A53F157930AFL,
0x92122D710E364FB8L,
0x941866E73BEFF4C9L,
0x94305C26580F73C5L,
0x9437792831DF7D3FL,
0xA123A62F93178B20L,
0xA85882CE1044C450L,
0xAA3DAFFDB10C4937L,
0xAC6262F52C98AA39L,
0xAD937A449831E8A0L,
0xAE50DA1FAD60A096L,
0xAFFF4C95B99A334DL,
0xB40F341C746EC94FL,
0xB7E8ED757F5D13A2L,
0xB98B6B5396932FE9L,
0xBCDD9DC12766F0CEL,
0xBEBA72FB1CCBA426L,
0xC00BE1DEBAF2808BL,
0xC2664D0958ECFE4CL,
0xC41FF7C9C87C7C05L,
0xC7599EBFE3E72406L,
0xC8D49E5601E661A9L,
0xC963695082FD728EL,
0xD1EFCDF4B3316D34L,
0xD54B91CC77B239EDL,
0xD59EE91F0B09EA01L,
0xD8CA3D595E982BACL,
0xDCD8D615A6449E3EL,
0xDE23A0809A8B9BD6L,
0xDEFC208F237D4104L,
0xDF2DDFF310CDB375L,
0xE09AE4604842582FL,
0xE1919804D5BF468FL,
0xE2EB3AC7E56C467EL,
0xE603D6A51FAD692BL,
0xE9184BE55B1D962AL,
0xE9F20BAD25F60807L,
0xF3702A4A5490B8E8L,
0xF474E44518F26736L,
0xF7E96E74DFA58DBCL,
0xFC773AE20C827691L,
0xFD5BFC610056D720L,
0xFFA15BF021F1E37CL,
0xFFDD1A80F1ED3405L,
0x10E067CD55C5E5L,
0x761619136CC13EL,
0x22BAA234C5BFB8AL,
0x3085068CB7201B8L,
0x45B11BC78A3ABA3L,
0x55CFCA0F2281C07L,
0xB6E292FA5955ADEL,
0xEE6511B66FD5EF0L,
0x100150A253996624L,
0x10B2BDCA849D9B3EL,
0x10DBC48446E0DAE5L,
0x144277B467723158L,
0x14DB2E6FEAD04AF0L,
0x154B6CB22D294CFAL,
0x17924CCA5227622AL,
0x193B2697EAAED41AL,
0x1CD6F11C6A358BB7L,
0x1E0A8C3358FF3DAEL,
0x24D2F6048FEF4E49L,
0x24EC99D5E7DC5571L,
0x25E962F1C28F71A2L,
0x275D0732B877AF29L,
0x2AD1CE3A112F015DL,
0x2ADFEFBBFE29D931L,
0x2B3A37467A344CDFL,
0x2B6DD8B3229D6837L,
0x2D308DBBC851B0D8L,
0x313BB4ABD8D4554CL,
0x327C8ED7C8706905L,
0x332F0B5369A18310L,
0x339A3E0B6BEEBEE9L,
0x33C64B921F523F2FL,
0x34A81EE78429FDF1L,
0x3826F4B2380C8B9BL,
0x398F942E01920CF0L,
0x3ADBA40367F73264L,
0x3B0B51ECBF6DB221L,
0x42D11A560FC9FBA9L,
0x43320DC9D2AE0892L,
0x440E89208F445FB9L,
0x46C808A4B5841F57L,
0x49312BDAFB0077D9L,
0x4A3797B30328202CL,
0x4BA3E254E758D70DL,
0x4BF881E49D37F530L,
0x4DA972745FEB30C1L,
0x4EF08C90FF16C675L,
0x4FD10DDC6D13821FL,
0x527DB6B46CE3BCBCL,
0x535E552D6F9700C1L,
0x5728504A6D454FFCL,
0x599B5C1213A099ACL,
0x5A5BD85C072E5EFEL,
0x5AB0CB3071AB40D1L,
0x5D74D3E5B9370476L,
0x5D92E6DDDE40ED84L,
0x5F215622FB630753L,
0x62DB241274397C34L,
0x63A220E60A17C7B9L,
0x647AB0224E149EBEL,
0x65F81B84C1D920CDL,
0x665C53C311193973L,
0x6749835432E0F0D2L,
0x69B6E0175084B377L,
0x6A47501EBB2AFDB2L,
0x6FCABF6FA54CAFFFL,
0x746BD4A53EC195FBL,
0x74B50BB9260E31FFL,
0x75CC60F5871D0FD3L,
0x767A586A5107FEEFL,
0x7AA7EE3627A19CF3L,
0x7ED9311D28BF1A65L,
0x7ED9481D28BF417AL
};
/*
* from 1.2.70
*
* com.alibaba.fastjson.parser.ParserConfig
*
* 手工排过序,源代码中不是这个顺序。注意符号位,别按无符号理解。
*/
private static long[] expectHash = new long[]
{
0x90a25f5baa21529eL,
0xaf586a571e302c6bL,
0xd734ceb4c3e9d1daL,
0xe2a8ddba03e69e0dL,
0xe3dd9875a2dc5283L,
0xed007300a7b227c6L,
0x295c4605fd1eaa95L,
0x2d10a5801b9d6136L,
0x47ef269aadc650b4L,
0x6439c4dff712ae8bL
};
/*
* from 1.2.42
*
* com.alibaba.fastjson.parser.ParserConfig.checkAutoType(String, Class, int)
*/
private static void PrivateFindBlackname ( String typeName, HashMap hm )
{
String className = typeName.replace('$', '.');
final long BASIC = 0xcbf29ce484222325L;
final long PRIME = 0x100000001b3L;
final long h3 =
(((((BASIC ^ className.charAt(0))
* PRIME)
^ className.charAt(1))
* PRIME)
^ className.charAt(2))
* PRIME;
long hash = h3;
for ( int i = 3; i < className.length(); ++i )
{
hash ^= className.charAt(i);
hash *= PRIME;
/*
* 二分查找,要求denyHashCodes是排过序的
*/
if ( Arrays.binarySearch( denyHashCodes, hash ) >= 0 )
{
hm.put( hash, className.substring( 0, i+1 ) );
break;
}
}
return;
} /* end of PrivateFindBlackname */
private static void PrivateFindBlackname2 ( String typeName, HashMap hm )
{
String className = typeName.replace('$', '.');
final long BASIC = 0xcbf29ce484222325L;
final long PRIME = 0x100000001b3L;
final long h3 =
(((((BASIC ^ className.charAt(0))
* PRIME)
^ className.charAt(1))
* PRIME)
^ className.charAt(2))
* PRIME;
long hash = h3;
for ( int i = 3; i < className.length(); ++i )
{
hash ^= className.charAt(i);
hash *= PRIME;
}
/*
* 二分查找,要求expectHash是排过序的
*/
if ( Arrays.binarySearch( expectHash, hash ) >= 0 )
{
hm.put( hash, className );
}
return;
} /* end of PrivateFindBlackname2 */
private static void EnumerateClassFromJar ( String JarFile )
{
try
{
/*
* https://docs.oracle.com/javase/8/docs/api/java/util/jar/JarInputStream.html
* https://docs.oracle.com/javase/8/docs/api/java/util/jar/JarEntry.html
*/
JarInputStream jis = new JarInputStream( new FileInputStream( JarFile ), false );
JarEntry je;
String EntryName;
String ClassName;
/*
* 此处Long不能写成long,Integer不能写成int
*/
HashMap hm = new HashMap<>();
while ( true )
{
je = jis.getNextJarEntry();
if ( je == null )
{
break;
}
EntryName = je.getName();
if ( EntryName.endsWith( ".class" ) )
{
// System.out.println( EntryName );
/*
* 干掉结尾的".class"再替换
*/
ClassName = EntryName.substring( 0, EntryName.length()-6 ).replace( "/", "." );
// System.out.println( ClassName );
PrivateFindBlackname( ClassName, hm );
/*
* 未做任何优化处理,懒得优化,于是浪费了不少CPU。本来
* expectHash就那么几个,还都在rt.jar中,没必要在此处
* 来这么一下。如果看不顺眼,注释掉下面这条代码即可。
*/
PrivateFindBlackname2( ClassName, hm );
}
}
Set>
es = hm.entrySet();
Iterator>
it = es.iterator();
Map.Entry e;
long hash;
String sth;
while ( it.hasNext() )
{
e = it.next();
hash = e.getKey();
sth = e.getValue();
System.out.println
(
String.format
(
"%d %#x %s",
hash,
hash,
sth
)
);
}
}
catch ( Exception e )
{
System.out.println( e.toString() );
e.printStackTrace();
}
} /* end of EnumerateClassFromJar */
private static void EnumerateFileFromDir ( String dir, String suffix )
{
/*
* Java 8的用法,Java 7不支持
*
* https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html
* https://docs.oracle.com/javase/8/docs/api/java/nio/file/Paths.html
*/
try
(
Stream paths = Files.walk( Paths.get( dir ), FileVisitOption.FOLLOW_LINKS )
)
{
paths
.filter( Files::isRegularFile )
.map( p -> p.toString() )
.filter( name -> name.endsWith( suffix ) )
.peek( System.out::println )
.forEach( FastjsonTypenameHash4::EnumerateClassFromJar );
}
catch ( Exception e )
{
System.out.println( e.toString() );
e.printStackTrace();
}
} /* end of EnumerateFileFromDir */
public static void main ( String[] argv ) throws Exception
{
String dir = argv[0];
EnumerateFileFromDir( dir, ".jar" );
}
}
--------------------------------------------------------------------------
留一个开放式问题,Java 9及以上版本没有rt.jar,只有modules这种东西。上述代
码不能用于modules,也不能直接用于jmod文件,后者虽然是ZIP格式,但目录结构多
了一层,如果要得到类名,需要针对性处理。