Sunday, June 28, 2009

ESAPI Logging

The OWASP ESAPI Logging interface is a security-centric but thin abstraction on top of traditional high-performance logging API's. There are both Log4j and native Java Logging default ESAPI logging implementations. The Log4j  implementation is especially mature.

The logging interface of the OWASP ESAPI library pre-defines 4 types of log files entries specific to the glory of security monitoring.

public static final EventType ....
SECURITY_SUCCESS = new EventType( "SECURITY SUCCESS", true);
SECURITY_FAILURE = new EventType( "SECURITY FAILURE", false);
EVENT_SUCCESS = new EventType( "EVENT SUCCESS", true);
EVENT_FAILURE = new EventType( "EVENT FAILURE", false);

Attributing every log entry with a security type is fundamental to ESAPI. Your implementation of ESAPI can extend or change this list if desired. 

ESAPI also supports a hierarchy of logging levels which can be configured at runtime to determine the severity of events that are logged, so that those log entries below the current threshold that are discarded. This is a common logging API feature and includes the following severity levels (fatal, error, warning, info, debug, trace). 

The ESAPI team considered simply adding a security severity level to Log4J, but decided that was not enough. We wanted to force a programmer to tag every log entry as a security event (or not), regardless of severity level. We did not add yet another logging abstraction to your life lightly.

The reference implementations also includes the following protections:
  • encodes any CRLF characters included in log data in order to prevent log injection attacks
  • optionally encodes HTML characters into the HTML entity to protect web based log viewing software
  • provides a mechanism to log session ids referentially so that sessions can be tracked in log files without exposing real session identifiers that could be used to hijack active sessions
  • provides a mechanism to automatically log HTTP post/get variables while allowing for masking of passwords and other security-critical information that should not be logged
Much of this is configurable in ESAPI.properties 

ESAPI.Logger=org.owasp.esapi.reference.Log4JLogFactory
#ESAPI.Logger=org.owasp.esapi.reference.JavaLogFactory
Specify your application name if you wish to log it. 
Logger.ApplicationName=ARMS
# If you use an HTML log viewer that does not properly HTML escape 
# log data, you can set LogEncodingRequired to true
Logger.LogEncodingRequired=false
Logger.LogApplicationName=false
Logger.LogServerIP=false
# LogFileName, the name of the logging file. Provide a full directory path (e.g., C:\\ESAPI\\ESAPI_logging_file) if you
# want to place it in a specific directory.
Logger.LogFileName=ARMS_ESAPI_LOGFILE
# MaxLogFileSize, the max size (in bytes) of a single log file before it cuts over to a new one (default is 10,000,000)
Logger.MaxLogFileSize=10000000


So now you want to (securely) log. Right on. Simply specify a logger in each class that requires logging:

private final Logger logger = ESAPI.getLogger(SimpleESAPIFilter.class.getName());

And log away!

logger.error(Logger.SECURITY_FAILURE,  "session has expired, log out user");

Here is an example of a log entry from one of my projects at Aspect. I'm not deploying on a cluster, yet, so I supressed the server IP, port and appName via ESAPI.properties.

2009-06-29 05:48:25,281 WARN  IntrusionDetector SECURITY FAILURE Anonymous:0@unknown:unknown Incorrect password provided for dave
org.owasp.esapi.errors.ValidationException: Login failed
at com.aspectsecurity.arms.web.SimpleESAPIFilter.doFilter(SimpleESAPIFilter.java:149)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:875)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
at java.lang.Thread.run(Thread.java:595)
2009-06-29 05:48:25,281 ERROR com.aspectsecurity.arms.web.actions.ARMSBaseAction EVENT SUCCESS Anonymous:0@unknown:270186 ENTRY POINT FOR ALL ACTIONS: 1246268905281
2009-06-29 05:48:25,281 ERROR com.aspectsecurity.arms.service.HibernateAccessController SECURITY SUCCESS Anonymous:0@unknown:270186 START assertAuthorizedForAction : action=com.aspectsecurity.arms.web.actions.user.LoginSubmitAction
2009-06-29 05:48:25,281 ERROR com.aspectsecurity.arms.service.HibernateAccessController SECURITY SUCCESS Anonymous:0@unknown:270186 ACCESS GRANTED assertAuthorizedForAction completeActionName=com.aspectsecurity.arms.web.actions.user.LoginSubmitAction IS NOT MANAGED, SO ALLOW GLOBAL ACCESS


5 comments:

Anonymous said...

Is there a way to specify multiple log files in ESAPI.properties?

Jim Manico said...

It depends on which logging implementation you use. For the Log4J ESAPI Logging factory, you can use log4j's capacity to separate log appenders on a logging "name" basis (the log4j logging constructor argument).

Dave Read said...

Jim, thank you for the clarification on leveraging log4j. I wondered if there was a way to just configure ESAPI to log using an already existing logger? I have different logging levels (and files in some cases) based on packages. I'd want to treat ESAPI log messages in the same manner. Is this possible or is there a simple way to use my existing log4j configuration (rolling log files by date, setting levels by package, etc) within the ESAPI.properties? Thanks, Dave

Ajay said...

Hi Jim,
what is the difference between
org.owasp.esapi.reference.Log4JLogFactory
ESAPI.Logger=org.owasp.esapi.reference.JavaLogFactory

I am getting below exception on JBOSS, and need to restart server :

java.lang.ClassCastException: org.owasp.esapi.reference.Log4JLogger cannot be cast to org.owasp.esapi.Logger
at org.owasp.esapi.reference.Log4JLogFactory.getLogger(Log4JLogFactory.java:88) [esapi-2.0.1.jar:2.0.1]

Jim Manico said...

Ajay, can you please send that question to the ESAPI user list? https://lists.owasp.org/listinfo/esapi-user

Thank you!
- Jim