简介: x-pack是elasticsearch的一个收费的扩展包,将权限管理,警告,监视等功能捆绑在一个易于安装的软件包中,x-pack被设计为一个无缝的工作,但是你可以轻松的启用或者关闭一些功能。如果购买商业版需要每年支付十多万。为了使用几个不可或缺功能而花大钱去购买,有点不值得,特别是对于中小型企业来说。所以我在这里主要通过如何破解来启用x-pack的一些功能,本文章仅供技术分享,禁止商业用途! |
反编译
x-pack是收费项目,想启动它需要破解,本文以7.X 版本为例进行破解。
x-pack从6.4版本后就内置在elasticsearch中,使用只需要把配置打开即可(官方有30天的试用期)。
x-pack的lisence校验在elasticsearch-7.0.0/modules/x-pack-core的x-pack-core-7.0.0.jar中,破解之前需要用反编译工具(如:JD-GUI)把jar打开源码出来,我这里使用idea反编译。
修改X-pack相关源码
x-pack的lisence的校验主要是这两个文件:
- 验证licence是否有效:
org.elasticsearch.license.LicenseVerifier
验证jar包是否被修改:
org.elasticsearch.xpack.core.XPackBuild
反编译源码出来后需要把这两个类的源码提取出来放到新创建同名的java文件里,此时这两个类引用的java类很多不识别怎么办?需要把elasticsearch相关的jar包引进来,然后就可以编译替换目标class了。
修改LicenseVerifier.java
两个静态方法修改为全部返回true
改前 |
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 );
}
}
}
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);
}
}
|
|
改后 |
package org.elasticsearch.license;
public class LicenseVerifier
{
public static boolean verifyLicense( final License license, final byte [] array) {
return true ;
}
public static boolean verifyLicense( final License license) {
return true ;
}
}
|
|
修改XPackBuild.java
最后一个静态代码块中 try的部分全部删除
改前 |
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);
}
}
|
|
改后 |
package org.elasticsearch.xpack.core;
import java.nio.file.*;
import org.elasticsearch.common.io.*;
import java.net.*;
import org.elasticsearch.common.*;
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 location = XPackBuild. class .getProtectionDomain().getCodeSource().getLocation();
try {
return PathUtils.get(location.toURI());
}
catch (URISyntaxException ex) {
throw new RuntimeException(ex);
}
}
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 {
getElasticsearchCodebase();
CURRENT = new XPackBuild( "Unknown" , "Unknown" );
}
}
|
|
替换目标文件
把上面修改编译出来的LicenseVerifier.class和XPackBuild.class替换./elasticsearch-7.0.0/modules/x-pack-core/x-pack-core-7.0.0.jar。
替换步骤:
- 查找文件:jar -tvf x-pack-core-7.0.0-new.jar |grep LicenseVerifier
- 找到后解压:jar -xvf x-pack-core-7.0.0-new.jar |grep org/elasticsearch/license/LicenseVerifier.class
- 手动把自己修改后编译生成的class覆盖解压出来的文件,然后压回jar包:jar -uvf x-pack-core-7.0.0.jar org/elasticsearch/license/LicenseVerifier.class
- 最后把替换好的jar包替换elasticsearch下的x-pack-core-7.0.0.jar包
申请license
去官网(https://license.elastic.co/registration)申请license后,下载下来是这种格式:
{"license":{"uid":"864c20ea-b26f-4f1d-bfe5-4f02a26f90a9","type":"platinum","issue_date_in_millis":1570752000000,"expiry_date_in_millis":2524579200999,"max_nodes":100,"issued_to":"deng pang (yiren)","issuer":"Web Form","signature":"AAAAAwAAAA3m1fB/yRfUho18V4FpAAABmC9ZN0hjZDBGYnVyRXpCOW5Bb3FjZDAxOWpSbTVoMVZwUzRxVk1PSmkxaktJRVl5MUYvUWh3bHZVUTllbXNPbzBUemtnbWpBbmlWRmRZb25KNFlBR2x0TXc2K2p1Y1VtMG1UQU9TRGZVSGRwaEJGUjE3bXd3LzRqZ05iLzRteWFNekdxRGpIYlFwYkJiNUs0U1hTVlJKNVlXekMrSlVUdFIvV0FNeWdOYnlESDc3MWhlY3hSQmdKSjJ2ZTcvYlBFOHhPQlV3ZHdDQ0tHcG5uOElCaDJ4K1hob29xSG85N0kvTWV3THhlQk9NL01VMFRjNDZpZEVXeUtUMXIyMlIveFpJUkk2WUdveEZaME9XWitGUi9WNTZVQW1FMG1DenhZU0ZmeXlZakVEMjZFT2NvOWxpZGlqVmlHNC8rWVVUYzMwRGVySHpIdURzKzFiRDl4TmM1TUp2VTBOUlJZUlAyV0ZVL2kvVk10L0NsbXNFYVZwT3NSU082dFNNa2prQ0ZsclZ4NTltbU1CVE5lR09Bck93V2J1Y3c9PQAAAQB4zgpe5lluBbJYaQBWNDxrK0J9V4fnb8KWMmgIGj7ymw++bvV9rkmNtjDixWZkdSbWVQr0WLBpZoye+yQCqWB559BTqinUmIazgRpVFtaggN4RXgJA6V/N9NgOv0Vw0DvN9FI2aU5iRv7nXaNmpkMPlaCngI+2F3FoBuF9GyHsXYaOqDYkMdazT3W757QnP58ZCQT9S98gIcU75yqyWlKZek8UlUtUxSCSTtOyMtWrwag238/OgXv8BlmtQcH9A/XQBmAQlkzbgBVBkWoS0w2aqCM4Q3X7qTOH/Ea+xT/IJVhZgeTXh947kW1unEBEfwF6GZQkQQW+4pH6GEtCGTO/","start_date_in_millis":1570752000000}}
|
许可证书分有三类GOLD(黄金),PLATINUM(白金),ENTERPRISE(企业),我上面把type手动改成了白金版,然后再把过期时间改到了2050年
禁用elasticsearch安全协议
导出许可证书之前要先关闭xpack安全认证,打开../config/elasticsearch.yml文件在末尾添加:xpack.security.enabled: false
并启动elasticsearch服务:./bin/elasticsearch -d
导入license
curl - XPUT - u elastic 'http://192.168.1.9:9200/_xpack/license' - H "Content-Type: application/json" - d @license.json
|
导入成功后再把xpack安全认证打开:
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
内置账号创建密码
使用内置帐号需要设置密码,执行命令:./bin/elasticsearch-setup-passwords interactive 按提示输入密码
修改kibanna内置账号
安全认证开启后,只有配置了帐号信息才能使用,vi kibana.yml
elasticsearch.username: "kibana"
elasticsearch.password: "xxxxxx"
重启Kibana
以上配置完成后,重启kibana并访问,此时需要帐号登录
看到上面许可的有效期,说明我们已经破解成功并可以使用权限功能和告警功能了。完成!!!