How to Add a Security Log Level in Log4j

Author
Arshan Dabirsiaghi

The Problem
Anecdotally, most application security engineers could tell you that the state of auditing and logging in web applications today is fairly poor. This is due to a number of issues:
 * 1) Security-relevant events don't get logged
 * 2) The information contained within those log messages is incomplete
 * 3) It's difficult to analyze, filter and generally reconstruct an attack because messages are spread around various log levels

The goal of this page is to let you know how to fix the last item in the list. A Security log level can help an incident response team filter out security-related messages and reconstruct an attack. There are two files here, SecurityLevel.java and log4j.xml. To add this level to your project, simply add SecurityLevel.java to your classpath. If you want to execute the test case, add the log4j.xml file to your classpath. If you're getting a "No appenders found" error, make sure there is a log4j.xml or log4j.properties file on your classpath, because log4j can't find either.

The Java Code: SecurityLevel.java
is "SECURITY" level. If yes then returns {@link SecurityLevel#SECURITY}, * else calls {@link SecurityLevel#toLevel(String, Level)} passing it {@link Level#DEBUG} as the defaultLevel *	    * @see Level#toLevel(java.lang.String) * @see Level#toLevel(java.lang.String, org.apache.log4j.Level) *	    */	    public static Level toLevel(String sArg) { if (sArg != null && sArg.toUpperCase.equals(SECURITY_MSG)) { return SECURITY; }	       return (Level) toLevel(sArg, Level.DEBUG); }

/**	    * Checks whether   is {@link SecurityLevel#SECURITY_LEVEL_INT}. If yes then returns {@link SecurityLevel#SECURITY}, * else calls {@link SecurityLevel#toLevel(int, Level)} passing it {@link Level#DEBUG} as the defaultLevel *	    * @see Level#toLevel(int) * @see Level#toLevel(int, org.apache.log4j.Level) *	    */	    public static Level toLevel(int val) { if (val == SECURITY_LEVEL_INT) { return SECURITY; }	       return (Level) toLevel(val, Level.DEBUG); }

/**	    * Checks whether   is {@link SecurityLevel#SECURITY_LEVEL_INT}. If yes then returns {@link SecurityLevel#SECURITY}, * else calls {@link Level#toLevel(int, org.apache.log4j.Level)} *	    * @see Level#toLevel(int, org.apache.log4j.Level) */	   public static Level toLevel(int val, Level defaultLevel) { if (val == SECURITY_LEVEL_INT) { return SECURITY; }	       return Level.toLevel(val,defaultLevel); }

/**	    * Checks whether   is "SECURITY" level. If yes then returns {@link SecurityLevel#SECURITY}, * else calls {@link Level#toLevel(java.lang.String, org.apache.log4j.Level)} *	    * @see Level#toLevel(java.lang.String, org.apache.log4j.Level) */	   public static Level toLevel(String sArg, Level defaultLevel) { if(sArg != null && sArg.toUpperCase.equals(SECURITY_MSG)) { return SECURITY; }	   return Level.toLevel(sArg,defaultLevel); }	 public static void main(String[] args) { Logger logger = Logger.getLogger(SecurityLevel.class.getName); logger.log(SecurityLevel.SECURITY,"This is a SECURITY level message"); System.out.println("Wrote the log with my security level"); logger.log(Level.DEBUG ,"I am a debug message"); System.out.println("Wrote the log with debug level"); } }