标题: 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格式,但目录结构多 了一层,如果要得到类名,需要针对性处理。