Check for valid session before starting a new thread

This could reduce load for malicious senders as there have to be session
active to start the expensive operation of creating a new thread.
This commit is contained in:
games647
2022-06-07 19:29:06 +02:00
parent 7cab5993b7
commit 32fe2cdf4e
2 changed files with 38 additions and 31 deletions

View File

@ -30,6 +30,7 @@ import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.core.antibot.AntiBotService;
import com.github.games647.fastlogin.core.antibot.AntiBotService.Action;
@ -124,9 +125,15 @@ public class ProtocolLibListener extends PacketAdapter {
private void onEncryptionBegin(PacketEvent packetEvent, Player sender) {
byte[] sharedSecret = packetEvent.getPacket().getByteArrays().read(0);
packetEvent.getAsyncMarker().incrementProcessingDelay();
Runnable verifyTask = new VerifyResponseTask(plugin, packetEvent, sender, sharedSecret, keyPair);
plugin.getScheduler().runAsync(verifyTask);
BukkitLoginSession session = plugin.getSession(sender.getAddress());
if (session == null) {
plugin.getLog().warn("GameProfile {} tried to send encryption response at invalid state", sender.getAddress());
sender.kickPlayer(plugin.getCore().getMessage("invalid-request"));
} else {
packetEvent.getAsyncMarker().incrementProcessingDelay();
Runnable verifyTask = new VerifyResponseTask(plugin, packetEvent, sender, session, sharedSecret, keyPair);
plugin.getScheduler().runAsync(verifyTask);
}
}
private void onLogin(PacketEvent packetEvent, Player player, String username) {

View File

@ -79,16 +79,20 @@ public class VerifyResponseTask implements Runnable {
private final Player player;
private final BukkitLoginSession session;
private final byte[] sharedSecret;
private static Method encryptMethod;
private static Method cipherMethod;
public VerifyResponseTask(FastLoginBukkit plugin, PacketEvent packetEvent, Player player,
public VerifyResponseTask(FastLoginBukkit plugin, PacketEvent packetEvent,
Player player, BukkitLoginSession session,
byte[] sharedSecret, KeyPair keyPair) {
this.plugin = plugin;
this.packetEvent = packetEvent;
this.player = player;
this.session = session;
this.sharedSecret = Arrays.copyOf(sharedSecret, sharedSecret.length);
this.serverKey = keyPair;
}
@ -96,14 +100,7 @@ public class VerifyResponseTask implements Runnable {
@Override
public void run() {
try {
BukkitLoginSession session = plugin.getSession(player.getAddress());
if (session == null) {
disconnect("invalid-request",
"GameProfile {0} tried to send encryption response at invalid state",
player.getAddress());
} else {
verifyResponse(session);
}
verifyResponse(session);
} finally {
//this is a fake packet; it shouldn't be sent to the server
synchronized (packetEvent.getAsyncMarker().getProcessingLock()) {
@ -143,25 +140,7 @@ public class VerifyResponseTask implements Runnable {
InetAddress address = socketAddress.getAddress();
Optional<Verification> response = resolver.hasJoined(requestedUsername, serverId, address);
if (response.isPresent()) {
Verification verification = response.get();
plugin.getLog().info("Profile {} has a verified premium account", requestedUsername);
String realUsername = verification.getName();
if (realUsername == null) {
disconnect("invalid-session", "Username field null for {}", requestedUsername);
return;
}
SkinProperty[] properties = verification.getProperties();
if (properties.length > 0) {
session.setSkinProperty(properties[0]);
}
session.setVerifiedUsername(realUsername);
session.setUuid(verification.getId());
session.setVerified(true);
setPremiumUUID(session.getUuid());
receiveFakeStartPacket(realUsername);
encryptConnection(session, requestedUsername, response.get());
} else {
//user tried to fake an authentication
disconnect("invalid-session", "GameProfile {} ({}) tried to log in with an invalid session. ServerId: {}", session.getRequestUsername(), socketAddress, serverId);
@ -171,6 +150,27 @@ public class VerifyResponseTask implements Runnable {
}
}
private void encryptConnection(BukkitLoginSession session, String requestedUsername, Verification verification) {
plugin.getLog().info("Profile {} has a verified premium account", requestedUsername);
String realUsername = verification.getName();
if (realUsername == null) {
disconnect("invalid-session", "Username field null for {}", requestedUsername);
return;
}
SkinProperty[] properties = verification.getProperties();
if (properties.length > 0) {
session.setSkinProperty(properties[0]);
}
session.setVerifiedUsername(realUsername);
session.setUuid(verification.getId());
session.setVerified(true);
setPremiumUUID(session.getUuid());
receiveFakeStartPacket(realUsername);
}
private void setPremiumUUID(UUID premiumUUID) {
if (plugin.getConfig().getBoolean("premiumUuid") && premiumUUID != null) {
try {