How do you write an exception without revealing sensitive information?

4.8k Views Asked by At

I'm writing a program, from a security point of view, that will catch an SQLException. I'm trying to purge all sensitive information.

catch(SQLException se){
  se.printStackTrace();
}

Would writing it the above way reveal sensitive information? If so, what would be a secure way to write it?

4

There are 4 best solutions below

0
On

You are revealing parts of your code, as line numbers and variable names will be printed.

The best way would be to just custom your own message. Another method can be something similar to the way IIS error messages are printed: show full stack trace if the request is from the server computer (debugging) but show a generic error for external requests.

1
On

Even from a UX point of view, spewing out technical info will create a crappy experience for the user.

Use a polite general error code (and or error message) that users can send you to help with debugging

0
On

CERT Secure Coding sheds some light on this topic. They give examples as to why simply printing the stack trace is not secure. There are several issues from both a technical and business prospective:

  • SQLExceptions can reveal hints about database structure
  • Sensitive client information could be revealed by an exception
  • Stack traces in general can reveal implementation details of your application

There are several things you can do to mitigate these risks.

  1. Discard the exception. While far from ideal, one potential solution could be to catch the original exception, and either print a message free of sensitive data to Standard Error or throw a new exception with a different message. This, however, can make debugging difficult, but it could reduce the risk of exposing sensitive information.

    catch(SQLException se){
        throw new SQLException("Error executing query.");
    }
    
  2. Clean up the exception.

    catch (SQLException se) { 
        MyExceptionCleaner.clean(se); // Remove any sensitive data 
    }
    

The MyExceptionCleaner object has the ability to capture and filter any sensitive data while still preserving any details that might be useful for maintenance. For more information, check out this question.

0
On

Q) Why printing the stack trace after an exception is thrown is insecure ?

A) A stack trace is an informational leak, which reveals some details about the implementation of your system. Not a serious vulnerability but could aid attackers to gain certain information about the deign of the database (database version, table names, code filenames).

Printing the stack trace could also allow attackers to use debugging tools to identify and exploit flaws in the system.

Apart from the security issues discussed above the stack trace should not be displayed to any users of the system or attackers. Customer confidence in the system will be decreased if an error such as the stack trace is printed onto the console.

The user is unclear if their transaction has been completed, or unclear on why such an error has been shown.



An Error Has Occurred Summary: Syntax error (missing operator) in query expression 'username = 'john' or 1=1 ' AND password = 'gggg''. Error Message: System.Data.OleDb.OleDbException: Syntax error (missing operator) in query expression 'username = 'john' or 1=1 ' AND password = 'gggg''. at System.Data.OleDb.OleDbCommand.ExecuteCommandTextErrorHandling(OleDbHResult hr) at System.Data.OleDb.OleDbCommand.ExecuteCommandTextForSingleResult(tagDBPARAMS dbParams, Object& executeResult) at System.Data.OleDb.OleDbCommand.ExecuteCommandText(Object& executeResult) at System.Data.OleDb.OleDbCommand.ExecuteCommand(CommandBehavior behavior, Object& executeResult) at System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(CommandBehavior behavior, String method) at System.Data.OleDb.OleDbCommand.ExecuteReader(CommandBehavior behavior) at System.Data.OleDb.OleDbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior) at System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior) at System.Data.Common.DbDataAdapter.Fill(DataSet dataSet, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior) at System.Data.Common.DbDataAdapter.Fill(DataSet dataSet, String srcTable) at Altoro.Authentication.ValidateUser (String uName, String pWord) in c:\downloads\AltoroMutual_v6\website\bank\login.aspx.cs:line 68 at Altoro.Authentication.Page_Load(Object sender, EventArgs e) in c:\downloads\AltoroMutual_v6\website\bank \login.aspx.cs:line 33 at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) at System.Web.UI.Control.OnLoad (EventArgs e) at System.Web.UI.Control.LoadRecursive() at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)



As shown in the example stack trace shown above, the user name that was entered contained invalid characters that were not expected to be entered into the username field, as a result the system crashed and thrown this detailed stack trace to the screen.

What should have occurred is either a customized exception made by the developer to be thrown which instead of revealing all of the above sensitive information to the user just show a message such as:

    Invalid character entered.
    Please enter letters only.
    Please try again!

Two ways of dealing with exceptions and stack trace is by SANITIZING or PURGING.

1) Sanitizing

As shown above, the developer anticipated that an error in input could occur and wrote a error handling section of code that instead of printing the stack trace printed a small easy to understand message to the user on why their action was not completed.

The developer sanitized or "cleaned" the exception to prevent
the system from crashing and can add a loop so if the data entered is incorrect an error message will be thrown and the user asked to re enter their credentials.

2) Purging

Similar to sanitizing, the anticipation of an error occurring allows the developer to intervene and display an error message that is customized only to the understanding of the developer or perhaps the error will not be thrown at all and just a customized error will be thrown to a log file.

Any user facing errors that occur will be sanitized so that the customer can easily understand why the error occurred and the error is then logged. The logged error is purged inside the log file with an id number or a customized

thrown error so instead of FileNotFoundException being displayed in the log the developer can customize that to read Error:782.

This prevents writing the descriptive error in plain text showing the vulnerabilities in a system.The customized id of an error is logged in a dictionary of errors within the companies database so the developer can search the ID and a description is assigned to the error to give an understanding of why it occurred but only authorized users can access this, preventing misuse of the information.