Module
Improper Debug/Error Handling (Information exposure through an debug message/error message/stack trace/exception)
Summary
An error message or stack trace may contain sensitive information that can reveal unnecessary and potentially sensitive system information to unindended individuals.
Description
Error messages are often used to indicate that a problem has occurred in a program. They are often displayed to the user, and can be used to help identify the problem.
In addition, Software developers often add stack traces to error messages, as a debugging aid. Whenever that error message occurs for an end user, the developer can use the stack trace to help identify how to fix the problem. In particular, stack traces can tell the developer more about the sequence of events that led to a failure, as opposed to merely the final state of the software when the error occurred.
However, error messages and stack traces can also contain sensitive information that can be used by an attacker to gain unauthorized access to a system. For example, an error message might contain a stack trace that includes the names of files, directories, and other system information. In addition, error messages can also contain sensitive information such as passwords, usernames, and other sensitive data.
Although those information can be useful to the users, and useful for software developers to debug the program, unfortunately, the same information can be useful to an attacker. For instance, the sequence of class names in a stack trace can reveal the structure of the application as well as any internal components it relies on; the username and password can allow an attacker can use to gain access to the system.
Risk
How Can It Happen? Printing stack trace and excepton messages might reveal username and password or other sensitive information, which allows an attacker to gain access to the system.
Example
In response to a password-filling request, the debug message, instead of a simple Granted/Denied response, prints an elaborate message, “The user-entered password does not match the actual password stored in
Example Code (Bad Code)
In the following example, an exception is sent back to the remote user by calling ToString(), and writing it to the response. As such, the user is able to see a detailed stack trace, which which may contain sensitive information.
...
using System;
using System.Web;
public class StackTraceHandler : IHttpHandler
{
public void ProcessRequest(HttpContext ctx)
{
try
{
doSomeWork();
}
catch (Exception ex)
{
// BAD: printing a stack trace back to the response
ctx.Response.Write(ex.ToString());
return;
}
}
}
...
Addressing Improper Debug/Error Handling
Control who can see what. For instance, send the user a more generic error message that reveals less information. Also suppress the stack trace entirely for the user. For debug purpose, if the stack trace must be preserved or some more sensitive data must be emitted, log it only on the server or a host that the user has no access to.
In the following example, a generic error message is shown to the user while the error message is logged only on the server. That way, the developers can still access and use the error log, but remote users will not see the information.
using System;
using System.Web;
public class StackTraceHandler : IHttpHandler
{
public void ProcessRequest(HttpContext ctx)
{
try
{
doSomeWork();
}
catch (Exception ex)
{
// GOOD: log the stack trace, and send back a non-revealing response
log("Exception occurred", ex);
// GOOD: send a generic error message to the user
ctx.Response.Write("Exception occurred");
return;
}
}
}
Fixing Weaknesses
In this lab, you will be given a code snippet that contains an Improper Debug/Error Handling error, a potential vulnerability. Your task is to identify the error and fix it.
Examine the code snippet below that computes total salary for an organization.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class TotalSalary {
public static void main(String[] args) {
// Path to your CSV file
String csvFile = "employees.csv";
String line;
String csvSplitBy = ",";
double totalSalary = 0.0;
try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) {
// Skip header line if your CSV has one
br.readLine();
while ((line = br.readLine()) != null) {
// Split the line by comma
String[] employee = line.split(csvSplitBy);
// Assuming the format is: name,ssn,birthdate,salary
// Make sure salary is the 4th column (index 3)
try {
double salary = Double.parseDouble(employee[3].trim());
totalSalary += salary;
} catch (NumberFormatException e) {
System.err.println("Error parsing salary for line: " + line);
}
}
System.out.printf("Total salary for all employees: $%.2f%n", totalSalary);
} catch (IOException e) {
e.printStackTrace();
}
}
}
The input file employees.csv
is expected to have the following format:
name,ssn,birthdate,salary
John Doe,123-45-6789,1980-05-15,75000.50
Jane Smith,987-65-4321,1975-11-22,82500.75
Bob Johnson,456-78-9012,1990-03-08,68000.00
- Identity the locations of the Improper Debug/Error Handling error in the code snippet. Hint: there are two locations.
- Fix the security weakness using the skills you just learned, i.e., revise the program to properly handle at least one of the two such errors.
- Complete the survey in the next page. One of the question in the survey asks for your solution to the lab. Copy your solution code snippet (snippet only) and paste it into the survey.
Acknowledgement
This page is inspired by the Security Injection@Towson project.