Initial mitigation for folks updating Dynmap but not patching MC for

some reason
This commit is contained in:
Mike Primm 2021-12-23 14:27:33 -06:00
parent 895dcf3244
commit 9e602f50d6
3 changed files with 61 additions and 8 deletions

View File

@ -141,6 +141,7 @@ public class DynmapCore implements DynmapCommonAPI {
private boolean loginRequired;
private String hackAttemptSub = "(IaM5uchA1337Haxr-Ban Me!)";
// WEBP support
private String cwebpPath;
private String dwebpPath;
@ -599,11 +600,13 @@ public class DynmapCore implements DynmapCommonAPI {
updateConfigHashcode(); /* Initialize/update config hashcode */
loginRequired = configuration.getBoolean("login-required", false);
hackAttemptSub = configuration.getString("hackAttemptBlurb", "(IaM5uchA1337Haxr-Ban Me!)");
// If not disabled, load and initialize the internal web server
if (!isInternalWebServerDisabled) {
loadWebserver();
}
enabledTriggers.clear();
List<String> triggers = configuration.getStrings("render-triggers", new ArrayList<String>());
@ -2297,13 +2300,60 @@ public class DynmapCore implements DynmapCommonAPI {
public String getDefImageFormat() { return def_image_format; }
public String scanAndReplaceLog4JMacro(String msg) {
int nestcnt = 0;
int off = 0;
int firsthit = -1;
boolean done = false;
String orig = msg;
while (!done) {
int idx = msg.indexOf("${", off); // Look for next ${
if (idx >= 0) { // Hit
if (nestcnt == 0) firsthit = idx; // Record start of hit
nestcnt++;
off = idx + 2;
}
else {
idx = msg.indexOf("}", off); // Next }
if (idx >= 0) {
if (nestcnt > 0) {
nestcnt--;
if ((nestcnt == 0) && (firsthit >= 0)) { // If back to zero, time to strip it
String newmsg = msg.substring(0, firsthit) + hackAttemptSub + msg.substring(idx+1);
msg = newmsg; // Switch to new version, and restart
off = 0;
firsthit = -1; // And restart scan
}
}
off = idx + 1;
}
else { // At end without a close
if (firsthit >= 0) { // Open strip?
String newmsg = msg.substring(0, firsthit) + hackAttemptSub; // Replace rest
msg = newmsg; // Switch to new version, and restart
}
done = true;
}
}
}
return msg;
}
public void webChat(final String name, final String message) {
if(mapManager == null)
return;
// Check for folks trying to exploit Log4J
final String cleanname = scanAndReplaceLog4JMacro(name);
final String cleanmsg = scanAndReplaceLog4JMacro(message);
if (!cleanname.equals(name)) {
Log.severe("Possible hack attempt blocked: name contains Log4J macro - " + name.replaceAll("\\$", "_"));
}
if (!cleanmsg.equals(message)) {
Log.severe("Possible hack attempt blocked: message contains Log4J macro (from " + cleanname + ") - " + message.replaceAll("\\$", "_"));
}
Runnable c = new Runnable() {
@Override
public void run() {
ChatEvent event = new ChatEvent("web", name, message);
ChatEvent event = new ChatEvent("web", cleanname, cleanmsg);
events.trigger("webchat", event);
}
};

View File

@ -49,6 +49,8 @@ public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
private MapStorage storage;
private File baseStandaloneDir;
private String safeString(String s) { return s.replaceAll("\\$", "_"); }
private static class FileToWrite {
String filename;
byte[] content;
@ -420,17 +422,17 @@ public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
isip = false;
if(checkuserban) {
if(core.getServer().isPlayerBanned(name)) {
Log.info("Ignore message from '" + ip + "' - banned player (" + name + ")");
Log.info("Ignore message from '" + ip + "' - banned player (" + safeString(name) + ")");
ok = false;
}
}
if(chat_perms && !core.getServer().checkPlayerPermission(name, "webchat")) {
Log.info("Rejected web chat from " + ip + ": not permitted (" + name + ")");
Log.info("Rejected web chat from " + ip + ": not permitted (" + safeString(name) + ")");
ok = false;
}
}
else if(requireplayerloginip) {
Log.info("Ignore message from '" + name + "' - no matching player login recorded");
Log.info("Ignore message from '" + safeString(name) + "' - no matching player login recorded");
ok = false;
}
}

View File

@ -52,6 +52,7 @@ public class SendMessageServlet extends HttpServlet {
public DynmapCore core;
public HashSet<String> proxyaddress = new HashSet<String>();
private String safeString(String s) { return s.replaceAll("\\$", "_"); }
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
byte[] bytes;
@ -65,7 +66,7 @@ public class SendMessageServlet extends HttpServlet {
}
else if(chat_requires_login && (!userID.equals(LoginServlet.USERID_GUEST)) && chat_perms &&
(!core.checkPermission(userID, "webchat"))) {
Log.info("Rejected web chat by " + userID + ": not permitted");
Log.info("Rejected web chat by " + safeString(userID) + ": not permitted");
error = "not-permitted";
}
else {
@ -118,20 +119,20 @@ public class SendMessageServlet extends HttpServlet {
String id = ids.get(0);
if (check_user_ban) {
if (core.getServer().isPlayerBanned(id)) {
Log.info("Ignore message from '" + message.name + "' - banned player (" + id + ")");
Log.info("Ignore message from '" + safeString(message.name) + "' - banned player (" + id + ")");
error = "not-allowed";
ok = false;
}
}
if (chat_perms && !core.getServer().checkPlayerPermission(id, "webchat")) {
Log.info("Rejected web chat from '" + message.name + "': not permitted (" + id + ")");
Log.info("Rejected web chat from '" + safeString(message.name) + "': not permitted (" + id + ")");
error = "not-allowed";
ok = false;
}
message.name = id;
isip = false;
} else if (require_player_login_ip) {
Log.info("Ignore message from '" + message.name + "' - no matching player login recorded");
Log.info("Ignore message from '" + safeString(message.name) + "' - no matching player login recorded");
error = "not-allowed";
ok = false;
}