背景
因为要使用es的告警功能,而告警功能是收费版本,那么就破解白金级吧。
原理
license中有个signature字段,ES会根据这个字段判断License是否被篡改。只要取消ES的这个判断逻辑,就可以随便篡改License,达到激活的目的了。
我是基于 官方 ES Docker 镜像 7.13.0 版本进行破解的。原则上支持任意版本破解。
破解
提取文件
1
| ES_HOME/modules/x-pack-core/x-pack-core-7.13.0.jar
|
获取Jar包查看工具Luyten,你可以可以使用其他的工具,GitHub
然后打开x-pack-core-7.13.0.jar这个文件:
定位到两个文件:然后点击File–Save As 另存为java源码文件:
修改源码
org.elasticsearch.license/LicenseVerifier.class 另存后:LicenseVerifier.java
LicenseVerifier.java 修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| package org.elasticsearch.license;
import java.nio.*; import org.elasticsearch.common.bytes.*; import java.security.*; import java.util.*; import org.elasticsearch.common.xcontent.*; import org.apache.lucene.util.*; import org.elasticsearch.core.internal.io.*; import java.io.*;
public class LicenseVerifier { public static boolean verifyLicense(final License license, final byte[] publicKeyData) { /* 注释掉这一大段 byte[] signedContent = null; byte[] publicKeyFingerprint = null; try { final byte[] signatureBytes = Base64.getDecoder().decode(license.signature()); final ByteBuffer byteBuffer = ByteBuffer.wrap(signatureBytes); final int version = byteBuffer.getInt(); final int magicLen = byteBuffer.getInt(); final byte[] magic = new byte[magicLen]; byteBuffer.get(magic); final int hashLen = byteBuffer.getInt(); publicKeyFingerprint = new byte[hashLen]; byteBuffer.get(publicKeyFingerprint); final int signedContentLen = byteBuffer.getInt(); signedContent = new byte[signedContentLen]; byteBuffer.get(signedContent); final XContentBuilder contentBuilder = XContentFactory.contentBuilder(XContentType.JSON); license.toXContent(contentBuilder, (ToXContent.Params)new ToXContent.MapParams((Map)Collections.singletonMap("license_spec_view", "true"))); final Signature rsa = Signature.getInstance("SHA512withRSA"); rsa.initVerify(CryptUtils.readPublicKey(publicKeyData)); final BytesRefIterator iterator = BytesReference.bytes(contentBuilder).iterator(); BytesRef ref; while ((ref = iterator.next()) != null) { rsa.update(ref.bytes, ref.offset, ref.length); } return rsa.verify(signedContent); } catch (IOException ex) {} catch (NoSuchAlgorithmException ex2) {} catch (SignatureException ex3) {} catch (InvalidKeyException e) { throw new IllegalStateException(e); } finally { if (signedContent != null) { Arrays.fill(signedContent, (byte)0); } } */ return true; // 增加这行 } public static boolean verifyLicense(final License license) { /* 注释掉这一大段 byte[] publicKeyBytes; try { final InputStream is = LicenseVerifier.class.getResourceAsStream("/public.key"); try { final ByteArrayOutputStream out = new ByteArrayOutputStream(); Streams.copy(is, (OutputStream)out); publicKeyBytes = out.toByteArray(); if (is != null) { is.close(); } } catch (Throwable t) { if (is != null) { try { is.close(); } catch (Throwable t2) { t.addSuppressed(t2); } } throw t; } } catch (IOException ex) { throw new IllegalStateException(ex); } return verifyLicense(license, publicKeyBytes); */ return true; // 增加这行 } }
|
org.elasticsearch.xpack.core/XPackBuild.class 另存后:XPackBuild.java
XPackBuild.java 修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| package org.elasticsearch.xpack.core;
import org.elasticsearch.common.io.*; import java.net.*; import org.elasticsearch.common.*; import java.nio.file.*; import java.io.*; import java.util.jar.*;
public class XPackBuild { public static final XPackBuild CURRENT; private String shortHash; private String date; @SuppressForbidden(reason = "looks up path of xpack.jar directly") static Path getElasticsearchCodebase() { final URL url = XPackBuild.class.getProtectionDomain().getCodeSource().getLocation(); try { return PathUtils.get(url.toURI()); } catch (URISyntaxException bogus) { throw new RuntimeException(bogus); } } XPackBuild(final String shortHash, final String date) { this.shortHash = shortHash; this.date = date; } public String shortHash() { return this.shortHash; } public String date() { return this.date; } static { final Path path = getElasticsearchCodebase(); String shortHash = null; String date = null; Label_0109: { /* 注释掉这一大段即可 if (path.toString().endsWith(".jar")) { try { final JarInputStream jar = new JarInputStream(Files.newInputStream(path, new OpenOption[0])); try { final Manifest manifest = jar.getManifest(); shortHash = manifest.getMainAttributes().getValue("Change"); date = manifest.getMainAttributes().getValue("Build-Date"); jar.close(); } catch (Throwable t) { try { jar.close(); } catch (Throwable t2) { t.addSuppressed(t2); } throw t; } break Label_0109; } catch (IOException e) { throw new RuntimeException(e); } } */ shortHash = "Unknown"; date = "Unknown"; } CURRENT = new XPackBuild(shortHash, date); } }
|
java源代码已经更改完毕,下面就是生成class文件,然后替换原来的class文件即可:
生成Class文件
执行这段脚本,就可以得到2个Java代码对应的class文件
1 2 3 4 5 6 7 8
| ES_HOME="/usr/share/elasticsearch" ES_JAR=$(cd $ES_HOME && ls lib/elasticsearch-[0-9]*.jar) ESCORE_JAR=$(cd $ES_HOME && ls lib/elasticsearch-core-*.jar) LUCENE_JAR=$(cd $ES_HOME && ls lib/lucene-core-*.jar) XPACK_JAR=$(cd $ES_HOME && ls modules/x-pack-core/x-pack-core-*.jar)
javac -cp "${ES_HOME}/${ES_JAR}:${ES_HOME}/${LUCENE_JAR}:${ES_HOME}/${XPACK_JAR}:${ES_HOME}/${ESCORE_JAR}" LicenseVerifier.java javac -cp "${ES_HOME}/${ES_JAR}:${ES_HOME}/${LUCENE_JAR}:${ES_HOME}/${XPACK_JAR}:${ES_HOME}/${ESCORE_JAR}" XPackBuild.java
|
解压重新替换并打包
我们把$ES_HOME/modules/x-pack-core/x-pack-core-7.13.0.jar提取出来,放到一个临时的/elk/x-pack目录中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| $ export ES_HOME="/usr/share/elasticsearch" $ cp $ES_HOME/modules/x-pack-core/x-pack-core-7.13.0.jar /elk/x-pack $ cd /elk/x-pack # 解压x-pack-core-7.13.0.jar $ jar -xvf x-pack-core-7.13.0.jar
# 替换.class文件 $ cp /root/XPackBuild.class /elk/x-pack/org/elasticsearch/xpack/core/ $ cp /root/LicenseVerifier.class /elk/x-pack/org/elasticsearch/license/
# 重新打包生成x-pack-core-7.13.0.jar文件 $ cd /elk/x-pack $ rm -rf x-pack-core-7.13.0..jar # 删除临时拷贝过来的源文件 $ jar cvf x-pack-core-7.13.0..jar .
|
申请License并修改导入
去官网申请License。
我们将申请下来的License中的type
改为platinum
,将expiry_date_in_millis
延长N年时间:
1 2 3 4 5 6 7 8 9 10 11 12 13
| { "license": { "uid": "92c6b41e-59f9-4674-b227-77063c5fa8b0", "type": "platinum", "issue_date_in_millis": 1642291200000, "expiry_date_in_millis": 3107746200000, "max_nodes": 100, "issued_to": "junyao hong (race)", "issuer": "Web Form", "signature": "AAAAAwAAAA0kxge9SLSAvWWnMgDEAAABmC9ZN0hjZDBGYnVyRXpCOW5Bb3FjZDAxOWpSbTVoMVZwUzRxVk1PSmkxaktJRVl5MUYvUWh3bHZVUTllbXNPbzBUemtnbWpBbmlWRmRZb25KNFlBR2x0TXc2K2p1Y1VtMG1UQU9TRGZVSGRwaEJGUjE3bXd3LzRqZ05iLzRteWFNekdxRGpIYlFwYkJiNUs0U1hTVlJKNVlXekMrSlVUdFIvV0FNeWdOYnlESDc3MWhlY3hSQmdKSjJ2ZTcvYlBFOHhPQlV3ZHdDQ0tHcG5uOElCaDJ4K1hob29xSG85N0kvTWV3THhlQk9NL01VMFRjNDZpZEVXeUtUMXIyMlIveFpJUkk2WUdveEZaME9XWitGUi9WNTZVQW1FMG1DenhZU0ZmeXlZakVEMjZFT2NvOWxpZGlqVmlHNC8rWVVUYzMwRGVySHpIdURzKzFiRDl4TmM1TUp2VTBOUlJZUlAyV0ZVL2kvVk10L0NsbXNFYVZwT3NSU082dFNNa2prQ0ZsclZ4NTltbU1CVE5lR09Bck93V2J1Y3c9PQAAAQBAD9GxJeiZQonVdEVrn5+frA3tMD18Stcp3fiHVGVdXRzbHQd3N23tTXSyXlqQo0lB/dDt1A4iKh8/Wotp38mFkYq/W/HbJC3hYkJaOQwBPO0aelWYTi4hAxw7c8HSjLf2S4J0dK7LYRW9vfuaK/YrCr42fOGsZ3GX+9WcwbBWT6ONnaJa2dMQRnDsrmcE599LiEz++8GvICWhzfGxjcHk4lsEGmFBC1FajDQsGf/d7oCI3EiNodgSMHtP3u6DZCt8h036wn4gyv5XdH3YauUltsKDmYqGFfD/Udy4kmiKR5qExX4i/K+7q+p4TVJ3GHqgVwtdXGkKiq32qXEqktj6", "start_date_in_millis": 1642291200000 } }
|
好了license.json文件已经OK了.
接下来导入License请确保
1 2
| xpack.security.enabled: false xpack.security.transport.ssl.enabled: false
|
等更新完升级为白金后再开启配置。
然后加载License到ES中:
1 2 3
| $ curl -XPUT -u elastic 'http://localhost:9200/_xpack/license' -H "Content-Type: application/json" -d @license.json Enter host password for user 'elastic': # 输入elastic用户密码 {"acknowledged":true,"license_status":"valid"} # license写入成功
|
查看License:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| $ curl -XGET -uelastic http://localhost:9200/_license Enter host password for user 'elastic': { "license" : { "status" : "active", "uid" : "92c6b41e-59f9-4674-b227-77063c5fa8b0", "type" : "platinum", "issue_date" : "2019-11-29T00:00:00.000Z", "issue_date_in_millis" : 1558051200000, "expiry_date" : "2068-06-24T14:50:00.999Z", "expiry_date_in_millis" : 2524579200999, "max_nodes" : 1000, "issued_to" : "pyker", "issuer" : "Web Form", "start_date_in_millis" : 1558051200000 } }
|
最后,确保 elasticsearch 和 kibana均重启。单独elasticsearch,不重启kibana,会导致进入kibana时候提示 license无效。
kibana查看许可
专题目录
ElasticStack-安装篇
ElasticStack-elasticsearch篇
ElasticStack-logstash篇
elasticSearch-mapping相关
elasticSearch-分词器介绍
elasticSearch-分词器实践笔记
elasticSearch-同义词分词器自定义实践
docker-elk集群实践
filebeat与logstash实践
filebeat之pipeline实践
Elasticsearch 7.x 白金级 破解实践
elk的告警调研与实践