Skip to content

Commit c254f72

Browse files
committed
Fix security issue with accidently leaked token
1 parent 95b91d9 commit c254f72

13 files changed

Lines changed: 40 additions & 269 deletions

File tree

SECURITY.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,9 @@ This page will be updated with any notices about security issues in BungeeGuard.
1010
* `v1.2.0` released which fixes a security issue in the BungeeGuard Spigot plugin.
1111
* The issue allowed malicious users to bypass BungeeGuard's authentication checks.
1212
* All releases prior to `1.2` are affected.
13+
14+
#### #002 - 2nd June 2025
15+
* `v1.4.0` released which fixes a security issue in the BungeeGuard BungeeCord plugin.
16+
* An issue introduced in BungeeCord build 1756 caused the BungeeGuard token to be leaked to players using Minecraft 1.20.2 or higher via the LoginSuccess packet.
17+
* This issue only affects BungeeGuard setups using BungeeCord, it does not affect Velocity proxies.
18+
* Affected users are recommended to update to BungeeGuard `v1.4.0` or later on their proxy, and rotate their BungeeGuard tokens.

bungeeguard-backend/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<parent>
88
<groupId>me.lucko</groupId>
99
<artifactId>bungeeguard</artifactId>
10-
<version>1.3-SNAPSHOT</version>
10+
<version>1.4-SNAPSHOT</version>
1111
</parent>
1212

1313
<artifactId>bungeeguard-backend</artifactId>

bungeeguard-bungee-java9/pom.xml

Lines changed: 0 additions & 53 deletions
This file was deleted.

bungeeguard-bungee-java9/src/main/java/me/lucko/bungeeguard/bungee/SpoofedLoginResultJava9.java

Lines changed: 0 additions & 49 deletions
This file was deleted.

bungeeguard-bungee/pom.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,16 @@
77
<parent>
88
<groupId>me.lucko</groupId>
99
<artifactId>bungeeguard</artifactId>
10-
<version>1.3-SNAPSHOT</version>
10+
<version>1.4-SNAPSHOT</version>
1111
</parent>
1212

1313
<artifactId>bungeeguard-bungee</artifactId>
1414

15+
<properties>
16+
<maven.compiler.source>9</maven.compiler.source>
17+
<maven.compiler.target>9</maven.compiler.target>
18+
</properties>
19+
1520
<build>
1621
<resources>
1722
<resource>

bungeeguard-bungee/src/main/java/me/lucko/bungeeguard/bungee/SpoofedLoginResult.java

Lines changed: 18 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import net.md_5.bungee.connection.LoginResult;
3131
import net.md_5.bungee.protocol.Property;
3232

33-
import java.lang.reflect.Constructor;
3433
import java.lang.reflect.Field;
3534
import java.util.Arrays;
3635

@@ -41,32 +40,15 @@
4140
* To achieve this, the stack trace is analyzed. This is kinda crappy, but is the only way
4241
* to modify the properties without leaking the token to other clients via the tablist.
4342
*/
44-
abstract class SpoofedLoginResult extends LoginResult {
43+
class SpoofedLoginResult extends LoginResult {
4544
private static final Field PROFILE_FIELD;
46-
private static final Constructor<? extends SpoofedLoginResult> OFFLINE_MODE_IMPL;
47-
private static final Constructor<? extends SpoofedLoginResult> ONLINE_MODE_IMPL;
4845

49-
static {
50-
Class<? extends SpoofedLoginResult> implClass;
51-
if (classExists("java.lang.StackWalker")) {
52-
try {
53-
implClass = Class.forName("me.lucko.bungeeguard.bungee.SpoofedLoginResultJava9")
54-
.asSubclass(SpoofedLoginResult.class);
55-
} catch (ClassNotFoundException e) {
56-
throw new RuntimeException(e);
57-
}
58-
} else if (classExists("jdk.internal.reflect.Reflection")) {
59-
implClass = SpoofedLoginResultJdkInternal.class;
60-
} else {
61-
implClass = SpoofedLoginResultReflection.class;
62-
}
46+
private static final StackWalker STACK_WALKER = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
6347

48+
static {
6449
try {
6550
PROFILE_FIELD = InitialHandler.class.getDeclaredField("loginProfile");
6651
PROFILE_FIELD.setAccessible(true);
67-
68-
OFFLINE_MODE_IMPL = implClass.getConstructor(String.class);
69-
ONLINE_MODE_IMPL = implClass.getConstructor(LoginResult.class, String.class);
7052
} catch (ReflectiveOperationException e) {
7153
throw new ExceptionInInitializerError(e);
7254
}
@@ -76,15 +58,11 @@ static void inject(InitialHandler handler, String token) {
7658
LoginResult profile = handler.getLoginProfile();
7759
LoginResult newProfile;
7860

79-
try {
80-
// profile is null for offline mode servers
81-
if (profile == null) {
82-
newProfile = OFFLINE_MODE_IMPL.newInstance(token);
83-
} else {
84-
newProfile = ONLINE_MODE_IMPL.newInstance(profile, token);
85-
}
86-
} catch (ReflectiveOperationException e) {
87-
throw new RuntimeException(e);
61+
// profile is null for offline mode servers
62+
if (profile == null) {
63+
newProfile = new SpoofedLoginResult(token);
64+
} else {
65+
newProfile = new SpoofedLoginResult(profile, token);
8866
}
8967

9068
try {
@@ -94,15 +72,6 @@ static void inject(InitialHandler handler, String token) {
9472
}
9573
}
9674

97-
private static boolean classExists(String className) {
98-
try {
99-
Class.forName(className);
100-
return true;
101-
} catch (ClassNotFoundException e) {
102-
return false;
103-
}
104-
}
105-
10675
private final Property bungeeGuardToken;
10776
private final Property[] bungeeGuardTokenArray;
10877
private final boolean offline;
@@ -123,9 +92,17 @@ protected SpoofedLoginResult(String bungeeGuardToken) {
12392
this.offline = true;
12493
}
12594

126-
protected Property[] getSpoofedProperties(Class<?> caller) {
95+
@Override
96+
public Property[] getProperties() {
97+
StackWalker.StackFrame frame = STACK_WALKER.walk(s ->
98+
// find the first frame that starts with "net.md_5.bungee"
99+
s.dropWhile(f -> !f.getClassName().startsWith("net.md_5.bungee"))
100+
.findFirst()
101+
.orElse(null)
102+
);
103+
127104
// if the getProperties method is being called by the server connector, include our token in the properties
128-
if (caller == ServerConnector.class) {
105+
if (frame != null && frame.getDeclaringClass() == ServerConnector.class && frame.getMethodName().equals("connected")) {
129106
return addTokenProperty(super.getProperties());
130107
} else {
131108
return super.getProperties();

bungeeguard-bungee/src/main/java/me/lucko/bungeeguard/bungee/SpoofedLoginResultJdkInternal.java

Lines changed: 0 additions & 50 deletions
This file was deleted.

bungeeguard-bungee/src/main/java/me/lucko/bungeeguard/bungee/SpoofedLoginResultReflection.java

Lines changed: 0 additions & 58 deletions
This file was deleted.

bungeeguard-spigot-legacy/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
<parent>
88
<groupId>me.lucko</groupId>
99
<artifactId>bungeeguard</artifactId>
10-
<version>1.3-SNAPSHOT</version>
10+
<version>1.4-SNAPSHOT</version>
1111
</parent>
1212

1313
<artifactId>bungeeguard-spigot-legacy</artifactId>
14-
<version>1.3-SNAPSHOT</version>
14+
<version>1.4-SNAPSHOT</version>
1515

1616
<build>
1717
<resources>

bungeeguard-spigot/pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
<parent>
88
<groupId>me.lucko</groupId>
99
<artifactId>bungeeguard</artifactId>
10-
<version>1.3-SNAPSHOT</version>
10+
<version>1.4-SNAPSHOT</version>
1111
</parent>
1212

1313
<artifactId>bungeeguard-spigot</artifactId>
14-
<version>1.3-SNAPSHOT</version>
14+
<version>1.4-SNAPSHOT</version>
1515

1616
<build>
1717
<resources>
@@ -46,7 +46,7 @@
4646
<dependency>
4747
<groupId>me.lucko</groupId>
4848
<artifactId>bungeeguard-spigot-legacy</artifactId>
49-
<version>1.3-SNAPSHOT</version>
49+
<version>1.4-SNAPSHOT</version>
5050
<scope>compile</scope>
5151
</dependency>
5252
</dependencies>

0 commit comments

Comments
 (0)