Skip to content

Commit dfd8cf6

Browse files
committed
ZOOKEEPER-5082: Remove special characters from audit logs
Reviewers: tisonkun, phunt, PDavid Author: anmolnar Closes #2448 from anmolnar/ZOOKEEPER-5082 (cherry picked from commit e4f0cd4) Signed-off-by: Andor Molnar <andor@cloudera.com>
1 parent 973bbc4 commit dfd8cf6

4 files changed

Lines changed: 29 additions & 2 deletions

File tree

zookeeper-server/src/main/java/org/apache/zookeeper/audit/AuditEvent.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.LinkedHashMap;
2121
import java.util.Map;
2222
import java.util.Set;
23+
import org.apache.zookeeper.common.StringUtils;
2324

2425
public final class AuditEvent {
2526
private static final char PAIR_SEPARATOR = '\t';
@@ -75,7 +76,7 @@ public String toString() {
7576
buffer.append(PAIR_SEPARATOR);
7677
}
7778
buffer.append(key).append(KEY_VAL_SEPARATOR)
78-
.append(value);
79+
.append(StringUtils.sanitizeForLog(value));
7980
}
8081
}
8182
//add result field

zookeeper-server/src/main/java/org/apache/zookeeper/common/StringUtils.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,19 @@ public static boolean isEmpty(String str) {
9292
return str == null || str.length() == 0;
9393
}
9494

95+
/**
96+
* Sanitizes a string for safe inclusion in log messages by removing
97+
* any control characters between [\x00-\x1F]. This prevents
98+
* log-injection attacks (CWE-117) where attacker-controlled input
99+
* containing newlines could forge fake log entries.
100+
*
101+
* @param str the string to sanitize, may be null
102+
* @return the sanitized string, or {@code null} if input is {@code null}
103+
*/
104+
public static String sanitizeForLog(String str) {
105+
if (str == null) {
106+
return null;
107+
}
108+
return str.replaceAll("[\\x00-\\x1F]", "");
109+
}
95110
}

zookeeper-server/src/main/java/org/apache/zookeeper/server/auth/EnsembleAuthenticationProvider.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.HashSet;
2323
import java.util.Set;
2424
import org.apache.zookeeper.KeeperException;
25+
import org.apache.zookeeper.common.StringUtils;
2526
import org.apache.zookeeper.server.ServerCnxn;
2627
import org.apache.zookeeper.server.ServerMetrics;
2728
import org.slf4j.Logger;
@@ -92,7 +93,7 @@ public KeeperException.Code handleAuthentication(ServerCnxn cnxn, byte[] authDat
9293
long currentTime = System.currentTimeMillis();
9394
if (lastFailureLogged + MIN_LOGGING_INTERVAL_MS < currentTime) {
9495
String id = cnxn.getRemoteSocketAddress().getAddress().getHostAddress();
95-
String logEnsembleName = receivedEnsembleName.replaceAll("[\\x00-\\x1F]", "");
96+
String logEnsembleName = StringUtils.sanitizeForLog(receivedEnsembleName);
9697
LOG.warn("Unexpected ensemble name: ensemble name: {} client ip: {}", logEnsembleName, id);
9798
lastFailureLogged = currentTime;
9899
}

zookeeper-server/src/test/java/org/apache/zookeeper/audit/AuditEventTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,14 @@ public void testFormatShouldIgnoreKeyIfValueIsNull() {
4242
String expected = "operation=Value2\tresult=success";
4343
assertEquals(expected, actual);
4444
}
45+
46+
@Test
47+
public void testSanitizeInvalidOutput() {
48+
AuditEvent auditEvent = new AuditEvent(Result.SUCCESS);
49+
auditEvent.addEntry(AuditEvent.FieldName.USER, "Value1");
50+
auditEvent.addEntry(AuditEvent.FieldName.OPERATION, "\nfake\toperation=delete\rznode=/forged:pw");
51+
String actual = auditEvent.toString();
52+
String expected = "user=Value1\toperation=fakeoperation=deleteznode=/forged:pw\tresult=success";
53+
assertEquals(expected, actual);
54+
}
4555
}

0 commit comments

Comments
 (0)