OneAPM大讲堂 | Java 异常日志记录最佳实践
【编者按】本文作者是 Casey Dunham。Casey 是一位具有 10 多年经验的专业软件开发人员,以其独特的方式应对应用安全问题而闻名。本文系国内 ITOM 管理平台 OneAPM 工程师编译整理。
作为安全顾问,我对各种应用程序进行评估。 在我测试过的所有应用程序中,我发现它们通常会遇到一些对异常问题的处理和日志记录不足。日志记录和监控往往是被忽视的领域,并且由于对 Web 应用程序的威胁日益增加,它们已被添加到 OWASP Top 10 的十大问题之一,名为“Insufficient Logging and Monitoring(没有足够的日志记录及监测)”。
这会带来什么问题?让我们来看看。
日志?谁需要日志?
首先,为什么我们要使用日志?重点是什么?
正确的日志记录不仅适用于调试应用程序,而且对取证和事件响应也有许多的益处。您如何知道某人是否正在针对您的应用程序运行漏洞扫描程序?或者正在进行强力攻击程序试图访问用户帐户?能知道这些当然最好,但还有其他更微妙的事情。
大多数成功的攻击都是从攻击应用程序并寻找其弱点。攻击者对应用程序进行调查的次数越多,攻击者可以找到并成功利用该应用程序弱点的可能性就越大。攻击者之所以能够保持攻击是因为其攻击被忽视了,并且由于违规检测平均周期 191 天,日志通常是我们能看到攻击正在发生的唯一方式了。没有日志信息的话,我们将很难评估谁在什么时候访问以及访问的深度。
创建并遵循日志记录策略
我很少见到一个具有实际日志记录策略的应用程序。 大多数情况下,我们实施日志记录已经是问题出现后的做法了。 我想这可能也算一种策略,但我们能做得更好吗? 我想我们可以。
当您将日志记录添加到应用程序中时,最好有一个总体一致的策略。 尽可能在所有应用程序中使用相同的日志记录框架。 这样就可以实现轻松地共享配置,如消息格式,并采用一致的日志记录模式。什么情况下需要记录出现警告/错误以及要使用哪些日志记录级别需要有一致的准则。 在记录任何东西时,消息格式应至少包含时间戳,当前线程标识符,调用者标识和源代码信息。 所有现代日志记录框架都支持这种类型的信息。
将所有这些作为开发人员文档的一部分,这将是在所有业务应用程序中创建和维护日志记录的绝佳方式。
记录完整的堆栈跟踪
在我所做的许多安全代码预览中,我经常看到的一个错误是:不记录整个堆栈跟踪以用于查找异常。 以这个假设为例,这是我多次看到的一个典型错误模式:

这个例子有好几个问题,我们只关注处理 SQLException 的部分。 比方说,在生产中看日志时,我们看到了这个:

这并没有告诉你很多信息。 什么导致了 SQLGrammarException?记录器会把所有包含抛出对象的异常进行归类,并且写出堆栈踪迹。 通过稍微改变代码,我们就能更清楚地了解发生了什么:

用这个代码我们就能完整的记录堆栈跟踪了,记录清楚地显示了一些邪恶的活动正在悄悄进行。

现在,只要查看日志,我们可以立即看到问题所在。 有人试图用 Acme’来查找客户,并打破了我们的 SQL 语句。 这个异常明确显示了 SQL 注入,如果我们分析日志时只能看到原始消息,这就很容易被忽略。 我们很可能没有深入考虑这个问题并转向了其他问题,导致没有发现这个严重的缺陷。
记录所有异常
“吞噬”异常是我看到的另一个很常见的问题:在应用程序的某个地方抛出一个异常,开发人员打算用 catch 块来处理,但由于某种原因,开发人员忘记了它或者认定它不重要。 以下示例说明了此问题:

据我的经验,这种做法非常普遍并且值得一提。 记录异常,重新抛出异常,或者根本不处理异常,在日志中都不会显示应用程序出现了任何问题。 我们没有理由不记录异常。“吞噬”这样的异常会导致隐藏在底层的问题被忽视,最终导致业务逻辑或安全漏洞问题。
不要将异常返回给用户
在执行任何类型的安全评估时,每一条有关应用程序或其环境的信息都可能有用。 看似无害的错误信息可能正是顾问(或攻击者)所需要的。 顾问们可能找到您的系统的一个漏洞-对系统进行攻击或者大大减少有效负荷,如果错误信息揭示相关漏洞正在使用的数据库系统的信息,那么我们需要对这个漏洞进行 SQL 注入测试。
通过某种错误处理简单地向用户返回异常消息也是一种常见的做法。 在测试身份验证系统时,我遇到了很多问题,如以下屏幕截图所示:

处理这个问题的代码可能会这么做:

稍后,异常会被抛出并被捕获。 开发人员用异常信息编写传达给用户的报错信息,这导致用户能够看到系统原始的异常信息。

就异常处理而言,这不仅是不好的做法,而且还会打开用户帐户验证的应用程序。 根据您正在处理的应用程序的类型,这本身可能就存在风险。
切勿将异常对象的内容返回给用户。 捕获异常,记录它并返回一个通用响应。 随着代码的进化,您永远不会知道异常消息可能包含哪些信息,并且异常消息本身是否会在将来发生变化。
不要记录敏感信息
我提到日志不仅可用于调试,还可用于合规性,审计和取证。 由于日志有很多用途,并且我们倾向于“记录所有内容”,它们可以成为惊人的信息来源。 如果日志包含用户名,密码,会话令牌或其他敏感信息,它确实减少了攻击者的工作量。 日志将揭示应用程序的内部工作和失败,攻击者可以使用这些进一步攻击应用程序。 因此,我们需要谨慎的对待日志并将其安全保存起来。 不应被记录信息如下:
信用卡号码
社保号码
密码
但以下类型的信息也不应被写入日志中:
会话标识符
授权令牌
个人姓名
电话号码
用户选择退出的信息(例如,不跟踪)
还有一个问题:一些司法管辖区不允许跟踪某些信息,这样做违反了法律。 了解应用程序的合规性要求及其处理的数据非常重要。
别让自己身处黑暗之中
虽然日志记录不是一项复杂的任务,但在正确使用日志方面有很多微妙之处和平衡点。 太少的信息没有太大价值,但是如果处理不当,太多的信息有可能变成负担。
记录应用程序日志不是选择题, 没有足够的日志,你将身在黑暗之中。
OneAPM Li 智能日志分析平台可以实时收集数据中心基础架构及应用的海量日志,实时搜索,实时分析,洞悉日志价值。想阅读更多技术文章,请访问 OneAPM 官方技术博客。
原文地址:https://blog.scalyr.com/2018/03/java-exceptions-log/
OneAPM大讲堂 | Java 异常日志记录最佳实践的更多相关文章
- [蟒蛇菜谱]Python日志记录最佳实践
# -*- coding: utf8 -*- import logging # 创建一个logger logger = logging.getLogger('mylogger') logger.set ...
- Java 日志管理最佳实践
转:http://blog.jobbole.com/51155/ 日志记录是应用程序运行中必不可少的一部分.具有良好格式和完备信息的日志记录可以在程序出现问题时帮助开发人员迅速地定位错误的根源.对于开 ...
- Log4Net异常日志记录在asp.net mvc3.0的应用
前言 log4net是.Net下一个非常优秀的开源日志记录组件.log4net记录日志的功能非常强大.它可以将日志分不同的等级,以不同的格式,输出到不同的媒介.本文主要是简单的介绍如何在Visual ...
- Atitit 拦截数据库异常的处理最佳实践
Atitit 拦截数据库异常的处理最佳实践 需要特殊处理的ex 在Dao层异常转换并抛出1 Server层转换为业务异常1 需要特殊处理的ex 在Dao层异常转换并抛出 } catch (SQLExc ...
- paip.java gui swt/jface 最佳实践
paip.java gui swt/jface 最佳实践 1. 工具:Eclipse +jigloo4 1 2. 安装插件: 1 1. IMPORT swt lib 2 2. 新建立窗体 2 3. 运 ...
- Log4Net异常日志记录在asp.net mvc3.0的应用(转载)
这篇博客写的很好:http://www.cnblogs.com/qianlifeng/archive/2011/04/22/2024856.html 前言 log4net是.Net下一个非常优秀的开源 ...
- paip.提升性能--多核编程中的java .net php c++最佳实践 v2.0 cah
paip.提升性能--多核编程中的java .net php c++最佳实践 v2.0 cah 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax ...
- atitit.Atitit. Gui控件and面板-----服务端控件 java struts的实现最佳实践
atitit.Atitit. Gui控件and面板-----服务端控件 java struts的实现最佳实践 1. 服务器控件的类别 1 1.1. 数据控件:该类控件可细分为两种类型:数据源控件和数 ...
- Java 处理异常 9 个最佳实践,你知道几个?
1. 在Finally中清理资源或者使用Try-With-Resource语句 使用Finally Java 7的Try-With-Resource语句 2. 给出准确的异常处理信息 3. 记录你所指 ...
随机推荐
- onload事件
onload事件:页面加载(文本和图片)完毕的时候, onload的作用: JS加载时和html是同步加载的,如果使用元素在定义元素之前易报错: <!DOCTYPE html> <h ...
- Zabbix系列之二——添加监控主机步凑
1.登录监控平台,配置——主机——创建主机 2.主机设置 3.添加模板
- SpringBoot之OAuth2.0学习之客户端快速上手
2.1.@EnableOAuth2Sso 这个注解是为了开启OAuth2.0的sso功能,如果我们配置了WebSecurityConfigurerAdapter,它通过添加身份验证过滤器和身份验证(e ...
- [java初探09]__关于java的包装类
前言 在Java语言的学习过程中,我们逐渐的理解了Java面向对象的思想,与类和对象的应用.但是在基本数据类型的使用上,我们无法将其定义为一个对象,通过使用对象的方法来使用它们,但是Java语言的思想 ...
- SQL 必知必会·笔记<18>管理事务处理
事务处理是一种机制,用来管理必须成批执行的SQL操作,保证数据库不包含不完整的操作结果.利用事务处理,可以保证一组操作不会中途停止,它们要 么完全执行,要么完全不执行(除非明确指示).如果没有错误发生 ...
- PHP序列化变量的4种方法
序列化是将变量转换为可保存或传输的字符串的过程:反序列化就是在适当的时候把这个字符串再转化成原来的变量使用.这两个过程结合起来,可以轻松地存储和传输数据,使程序更具维护性. 1. serialize ...
- 深入学习卷积神经网络(CNN)的原理知识
网上关于卷积神经网络的相关知识以及数不胜数,所以本文在学习了前人的博客和知乎,在别人博客的基础上整理的知识点,便于自己理解,以后复习也可以常看看,但是如果侵犯到哪位大神的权利,请联系小编,谢谢.好了下 ...
- Docker系列之Docker镜像(读书笔记)
一.基本概念 Docker包括三个基本概念镜像.容器.仓库. Docker镜像:就是一个只读的模板.例如:一个镜像可以包含一个完整的ubuntu操作系统环境,里面仅安装了Apache或其他应用程序.用 ...
- Java集合框架——容器的快速报错机制 fail-fast 是什么?
前言:最近看 java 集合方面的源码,了解到集合使用了 fail-fast 的机制,这里就记录一下这个机制是什么,有什么用,如何实现的. 一.fail-fast 简介 fail-fast 机制,即快 ...
- [转]---UAP中如何判断当前APP在哪个平台设备上运行
在做Win10开发的时候,我们可能经常会需要获得当前程序在在哪个平台设备上运行,用于UI和相关API的调用,那么可以通过什么方式知道当前APP运行的平台呢? 今天这里提供两个方法给大家做参考: 方法一 ...