mirror of
https://github.com/AuthMe/AuthMeReloaded.git
synced 2024-10-31 07:39:42 +01:00
commit
4d2e48ede7
34
pom.xml
34
pom.xml
@ -76,6 +76,8 @@
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
<sourceDirectory>src/main/java</sourceDirectory>
|
||||
<testSourceDirectory>test/main/java</testSourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
@ -589,13 +591,33 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- String comparison library. Used for dynamic help system. -->
|
||||
<dependency>
|
||||
<groupId>net.ricecode</groupId>
|
||||
<artifactId>string-similarity</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<!-- Unit testing -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
<version>4.12</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>java-hamcrest</artifactId>
|
||||
<scope>test</scope>
|
||||
<version>2.0.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
<version>2.0.5-beta</version>
|
||||
</dependency>
|
||||
|
||||
<!-- String comparison library. Used for dynamic help system. -->
|
||||
<dependency>
|
||||
<groupId>net.ricecode</groupId>
|
||||
<artifactId>string-similarity</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -6,80 +6,50 @@ import org.apache.logging.log4j.core.LogEvent;
|
||||
import org.apache.logging.log4j.core.Logger;
|
||||
import org.apache.logging.log4j.message.Message;
|
||||
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* Implements a filter for Log4j to skip sensitive AuthMe commands.
|
||||
* @author Xephi59
|
||||
*/
|
||||
public class Log4JFilter implements org.apache.logging.log4j.core.Filter {
|
||||
|
||||
/** List of commands (lower-case) to skip. */
|
||||
private static final String[] COMMANDS_TO_SKIP = { "/login ", "/l ", "/reg ", "/changepassword ",
|
||||
"/unregister ", "/authme register ", "/authme changepassword ", "/authme reg ", "/authme cp ",
|
||||
"/register " };
|
||||
|
||||
/** Constructor. */
|
||||
public Log4JFilter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result filter(LogEvent record) {
|
||||
try {
|
||||
if (record == null || record.getMessage() == null)
|
||||
return Result.NEUTRAL;
|
||||
String logM = record.getMessage().getFormattedMessage().toLowerCase();
|
||||
if (!logM.contains("issued server command:"))
|
||||
return Result.NEUTRAL;
|
||||
if (!logM.contains("/login ") && !logM.contains("/l ") && !logM.contains("/reg ") && !logM.contains("/changepassword ") && !logM.contains("/unregister ") && !logM.contains("/authme register ") && !logM.contains("/authme changepassword ") && !logM.contains("/authme reg ") && !logM.contains("/authme cp ") && !logM.contains("/register "))
|
||||
return Result.NEUTRAL;
|
||||
return Result.DENY;
|
||||
} catch (NullPointerException npe) {
|
||||
return Result.NEUTRAL;
|
||||
}
|
||||
if (record == null) {
|
||||
return Result.NEUTRAL;
|
||||
}
|
||||
return validateMessage(record.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result filter(Logger arg0, Level arg1, Marker arg2, String message,
|
||||
Object... arg4) {
|
||||
try {
|
||||
if (message == null)
|
||||
return Result.NEUTRAL;
|
||||
String logM = message.toLowerCase();
|
||||
if (!logM.contains("issued server command:"))
|
||||
return Result.NEUTRAL;
|
||||
if (!logM.contains("/login ") && !logM.contains("/l ") && !logM.contains("/reg ") && !logM.contains("/changepassword ") && !logM.contains("/unregister ") && !logM.contains("/authme register ") && !logM.contains("/authme changepassword ") && !logM.contains("/authme reg ") && !logM.contains("/authme cp ") && !logM.contains("/register "))
|
||||
return Result.NEUTRAL;
|
||||
return Result.DENY;
|
||||
} catch (NullPointerException npe) {
|
||||
return Result.NEUTRAL;
|
||||
}
|
||||
return validateMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result filter(Logger arg0, Level arg1, Marker arg2, Object message,
|
||||
Throwable arg4) {
|
||||
try {
|
||||
if (message == null)
|
||||
return Result.NEUTRAL;
|
||||
String logM = message.toString().toLowerCase();
|
||||
if (!logM.contains("issued server command:"))
|
||||
return Result.NEUTRAL;
|
||||
if (!logM.contains("/login ") && !logM.contains("/l ") && !logM.contains("/reg ") && !logM.contains("/changepassword ") && !logM.contains("/unregister ") && !logM.contains("/authme register ") && !logM.contains("/authme changepassword ") && !logM.contains("/authme reg ") && !logM.contains("/authme cp ") && !logM.contains("/register "))
|
||||
return Result.NEUTRAL;
|
||||
return Result.DENY;
|
||||
} catch (NullPointerException npe) {
|
||||
return Result.NEUTRAL;
|
||||
}
|
||||
if (message == null) {
|
||||
return Result.NEUTRAL;
|
||||
}
|
||||
return validateMessage(message.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result filter(Logger arg0, Level arg1, Marker arg2, Message message,
|
||||
Throwable arg4) {
|
||||
try {
|
||||
if (message == null)
|
||||
return Result.NEUTRAL;
|
||||
String logM = message.getFormattedMessage().toLowerCase();
|
||||
if (!logM.contains("issued server command:"))
|
||||
return Result.NEUTRAL;
|
||||
if (!logM.contains("/login ") && !logM.contains("/l ") && !logM.contains("/reg ") && !logM.contains("/changepassword ") && !logM.contains("/unregister ") && !logM.contains("/authme register ") && !logM.contains("/authme changepassword ") && !logM.contains("/authme reg ") && !logM.contains("/authme cp ") && !logM.contains("/register "))
|
||||
return Result.NEUTRAL;
|
||||
return Result.DENY;
|
||||
} catch (NullPointerException npe) {
|
||||
return Result.NEUTRAL;
|
||||
}
|
||||
return validateMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -92,4 +62,39 @@ public class Log4JFilter implements org.apache.logging.log4j.core.Filter {
|
||||
return Result.NEUTRAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a Message instance and returns the {@link Result} value
|
||||
* depending depending on whether the message contains sensitive AuthMe
|
||||
* data.
|
||||
*
|
||||
* @param message the Message object to verify
|
||||
* @return the Result value
|
||||
*/
|
||||
private static Result validateMessage(Message message) {
|
||||
if (message == null) {
|
||||
return Result.NEUTRAL;
|
||||
}
|
||||
return validateMessage(message.getFormattedMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a message and returns the {@link Result} value depending
|
||||
* depending on whether the message contains sensitive AuthMe data.
|
||||
*
|
||||
* @param message the message to verify
|
||||
* @return the Result value
|
||||
*/
|
||||
private static Result validateMessage(String message) {
|
||||
if (message == null) {
|
||||
return Result.NEUTRAL;
|
||||
}
|
||||
|
||||
String lowerMessage = message.toLowerCase();
|
||||
if (lowerMessage.contains("issued server command:")
|
||||
&& StringUtils.containsAny(lowerMessage, COMMANDS_TO_SKIP)) {
|
||||
return Result.DENY;
|
||||
}
|
||||
return Result.NEUTRAL;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,4 +25,16 @@ public class StringUtils {
|
||||
// Determine the difference value, return the result
|
||||
return Math.abs(service.score(first, second) - 1.0);
|
||||
}
|
||||
|
||||
public static boolean containsAny(String str, String... pieces) {
|
||||
if (str == null) {
|
||||
return false;
|
||||
}
|
||||
for (String piece : pieces) {
|
||||
if (str.contains(piece)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
230
test/main/java/fr/xephi/authme/Log4JFilterTest.java
Normal file
230
test/main/java/fr/xephi/authme/Log4JFilterTest.java
Normal file
@ -0,0 +1,230 @@
|
||||
package fr.xephi.authme;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.logging.log4j.core.Filter.Result;
|
||||
import org.apache.logging.log4j.core.LogEvent;
|
||||
import org.apache.logging.log4j.message.Message;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
/**
|
||||
* Test for {@link Log4JFilter}.
|
||||
*/
|
||||
public class Log4JFilterTest {
|
||||
|
||||
private final Log4JFilter log4JFilter = new Log4JFilter();
|
||||
|
||||
private static final String SENSITIVE_COMMAND = "User issued server command: /login pass pass";
|
||||
private static final String NORMAL_COMMAND = "User issued server command: /help";
|
||||
private static final String OTHER_COMMAND = "Starting the server... Write /l for logs";
|
||||
|
||||
// ---------
|
||||
// Test the filter(LogEvent) method
|
||||
// ---------
|
||||
@Test
|
||||
public void shouldFilterSensitiveLogEvent() {
|
||||
// given
|
||||
Message message = mockMessage(SENSITIVE_COMMAND);
|
||||
LogEvent event = Mockito.mock(LogEvent.class);
|
||||
when(event.getMessage()).thenReturn(message);
|
||||
|
||||
// when
|
||||
Result result = log4JFilter.filter(event);
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(Result.DENY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotFilterIrrelevantLogEvent() {
|
||||
// given
|
||||
Message message = mockMessage(NORMAL_COMMAND);
|
||||
LogEvent event = Mockito.mock(LogEvent.class);
|
||||
when(event.getMessage()).thenReturn(message);
|
||||
|
||||
// when
|
||||
Result result = log4JFilter.filter(event);
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(Result.NEUTRAL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotFilterNonCommandLogEvent() {
|
||||
// given
|
||||
Message message = mockMessage(OTHER_COMMAND);
|
||||
LogEvent event = Mockito.mock(LogEvent.class);
|
||||
when(event.getMessage()).thenReturn(message);
|
||||
|
||||
// when
|
||||
Result result = log4JFilter.filter(event);
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(Result.NEUTRAL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotFilterLogEventWithNullMessage() {
|
||||
// given
|
||||
Message message = mockMessage(null);
|
||||
LogEvent event = Mockito.mock(LogEvent.class);
|
||||
when(event.getMessage()).thenReturn(message);
|
||||
|
||||
// when
|
||||
Result result = log4JFilter.filter(event);
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(Result.NEUTRAL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotFilterWhenLogEventIsNull() {
|
||||
// given / when
|
||||
Result result = log4JFilter.filter(null);
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(Result.NEUTRAL));
|
||||
}
|
||||
|
||||
// ----------
|
||||
// Test filter(Logger, Level, Marker, String, Object...)
|
||||
// ----------
|
||||
@Test
|
||||
public void shouldFilterSensitiveStringMessage() {
|
||||
// given / when
|
||||
Result result = log4JFilter.filter(null, null, null, SENSITIVE_COMMAND, new Object[0]);
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(Result.DENY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotFilterNormalStringMessage() {
|
||||
// given / when
|
||||
Result result = log4JFilter.filter(null, null, null, NORMAL_COMMAND, new Object[0]);
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(Result.NEUTRAL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotFilterNonCommandStringMessage() {
|
||||
// given / when
|
||||
Result result = log4JFilter.filter(null, null, null, OTHER_COMMAND, new Object[0]);
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(Result.NEUTRAL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnNeutralForNullMessage() {
|
||||
// given / when
|
||||
Result result = log4JFilter.filter(null, null, null, null, new Object[0]);
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(Result.NEUTRAL));
|
||||
}
|
||||
|
||||
// --------
|
||||
// Test filter(Logger, Level, Marker, Object, Throwable)
|
||||
// --------
|
||||
@Test
|
||||
public void shouldFilterSensitiveObjectMessage() {
|
||||
// given / when
|
||||
Result result = log4JFilter.filter(null, null, null, SENSITIVE_COMMAND, new Exception());
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(Result.DENY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotFilterNullObjectParam() {
|
||||
// given / when
|
||||
Result result = log4JFilter.filter(null, null, null, (Object) null, new Exception());
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(Result.NEUTRAL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotFilterIrrelevantMessage() {
|
||||
// given / when
|
||||
Result result = log4JFilter.filter(null, null, null, OTHER_COMMAND, new Exception());
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(Result.NEUTRAL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotFilterNonSensitiveCommand() {
|
||||
// given / when
|
||||
Result result = log4JFilter.filter(null, null, null, NORMAL_COMMAND, new Exception());
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(Result.NEUTRAL));
|
||||
}
|
||||
|
||||
// --------
|
||||
// Test filter(Logger, Level, Marker, Message, Throwable)
|
||||
// --------
|
||||
@Test
|
||||
public void shouldFilterSensitiveMessage() {
|
||||
// given
|
||||
Message message = mockMessage(SENSITIVE_COMMAND);
|
||||
|
||||
// when
|
||||
Result result = log4JFilter.filter(null, null, null, message, new Exception());
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(Result.DENY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotFilterNonSensitiveMessage() {
|
||||
// given
|
||||
Message message = mockMessage(NORMAL_COMMAND);
|
||||
|
||||
// when
|
||||
Result result = log4JFilter.filter(null, null, null, message, new Exception());
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(Result.NEUTRAL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotFilterNonCommandMessage() {
|
||||
// given
|
||||
Message message = mockMessage(OTHER_COMMAND);
|
||||
|
||||
// when
|
||||
Result result = log4JFilter.filter(null, null, null, message, new Exception());
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(Result.NEUTRAL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotFilterNullMessage() {
|
||||
// given / when
|
||||
Result result = log4JFilter.filter(null, null, null, (Message) null, new Exception());
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(Result.NEUTRAL));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mocks a {@link Message} object and makes it return the given formatted message.
|
||||
*
|
||||
* @param formattedMessage the formatted message the mock should return
|
||||
* @return Message mock
|
||||
*/
|
||||
private static Message mockMessage(String formattedMessage) {
|
||||
Message message = Mockito.mock(Message.class);
|
||||
when(message.getFormattedMessage()).thenReturn(formattedMessage);
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user