diff --git a/README.md b/README.md index a4d79ef..70d91e8 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,6 @@ See [INSTALLATION.md](INSTALLATION.md) for a detailed install guide. ## License -BungeeGuard is licensed and made available under the permissive MIT license. Please see [LICENSE.txt](LICENSE.md) for more information. +BungeeGuard is licensed and made available under the permissive MIT license. Please see [LICENSE.txt](LICENSE.txt) for more information. Details about vulnerability reporting & security disclosures can be found in [SECURITY.md](SECURITY.md). diff --git a/bungeeguard-bungee-java9/pom.xml b/bungeeguard-bungee-java9/pom.xml new file mode 100644 index 0000000..ba459ba --- /dev/null +++ b/bungeeguard-bungee-java9/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + + me.lucko + bungeeguard + 1.2-SNAPSHOT + + + bungeeguard-bungee-java9 + + + 9 + 9 + + + + + me.lucko + bungeeguard-bungee + 1.2-SNAPSHOT + provided + + + net.md-5 + bungeecord-api + ${bungee.version} + provided + + + net.md-5 + bungeecord-proxy + ${bungee.version} + provided + + + + \ No newline at end of file diff --git a/bungeeguard-bungee-java9/src/main/java/me/lucko/bungeeguard/bungee/SpoofedLoginResultJava9.java b/bungeeguard-bungee-java9/src/main/java/me/lucko/bungeeguard/bungee/SpoofedLoginResultJava9.java new file mode 100644 index 0000000..8500bb5 --- /dev/null +++ b/bungeeguard-bungee-java9/src/main/java/me/lucko/bungeeguard/bungee/SpoofedLoginResultJava9.java @@ -0,0 +1,55 @@ +/* + * This file is part of BungeeGuard, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.bungeeguard.bungee; + +import net.md_5.bungee.ServerConnector; +import net.md_5.bungee.connection.LoginResult; + +public class SpoofedLoginResultJava9 extends SpoofedLoginResult { + private static final StackWalker STACK_WALKER = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); + + // online mode constructor + public SpoofedLoginResultJava9(LoginResult oldProfile, String extraToken) { + super(oldProfile, extraToken); + } + + // offline mode constructor + public SpoofedLoginResultJava9(String extraToken) { + super(extraToken); + } + + @Override + public LoginResult.Property[] getProperties() { + Class caller = STACK_WALKER.getCallerClass(); + + // if the getProperties method is being called by the server connector, include our token in the properties + if (caller == ServerConnector.class) { + return addTokenProperty(super.getProperties()); + } else { + return super.getProperties(); + } + } +} diff --git a/bungeeguard-bungee/src/main/java/me/lucko/bungeeguard/bungee/SpoofedLoginResult.java b/bungeeguard-bungee/src/main/java/me/lucko/bungeeguard/bungee/SpoofedLoginResult.java index fce9e48..8fd567a 100644 --- a/bungeeguard-bungee/src/main/java/me/lucko/bungeeguard/bungee/SpoofedLoginResult.java +++ b/bungeeguard-bungee/src/main/java/me/lucko/bungeeguard/bungee/SpoofedLoginResult.java @@ -25,11 +25,12 @@ package me.lucko.bungeeguard.bungee; -import net.md_5.bungee.ServerConnector; import net.md_5.bungee.connection.InitialHandler; import net.md_5.bungee.connection.LoginResult; +import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.util.Arrays; /** @@ -39,25 +40,62 @@ * To achieve this, the stack trace is analyzed. This is kinda crappy, but is the only way * to modify the properties without leaking the token to other clients via the tablist. */ -class SpoofedLoginResult extends LoginResult { - private static final StackWalker STACK_WALKER = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); - +abstract class SpoofedLoginResult extends LoginResult { private static final Field PROFILE_FIELD; + private static final Constructor OFFLINE_MODE_IMPL; + private static final Constructor ONLINE_MODE_IMPL; + static { + Class implClass; + try { + // try to use stackwalker if running Java 9 or newer + Class.forName("java.lang.StackWalker"); + implClass = Class.forName("me.lucko.bungeeguard.bungee.SpoofedLoginResultJava9").asSubclass(SpoofedLoginResult.class); + //System.out.println("[BungeeGuard] Using Java 9 (StackWalker) to spoof profile properties."); + } catch (ClassNotFoundException e) { + implClass = SpoofedLoginResultJava8.class; + //System.out.println("[BungeeGuard] Using Java 8 (Reflection/Stacktrace) to spoof profile properties."); + } + try { PROFILE_FIELD = InitialHandler.class.getDeclaredField("loginProfile"); PROFILE_FIELD.setAccessible(true); - } catch (NoSuchFieldException e) { + + OFFLINE_MODE_IMPL = implClass.getConstructor(String.class); + ONLINE_MODE_IMPL = implClass.getConstructor(LoginResult.class, String.class); + } catch (ReflectiveOperationException e) { throw new ExceptionInInitializerError(e); } } + static void inject(InitialHandler handler, String token) { + LoginResult profile = handler.getLoginProfile(); + LoginResult newProfile; + + try { + // profile is null for offline mode servers + if (profile == null) { + newProfile = OFFLINE_MODE_IMPL.newInstance(token); + } else { + newProfile = ONLINE_MODE_IMPL.newInstance(profile, token); + } + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + + try { + PROFILE_FIELD.set(handler, newProfile); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + private final String extraToken; private final Property[] justExtraToken; private final boolean offline; // online mode constructor - private SpoofedLoginResult(LoginResult oldProfile, String extraToken) { + protected SpoofedLoginResult(LoginResult oldProfile, String extraToken) { super(oldProfile.getId(), oldProfile.getName(), oldProfile.getProperties()); this.extraToken = extraToken; this.justExtraToken = new Property[]{new Property("bungeeguard-token", this.extraToken, "")}; @@ -65,27 +103,14 @@ private SpoofedLoginResult(LoginResult oldProfile, String extraToken) { } // offline mode constructor - private SpoofedLoginResult(String extraToken) { + protected SpoofedLoginResult(String extraToken) { super(null, null, new Property[0]); this.extraToken = extraToken; this.justExtraToken = new Property[]{new Property("bungeeguard-token", this.extraToken, "")}; this.offline = true; } - @Override - public Property[] getProperties() { - // there's no way this is the best way to do this, but idfk - Class caller = STACK_WALKER.getCallerClass(); - - // if the getProperties method is being called by the server connector, include our token in the properties - if (caller == ServerConnector.class) { - return addTokenProperty(super.getProperties()); - } else { - return super.getProperties(); - } - } - - private Property[] addTokenProperty(Property[] properties) { + protected Property[] addTokenProperty(Property[] properties) { if (properties.length == 0) { return this.justExtraToken; } @@ -110,22 +135,4 @@ public String getName() { } return super.getId(); } - - static void inject(InitialHandler handler, String token) { - LoginResult profile = handler.getLoginProfile(); - LoginResult newProfile; - - // profile is null for offline mode servers - if (profile == null) { - newProfile = new SpoofedLoginResult(token); // offline mode constructor - } else { - newProfile = new SpoofedLoginResult(profile, token); // online mode constructor - } - - try { - PROFILE_FIELD.set(handler, newProfile); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } } diff --git a/bungeeguard-bungee/src/main/java/me/lucko/bungeeguard/bungee/SpoofedLoginResultJava8.java b/bungeeguard-bungee/src/main/java/me/lucko/bungeeguard/bungee/SpoofedLoginResultJava8.java new file mode 100644 index 0000000..cd52423 --- /dev/null +++ b/bungeeguard-bungee/src/main/java/me/lucko/bungeeguard/bungee/SpoofedLoginResultJava8.java @@ -0,0 +1,62 @@ +/* + * This file is part of BungeeGuard, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.bungeeguard.bungee; + +import net.md_5.bungee.connection.LoginResult; + +public class SpoofedLoginResultJava8 extends SpoofedLoginResult { + private static final String SERVER_CONNECTOR = "net.md_5.bungee.ServerConnector"; + private static final String SERVER_CONNECTOR_CONNECTED = "connected"; + + // online mode constructor + public SpoofedLoginResultJava8(LoginResult oldProfile, String extraToken) { + super(oldProfile, extraToken); + } + + // offline mode constructor + public SpoofedLoginResultJava8(String extraToken) { + super(extraToken); + } + + @Override + public Property[] getProperties() { + // there's no way this is the best way to do this, but idfk + StackTraceElement[] trace = new Exception().getStackTrace(); + + if (trace.length < 2) { + return super.getProperties(); + } + + StackTraceElement callLocation = trace[1]; + + // if the getProperties method is being called by the server connector, include our token in the properties + if (callLocation.getClassName().equals(SERVER_CONNECTOR) && callLocation.getMethodName().equals(SERVER_CONNECTOR_CONNECTED)) { + return addTokenProperty(super.getProperties()); + } else { + return super.getProperties(); + } + } +} diff --git a/bungeeguard-bungee/src/main/resources/bungee.yml b/bungeeguard-bungee/src/main/resources/bungee.yml index cef7e4e..d775d55 100644 --- a/bungeeguard-bungee/src/main/resources/bungee.yml +++ b/bungeeguard-bungee/src/main/resources/bungee.yml @@ -1,5 +1,5 @@ name: BungeeGuard version: ${project.version} -description: Plugin which adds a security token to the BungeeCord handshaking protocol +description: A plugin-based security/firewall solution for BungeeCord and Velocity proxies. author: Luck main: me.lucko.bungeeguard.bungee.BungeeGuardProxyPlugin diff --git a/bungeeguard-spigot/src/main/resources/config.yml b/bungeeguard-spigot/src/main/resources/config.yml index 69d52e9..71df7bd 100644 --- a/bungeeguard-spigot/src/main/resources/config.yml +++ b/bungeeguard-spigot/src/main/resources/config.yml @@ -1,9 +1,9 @@ # BungeeGuard Configuration # Allowed authentication tokens. -allowed-tokens: [] -# - "the token generated by the proxy goes here" -# - "you can add as many as you like." +allowed-tokens: + - "the token generated by the proxy goes here" + - "you can add as many as you like." # Messages diff --git a/bungeeguard-spigot/src/main/resources/plugin.yml b/bungeeguard-spigot/src/main/resources/plugin.yml index 3c11ad2..a062e8c 100644 --- a/bungeeguard-spigot/src/main/resources/plugin.yml +++ b/bungeeguard-spigot/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: BungeeGuard version: ${project.version} -description: Plugin which adds a security token to the BungeeCord handshaking protocol +description: A plugin-based security/firewall solution for BungeeCord and Velocity proxies. author: Luck main: me.lucko.bungeeguard.spigot.BungeeGuardBackendPlugin diff --git a/bungeeguard-universal/pom.xml b/bungeeguard-universal/pom.xml index 940f53c..7ee99e8 100644 --- a/bungeeguard-universal/pom.xml +++ b/bungeeguard-universal/pom.xml @@ -49,6 +49,12 @@ 1.2-SNAPSHOT compile + + me.lucko + bungeeguard-bungee-java9 + 1.2-SNAPSHOT + compile + me.lucko bungeeguard-spigot diff --git a/pom.xml b/pom.xml index 8cc7dbc..daba6b2 100644 --- a/pom.xml +++ b/pom.xml @@ -11,6 +11,7 @@ bungeeguard-bungee + bungeeguard-bungee-java9 bungeeguard-spigot bungeeguard-universal @@ -19,8 +20,8 @@ UTF-8 - 9 - 9 + 1.8 + 1.8 1.15.2-R0.1-SNAPSHOT 1.15-SNAPSHOT