V5619. OWASP. Possible log injection. Potentially tainted data is written into logs.
The analyzer has detected data written into logs from an external source without validation. This can violate logging processes or compromise the contents of log files.
Errors related to data logging belong to A09:2021 – Security Logging and Monitoring Failures category of the OWASP Top 10 Application Security Risks list.
If logging of user input is performed without validation, an attacker can inject arbitrary data into logs.
Consider an example — let's say logs are stored in text format. An attacker can use different ways to find out the storage type — it's easy if the project is open source. Moreover, attackers can use other attacks. A possible log can look as follows:
INFO: User 'SomeUser' entered value: '2022'.
INFO: User 'SomeUser' logged out.
The code that performs logging can look as follows:
public class InputHelper
{
HttpRequest Request {get; set;}
Logger logger;
string UserName;
void ProcessUserInput()
{
string userInput = Request["UserInput"];
string logMessage = "INFO: User '"
+ UserName
+ "' entered value: '"
+ userInput + "'.";
logger.Log(logMessage);
....
}
}
In this case, an attacker can inject arbitrary data about events that never happened.
Let's say, an attacker enters the following:
2022/r/nINFO: User 'Admin' logged out.
Logs will contain the following information that can mislead the developer analyzing the logs:
INFO: User 'SomeUser' entered value: '2022'.
INFO: User 'Admin' logged out.
Let's consider another type of attack. For example, if logs are stored in XML format, an attacker can inject data that will make the contents of the report incorrect. Moreover, the following parsing of ready-made logs might produce incorrect data or fail with an error. Here is an example of vulnerable code:
public class InputHelper
{
HttpRequest Request {get; set;}
Logger logger;
void ProcessUserInput()
{
string userID = Request["userID"];
logger.Info(userID); // <=
....
}
}
An attacker can inject an unclosed tag and make it impossible to parse an XML file.
Possible vulnerabilities depend on architecture, input settings, logger, log output and other parts of logging system. For example, a log injection attack in XML format allows attackers to:
- violate the process of adding new log entries;
- violate the process of viewing ready-made logs;
- exploit an XEE vulnerability (for more details, see the V5615 diagnostic);
- exploit an XXE vulnerability (for more details, see the V5614 diagnostic);
- exploit an insecure deserialization vulnerability (for more details, see the V5611 diagnostic).
You can prevent some attacks by escaping characters so that they are not treated as part of XML syntax. For example, the initial character of the "<" tag should be escaped as "<". Some standard .NET methods, used to work with XML (for example, 'XNode' descendants), implement escaping of data written to an XML tree. Besides XML infrastructure, .NET provides stand-alone classes to ensure data security. Here's an example of a more secure code with encoding:
public class InputHelper
{
HttpRequest Request {get; set;}
Logger logger;
string EscapeCharsForXmlLog(string userInput)
{
return SecurityElement.Escape(userInput);
}
void ProcessUserInput()
{
string userInput = Request["userID"];
userInput = EscapeCharsForXmlLog(userInput);
logger.Info(userInput); // <=
....
}
}
Here's another example: the JSON standard prohibits null characters ("\0") in files. If an attacker introduces this character, it can break the process of saving or viewing ready-made logs. The null character should be escaped as "\u0000".
One more example: suppose logs are stored in relational DBMS that uses SQL. If input data is not verified, this can lead to an SQL injection attack (for more details, see the V5608 diagnostic).
The analyzer also considers method parameters from other assemblies potential sources of tainted data. The following article covers this topic in detail: "Why you should check values of public methods' parameters". Consider an example:
public class InputHelper
{
Logger logger;
public void ProcessInput(string input)
{
Log("Input logged:" + input);
}
private void Log(string input)
{
logger.Log(LogLevel.Information, input);
}
}
In this case, the analyzer will issue a warning of low certainty level for the 'Log' method. The infected result of string concatenation is used for logging.
As in the example above, you can make this code more secure by encoding the string:
public class InputHelper
{
Logger logger;
public void ProcessInput(string input)
{
Log(SecurityElement.Escape("Input logged:" + input));
}
private void Log(string input)
{
logger.Log(LogLevel.Information, input);
}
}
This diagnostic is classified as:
|