数据库日志是系统问题还是应用问题?

唯品会日志系统dragonfly 1.0是基于EFK构建,于2014年服务至今已长达7年,支持物理机日志采集,容器日志采集,特殊分类日志综合采集等,大大方便了全公司日志的存储和查询。

随着公司的业务发展,日志应用场景逐渐遇到了一些瓶颈,主要表现在应用数量和打印的日志越来越多,开发需要打印更多日志,定位业务问题,做出运营数据分析;另外外部攻击问题和审计要求,需要更多安全相关的日志数据要上报并且能够提供半年以上的保存时长,以应对潜在的攻击和攻击发生时调查原因和受影响面。ELK的架构的缺点显现,ES集群规模达260台机器,需要的硬件和维护成本高达千万,如果通过扩容的方法去满足上述业务场景,ES集群会太大会变动不稳定,创建独立集群,也需要更高成本,两者都会使得成本和维护工作量剧增。

鉴于这些问题,去年六月份我们开始探索新的日志系统架构,以彻底解决上面的问题。

时间戳,日志级别,线程名,类名,eventName,和自定义字段将被日志采集Agent解析后和其他元数据如域名,容器名或主机名一起以JSON格式上报。

自定义字段是开发人员根据业务需要打印到日志,主要支持功能:

①查询时支持各种聚合分析场景

②根据自定义字段进行聚合函数告警。

EFK日志存储在elasticsearch,每个域的日志以天粒度在ES创建一个索引,索引大小是根据前几日数据大小计算得出,每个索引分片大小不超过30G,日志量越多的域分片越多。如果一个域的日志量写入过大或超长,将会占用ES节点大量CPU来做解析和segment合并,这会影响其他域日志的正常写入,导致整体写入吞吐下降。排查是哪个域的哪个分片日志过大通常较为困难,在面对这种热点问题时经常要花很长时间。我们ES版本使用的是5.5,还不支持索引自动删除和冷热迁移,有几个脚本每日定时执行,完成删除索引,关闭索引,移动冷索引,创建新索引的任务,其中移动索引和创建新索引都是耗时非常长的操作。整个生命周期每天循环执行,如果突然一天某个步骤执行失败,或者执行时间太长,会导致整个生命周期拉长甚至无法完成,第二天的新数据写入将受到严重影响,甚至无法写入。另外ES的倒排索引需要对日志进行分词,产生的索引文件较大,占用了大量磁盘空间。

不过ES也有其优点,基于倒排索引的特性使得ES查询时,1个分片只需要一个核即可完成查询,因为查询速度通常较快,QPS较高。下面是在大规模(或海量)日志存储场景下ES的主要存储优点和缺点:

2019年我们尝试了另外一种HDFS存储方案,把每个域的数据按照域名+toYYDDMMHH(timestamp)+host作为键在客户端缓存,当大小或过期时间到了之后,提交到HDFS生成一个独立的文件,存储路径包含了域,主机和时间信息,搜索时即可根据这几个标签过滤,这种存储方式有点类似loki,它的缺点显而易见,优点是吞吐和压缩率都非常高,可以解决我们吞吐和压缩率不足的问题。如果基于此方案继续增强功能,如添加标签,简单的跳数索引,查询函数,多节点并发查询,多字段存储,需要开发的工作量和难度都非常大。我们对比了业界前沿使用的一些存储方案,最终选择了clickhouse,他的批量写入和列式存储方案完全满足我们的要求(基于HDFS存储),另外还提供了占用磁盘空间非常小的主键索引和跳数索引,相比ES的全文索引,优势明显。

实际生产环境中zstd的日志压缩比更高,这和应用日志的相似度有关,最大达到15.8。

Clickhouse压缩率这么高,但没有索引,其查询速度如何?虽然没有索引,但其向量执行和SIMD配合多核CPU,可以大大缓解没有全文索引的缺点。经过多次测试对比后,其查询速度在绝大多数场景下和ES不相上下,在部分场景下甚至比ES还要快。

下图是实际生产环境的数千个应用真实运行数据,查询24小时时间范围内日志和24小时以上时间范围日志的耗时对比

通过对日志的应用场景分析,我们发现万亿级别的日志,真正能被查询的日志数量是非常非常少的,这意味着ES对所有日志的分词索引,大多数是无效的,日志越多,这个分词消耗的资源越浪费。相对比clickhouse的MergeTree引擎专一的多,主要资源消耗是日志排序压缩和存储。

另外Clickhouse的MPP架构使得集群非常稳定,几乎不要太多运维工作。下面以一幅图综合对比ES和Clickhouse的优缺点,说明为什么我们选择将clickhouse作为下一代日志存储数据库。

EFK架构发展这么多年体系要成熟得多,ES默认参数和倒排索引使得你不需要对ES有太多了解即可轻松使用,开源kibana又提供丰富的查询界面和图形面板,对于日志量不大的场景来讲,EFK架构仍然是首选。Clickhouse是近几年OLAP领域比较热门的数据库,其成熟度和生态仍在快速发展中,用来存储日志的开源方案不是很多,要用好它不但需要对Clickhouse有深入的了解,还需要做很多开发工作。

起初dragonfly使用logstash来做日志采集,但logstash的配置较复杂并且无法支持配置文件下发,不便于容器环境下的日志采集,当时另一个使用GO语言开发的采集工具vfilebeat在性能和扩展性方面较好,我们在此基础上做了定制开发自己的日志采集组件vfilebeat。

vfilebeat运行在宿主机上,启动时可以通过参数指定采集的宿主机日志所属的域,如果没有指定,则读取安装时CMDB配置文件的域名和主机名,宿主机采集的每条日志均带上域名和主机名作为标签。

容器环境下vfilebeat还会监听容器的创建和销毁,当容器创建时,读取容器的POD信息获取到域名和主机名,然后从ETCD拉取到域的日志采集路径等配置参数,按照域名和POD名称生成容器所属目录的日志文件采集路径,并在本地生成新的配置文件,vfilebeat重新加载配置文件,即可滚动采集。

现在我们环境绝大部分应用均使用vfilebeat采集,少部分场景保留使用logstash采集。vfilebeat将采集到的日志附带上应用和系统环境等标签,序列化配置的数据格式,上报到kafka集群,应用日志是JSON,Accesslog为文本行。

writer把从kafka消费的数据先转换为结构化数据,vfilebeat上报的时候可能会上报一些日期较久的数据,太久的数据,报上来意义不大,并且会导致产生比较多的小part,消耗clickhosue cpu资源,这一步把这些过期超过三天的日期丢掉,无法解析的数据或者缺少必须字段的日志也会丢掉。经解析过滤后的数据再经过转换步骤,转换为clickhouse的表字段和类型。

转换操作从schema和metadata表读取域日志存储的元信息,schema定义了clickhouse本地表和全局表名,字段信息,以及默认的日志字段和表字段的映射关系。metadata定义了域日志具体使用的schema信息,日志存储的时长,域分区字段值,域自定义字段映射到的表字段,通过这些域级别的配置信息,我们做到可以指定域存储的表,存储的时长,超大日志域独立分区存储,降低日志合并的CPU消耗。自定义字段默认是按照数组存储,有些域打印的自定义日志字段较多,在日志量大的情况下,速度较慢,配置了自定义映射物理字段存储,可以提供比数组更快的查询速度和压缩率。

  • 域自定义存储元数据信息

经过转换后的数据,携带了存储到CK表所需要的所有信息,将临时存储在本地的一个队列内,本地队列可能混合存储了多个域多张表的日志,达到指定的长度或时间后,再被提交到一个进程级的全局队列内。

因为writer进程是多线程消费多个kafka分区,全局队列将同一个表多个线程的数据合并到一起,使得单次提交的批次更大,全局线程短暂缓冲,当满足写入条数,大小或超时后,数据将被作为一次写入,提交到submit worker线程。submit worker负责数据的写入,高可用,负载均衡,容错和重试等逻辑。

submit收到提交的批量数据后,随机寻找一个可用的clickhosue分片,提交写入到分片节点。clickhouse集群配置是双副本,当一个副本节点失败时,将尝试切换写入到另一个节点上,如果两个都失败,则暂时剔除分片,重新寻找一个健康的分片写入。

写入数据到Clickhouse我们使用的是clickhouse-jdbc,起初写入时消耗内存和CPU都较大,对jdbc源码进行分析后,我们发现jdbc写入数据时,先把所有数据转换成一个List对象,这个list对象相当于提交数据的byte[]副本格式,为了降低这个占用,在数据转换步骤我们进行优化,每条日志数据直接转换为jdbc可以直接使用的List数据,这样jdbc在构造生成SQL的时候,拿到的数据其实是List的一个引用,这个优化降低了约三分之一内存消耗。

clickhouse的弱集群概念保证了单节点宕机时,整个集群几乎不受影响,submit高可用保证了当节点异常时,数据仍然可以正常写入到健康节点,从而使得整个日志写入非常稳定,几乎没有因为节点宕机导致的延迟情况。

关于日志摄入Clickhouse的方式,石墨开源了另一种摄入方式,创建KafkaEngine表直接消费clickhouse,再将数据导入到物化视图内,通过物化视图最终导入到本地表。这种方式好处是节省了一个writer的组件,上报到kafka的数据直接就可以存储到clickhouse,但缺点非常多:

  • 每个topic都需要创建独立的KafkaEngine,如果需要切换表,增加topic,都要变更DDL,并且无法支持一个topic不同域存储到不同表
  • 另外解析kafka数据和物化视图都要消耗节点CPU资源,而clickhouse合并和查询都是非常依赖cpu资源的操作,这会加重clickhouse的负载,从而限制了clickhosue整体吞吐,影响了查询性能,需要扩容更多的节点来缓解此问题,clickhouse的单台服务器需要更多核数,SSD和大磁盘存储,因此扩容成本很高。

择了将解析写入组件独立出来,可解决上面提到的很多问题,也为后期很多扩展功能提供了很大灵活性,好处很多,不再一一列举。

提交到Clickhouse的数据以二维表的形式存储,二维表我们使用的是Clickhouse最常用的MergeTree引擎,关于MergeTree更详细的描述可以参考网上这篇文章《MergeTree的存储结构》。

  • 数据在磁盘的逻辑存储示意图

MergeTree采用类似LSM-Tree数据结构存储,每次提交的批量数据,按照表的分区键,分别保存到不同的part目录内,一个part内的行数据按照排序键进行排序后,再按列压缩存储到不同的文件内,Clickhouse后台任务会持续对这些每个小型的part进行合并,生成更大的part。

MergeTree虽然没有ES的倒排索引,但有更轻量级的分区键,主键索引和跳数索引。

  • 分 区键可以确保查找 的时 候 快速过滤掉很多part , 例 如按照时间 搜索时,只 命中时间 范围的part。
  • 主键索引和关系型数据库的主键不同,是用来对排序数据块 进行快速查找 的轻量级索引。
  • 跳数索引则根据索引类型对字段值进行索引,例如minmax索引指定字段的最大值和最小值,set存储了字段的唯一值进行索引,tokenbf_v1则对字段进行切分,创建bloomfilter索引,查询的时候可以直接根据关键字计算日志是否在对应数据块内.

个part的数据会被按照排序键进行排序,然后按照大小切分成一个个较小的块(index_granularity),块默认有8192行,同时主键索引对每个块的边界进行索引,跳数索引则根据索引的字段生成索引文件,通常这三者生成的索引文件都非常小,可缓存在内存中加速查询。

了解了MergeTree的实现原理,我们可以发现,影响Clickhouse写入的一个关键因素是part的数量,每次写入都会产生一个part,part越多,那么后台合并任务也将越繁忙。除了这个因素外,part的生成和合并均需要消耗CPU和磁盘IO。

所以总结一下,三个影响写入的因素:

要提高写入吞吐,就需要从这三个因素入手,降低part数量,提高CPU核数,提高磁盘IO

将图中的方法按照实现手段进行分类

硬件:CPU核数越多越好,我们生产环境40+,磁盘SSD是标配,由于SSD价格贵容量小,采用SSD+HDD冷热分离模式

表结构:长日志量又大的域使用bloomfilter索引加速查询,其他域则使用普通跳数索引即可,我们测试观察能节约近一半的CPU。

数据写入:Writer提交的数据,按照分区键进行分批提交,或者部分分区字段都可,也即单次提交的分区键基数尽可能小,最理想为1,此方法可大大降低小part数量。分区键的选择上,可根据应用日志的数量选择独立分区键,存储大日志量域,大日志量应用通常会达到条数阈值提交,可使得合并的part都是较大part,效率高;或者混合分区键,将小应用混合在一个分区提交。

很多次,我和别人解释为什么日志系统没有(全文索引)仍然这么快的原因时,我都直接丢出这张图,图源自商用产品Humio公司的网站,也是我们老板多次推荐我们学习参考的一个产品,2021年初已被CrowdStrike以4亿美元收购。

1PB的数据存储,没有了全文索引的情况,直接暴力检索一个关键字,肯定是超时的,如果先经过时间,标签以及bloomfilter进行过滤筛选后,再执行暴力搜索,则需要检索的数据量会小的多。MergeTree引擎是列式存储,压缩率很高,高压缩率有很多优势,从磁盘读取的数据量少,页面缓存需要的内存少,更多的文件可以缓存在高速内存中,Clickhouse有和Humio一样的向量化执行和SIMD,在查询时,这些内存中的压缩数据块会被CPU批量的执行SIMD指令,由于块足够小,通常为压缩前1M,这样函数向量执行和SIMD计算的数据足够全部放在cpu缓存内,不仅减少了函数调用次数,并且cpu cache的miss率大大降低。查询速度相比没有向量执行和SIMD有数倍提升。

起初我们计划使用表级别的TTL来管理日志,将不同存储时长的日志放入不同的表内,但这样会导致表和物化视图变得非常多,不方便管理,后来使用了一个改进方案,将TTL放在表分区字段内,开发一个简单的定时任务,每天扫描删除所有超过TTL日期的part,这样做到了一张表支持不同TTL的日志存储,灵活性非常高,应用可以通过界面很方便查看和调整存储的时长。

3.5 自定义字段存储方案

标准格式日志内的自定义字段名称由业务输出,基数是不确定的,我们第一版方案是创建数百个字符串,整数和浮点数的扩展字段,由开发自行配置这个自定义映射,后来发现这个方案存在严重缺陷:

①开发需要将日志的每一个字段均手动配置到映射上去,随着日志的变更,这样的字段越来越多,随着数量膨胀将难以维护,

②Clickhouse需要创建大量的列来保存这些字段,由于所有应用混合在一起存储,对于大多数应用,太多列不但浪费,并且降低了存储速度,占用了大量的文件系统INODE节点

后来借鉴了Uber日志存储的方案,每种数据类型的字段,分别创建两个数组,一个保存字段名称,另一个保存字段值,名字和值按顺序一一对应,查询时,使用clickhouse的数组检索函数来检索字段,这种用法支持所有的Clickhouse函数计算。

原来的映射自定义字段目前仍然保留10个,如果不够,可以随时添加,可以支持一些域的固定自定义字段,或者一些特殊类型的日志,例如审计日志,系统日志等,这些字段在查询的时候用户可以使用原来的名称,访问Clickhouse之前会被替换为表字段名称

自定义字段的另一个方案是存储在map内,可以节约两个字段,查询也更简单,但经过我们测试,查询性能没有数组好:

①数组存储压缩率相比比Map略好

②数组查询速度比Map快1.7倍以上

③Map的查询语法比数组简单,在前端简化了数组的查询语法情况下,这个优势可忽略

日志系统第一版是基于kibana开发的,版本较老。2.0系统我们直接抛弃旧版,自研了一套查询系统,效果如下:

新版查询会自动对用户输入的查询语句进行分析,添加上查询的应用域名和时间范围等,降低用户操作难度,支持多租户隔离。

自定义字段的查询是非常繁琐的,我们也做了一个简化操作:

Clickhouse一次执行一条语句,日志查询时柱状图和TOP示例日志是两条语句,会使得查询时间范围翻倍,参考携程的优化方法,查询详情时,我们会根据柱状图的结果,将时间范围缩小至TOP条记录所在的时间区间。

Clickhouse丰富的查询语法,让我们新日志系统的查询分析功能非常强大,从海量日志提取关键字,非常容易,下面列举两个查询用法:

①从文本和JSON混合的日志数据中提取JSON字段

1、打印日志不要太长,不超过10K

2、查询条件带上有跳数索引的标签,或者其他非日志详情的字段,召回日志数越小,查询速度越快

OLAP数据库Clickhouse是处理大规模数据密集型场景的利器,非常适合海量日志存储和查询分析,构建了一个低成本,无单点,高吞吐,高速查询的下一代日志系统。

}

来源: 【如有侵权请留言,将进行删除,谢谢】

攻击者可以通过应用程序中许多的不同的路径方式去危害企业业务。每种路径方法都代表了一种风险,这些风险都值得关注。

OWASP(开放式Web应用程序安全项目)是一个开放的社区,由非营利组织 OWASP基金会支持的项目。对所有致力于改进应用程序安全的人士开放,旨在提高对应用程序安全性的认识。

其最具权威的就是“10项最严重的Web 应用程序安全风险列表” ,总结并更新Web应用程序中最可能、最常见、最危险的十大漏洞,是开发、测试、服务、咨询人员应知应会的知识。

OWASP Top 10 2021 是全新的,具有新的图形设计和一页有用的信息图。

2021 年前 10 名发生了什么变化

有三个新类别,四个类别的命名和范围发生了变化,并且 2021 年的前 10 名中进行了一些合并。

从第五位上升;94% 的应用程序都经过了某种形式的破坏访问控制的测试。映射到 Broken Access Control 的 34 个 CWE 在应用程序中出现的次数比任何其他类别都多。

上移一位至 #2,以前称为敏感数据泄露,这是广泛的症状而不是根本原因。此处重新关注与密码学相关的漏洞,这些漏洞通常会导致敏感数据泄露或系统受损。

下滑到第三位。94% 的应用程序都针对某种形式的注入进行了测试,映射到此类别的 33 个 CWE 在应用程序中的出现次数排名第二。跨站点脚本攻击现在是此版本中此类别的一部分。

是2021 年的一个新类别,重点关注与设计缺陷相关的风险。如果我们真的想作为一个行业“安全左移”,就需要更多地使用威胁建模、安全设计模式和原则以及参考架构。

从上一版的第 6 位上升;90% 的应用程序都经过了某种形式的错误配置测试。随着更多定制性高度可配置的软件,看到这一类别上升也就不足为奇了。XML 外部实体 (XXE) 的前一个类别现在属于此类别。

之前的标题是 使用具有已知漏洞的组件,在行业调查中排名第二,但也有足够的数据通过数据分析进入前 10 名。该类别从 2017 年的第 9 位上升,是我们难以测试和评估风险的已知问题。它是唯一没有任何 CVE 映射到包含的 CWE 的类别,因此默认的利用和影响权重 )、库、数据库等中的安全设置未设置为安全值。

  • 服务器不发送安全标头或指令,或者它们未设置为安全值。
  • 软件已过时或易受攻击(请参阅 A06:2021-易受攻击和过时的组件)。

如果没有协调一致的、可重复的应用程序安全配置过程,系统将面临更高的风险。

安全配置错误 - 如何预防

应实施安全安装过程,包括:

  • 可重复的强化过程使部署另一个适当锁定的环境变得快速而轻松。开发、QA 和生产环境都应配置相同,在每个环境中使用不同的凭据。这个过程应该是自动化的,以最大限度地减少设置新安全环境所需的工作。
  • 一个没有任何不必要的功能、组件、文档和示例的最小平台。删除或不安装未使用的功能和框架。
  • 作为补丁管理流程的一部分,审查和更新适用于所有安全说明、更新和补丁的配置的任务(请参阅 A06:2021-易受攻击和过时的组件)。查看云存储权限(例如,S3 存储桶权限)。
  • 分段应用程序架构通过分段、容器化或云安全组 (ACL) 在组件或租户之间提供有效且安全的分离。
  • 向客户端发送安全指令,例如安全标头。
  • 验证配置和设置在所有环境中的有效性的自动化过程。

安全配置错误 - 攻击场景示例

场景#1:应用程序服务器带有未从生产服务器中删除的示例应用程序。这些示例应用程序具有攻击者用来破坏服务器的已知安全漏洞。假设这些应用程序之一是管理控制台,并且默认帐户未更改。在这种情况下,攻击者使用默认密码登录并接管。

场景#2:服务器上没有禁用目录列表。攻击者发现他们可以简单地列出目录。攻击者找到并下载已编译的 Java 类,对其进行反编译和逆向工程以查看代码。然后攻击者发现应用程序中存在严重的访问控制缺陷。

场景#3:应用服务器的配置允许将详细的错误消息(例如堆栈跟踪)返回给用户。这可能会暴露敏感信息或潜在缺陷,例如已知易受攻击的组件版本。

场景#4:云服务提供商拥有其他 CSP 用户对 Internet 开放的默认共享权限。这允许访问存储在云存储中的敏感数据。

A06:2021 – 易受攻击和过时的组件 概述

它在行业调查中排名第二,但也有足够的数据通过数据进入前 10 名。易受攻击的组件是我们难以测试和评估风险的已知问题,并且是唯一没有任何 CVE 映射到包含的 CWE 的类别,因此使用默认的漏洞利用/影响权重 5.0。值得注意的CWE包括CWE-1104:使用未维护的第三方组件和来自 2013 年和 2017 年前 10 名的两个 CWE。

易受攻击和过时的组件 - 描述

  • 如果您不知道您使用的所有组件的版本(客户端和服务器端)。这包括您直接使用的组件以及嵌套的依赖项。
  • 如果软件易受攻击、不受支持或已过期。这包括操作系统、Web/应用程序服务器、数据库管理系统 (DBMS)、应用程序、API 和所有组件、运行时环境和库。
  • 如果您不定期扫描漏洞并订阅与您使用的组件相关的安全公告。
  • 如果您没有以基于风险的方式及时修复或升级底层平台、框架和依赖项。这通常发生在修补是变更控制下的每月或每季度任务的环境中,使组织面临数天或数月不必要地暴露于固定漏洞的风险。
  • 如果软件开发人员不测试更新、升级或修补的库的兼容性。
  • 如果您不保护组件的配置(请参阅 A05:2021-安全配置错误)。

易受攻击和过时的组件 - 如何预防

应该有一个补丁管理流程来:

  • 删除未使用的依赖项、不必要的功能、组件、文件和文档。
  • 使用版本、OWASP Dependency Check、retire.js 等工具持续清点客户端和服务器端组件(例如框架、库)及其依赖项的版本。成分。使用软件组合分析工具来自动化该过程。订阅与您使用的组件相关的安全漏洞的电子邮件警报。
  • 仅通过安全链接从官方来源获取组件。首选签名包以减少包含修改后的恶意组件的机会(请参阅 A08:2021-软件和数据完整性故障)。
  • 监视未维护或未为旧版本创建安全补丁的库和组件。如果无法打补丁,请考虑部署虚拟补丁来监控、检测或防止发现的问题。

每个组织都必须确保在应用程序或产品组合的生命周期内制定持续的监控、分类和应用更新或配置更改的计划。

易受攻击和过时的组件 - 攻击场景示例

场景#1:组件通常以与应用程序本身相同的权限运行,因此任何组件中的缺陷都可能导致严重影响。此类缺陷可能是偶然的(例如,编码错误)或有意的(例如,组件中的后门)。发现的一些可利用组件漏洞的示例是:

  • CVE- 是一个 Struts 2 远程代码执行漏洞,可以在服务器上执行任意代码,已被归咎于重大漏洞。
  • 虽然物联网 (IoT) 通常很难或不可能修补,但修补它们的重要性可能很大(例如,生物医学设备)。

有一些自动化工具可以帮助攻击者找到未打补丁或配置错误的系统。例如,Shodan IoT 搜索引擎可以帮助您找到仍然存在 2014 年 4 月修补的 Heartbleed 漏洞的设备。

以前称为Broken Authentication,此类别从第二位下滑,现在包括与识别失败相关的 CWE。包括的值得注意的CWE包括CWE-297:不正确的证书验证与主机不匹配CWE-287:不正确的身份验证CWE-384:会话固定

认证和授权失败 - 描述

确认用户的身份、身份验证和会话管理对于防止与身份验证相关的攻击至关重要。如果应用程序存在以下情况,则可能存在身份验证漏洞:

  • 允许自动攻击,例如撞库,其中攻击者拥有有效用户名和密码的列表。
  • 允许蛮力或其他自动攻击。
  • 允许使用默认密码、弱密码或众所周知的密码,例如“Password1”或“admin/admin”。
  • 使用弱或无效的凭据恢复和忘记密码流程,例如无法确保安全的“基于知识的答案”。
  • 使用纯文本、加密或弱散列密码(请参阅 A3:2017-敏感数据暴露)。
  • 缺少或无效的多因素身份验证。
  • 在 URL 中公开会话 ID(例如,URL 重写)。
  • 成功登录后不要轮换会话 ID。
  • 不会正确地使会话 ID 无效。用户会话或身份验证令牌(主要是单点登录 (SSO) 令牌)在注销或一段时间不活动期间未正确失效。

认证和授权失败 - 如何预防

  • 在可能的情况下,实施多因素身份验证以防止自动凭证填充、暴力破解和被盗凭证重用攻击。
  • 不要使用任何默认凭据进行交付或部署,尤其是对于管理员用户。
  • 实施弱密码检查,例如针对前 10,000 个最差密码列表测试新密码或更改的密码。
  • 将密码长度、复杂性和轮换策略与 NIST 800-63b 的第 5.1.1 节中关于记忆秘密的指南或其他现代的、基于证据的密码策略保持一致。
  • 通过对所有结果使用相同的消息,确保注册、凭据恢复和 API 路径能够抵御帐户枚举攻击。
  • 限制或增加延迟失败的登录尝试。当检测到凭证填充、暴力破解或其他攻击时,记录所有故障并提醒管理员。
  • 使用服务器端、安全、内置的会话管理器,在登录后生成新的高熵随机会话 ID。会话 ID 不应在 URL 中,安全存储,并在注销、空闲和绝对超时后失效。

认证和授权失败 - 攻击场景示例

场景#1:凭证填充(使用已知密码列表)是一种常见的攻击。假设应用程序没有实施自动化威胁或凭证填充保护。在这种情况下,应用程序可以用作密码预言机来确定凭证是否有效。

场景#2:大多数身份验证攻击是由于继续使用密码作为唯一因素而发生的。一经考虑,最佳实践、密码轮换和复杂性要求会鼓励用户使用和重复使用弱密码。建议组织按照 NIST 800-63 停止这些做法并使用多因素身份验证。

场景 #3:应用程序会话超时设置不正确。用户使用公共计算机访问应用程序。用户没有选择“注销”,而是简单地关闭浏览器选项卡并走开。攻击者在一个小时后使用同一个浏览器,而用户仍然通过身份验证。

A08:2021 – 软件和数据完整性故障 概述

2021 年的新类别侧重于在不验证完整性的情况下做出与软件更新、关键数据和 CI/CD 管道相关的假设。来自 CVE/CVSS 数据的最高加权影响之一。著名的CWE包括CWE-502:不可信数据的反序列化CWE-829:包含不受信任的控制领域的功能CWE-494:下载没有完整性检查的代码

软件和数据完整性故障 - 描述

软件和数据完整性故障与不能防止完整性违规的代码和基础设施有关。例如,在对象或数据被编码或序列化为攻击者可以看到和修改的结构的情况下,很容易受到不安全的反序列化的影响。另一种形式是应用程序依赖来自不受信任的来源、存储库和内容交付网络 (CDN) 的插件、库或模块。不安全的 CI/CD 管道可能会导致未经授权的访问、恶意代码或系统受损。最后,许多应用程序现在包括自动更新功能,其中更新在没有充分完整性验证的情况下被下载并应用于以前受信任的应用程序。攻击者可能会上传自己的更新以分发并在所有安装上运行。

软件和数据完整性故障 - 如何预防

  • 确保未签名或未加密的序列化数据不会在没有某种形式的完整性检查或数字签名的情况下发送到不受信任的客户端,以检测序列化数据的篡改或重放
  • 通过签名或类似机制验证软件或数据来自预期来源
  • 确保库和依赖项(例如 npm 或 Maven)使用受信任的存储库
  • 确保您的 CI/CD 管道具有正确的配置和访问控制,以确保流经构建和部署过程的代码的完整性。

软件和数据完整性故障 - 攻击场景示例

场景 #1 不安全的反序列化: React 应用程序调用一组 Spring Boot 微服务。作为函数式程序员,他们试图确保他们的代码是不可变的。他们提出的解决方案是序列化用户状态并在每个请求中来回传递它。攻击者注意到“R00”Java 对象签名并使用 Java Serial Killer 工具在应用服务器上获取远程代码执行权。

场景 #2 无需签名即可更新:许多家用路由器、机顶盒、设备固件和其他固件不通过签名固件验证更新。未签名固件是攻击者越来越多的目标,预计只会变得更糟。这是一个主要问题,因为很多时候除了在未来版本中修复并等待以前的版本过时之外,没有任何补救机制。

场景#3 SolarWinds 恶意更新:众所周知,国家会攻击更新机制,最近的一次著名攻击是 SolarWinds Orion 攻击。开发该软件的公司拥有安全的构建和更新完整性流程。尽管如此,这些还是能够被破坏,并且在几个月的时间里,该公司向 18,000 多个组织分发了一个高度针对性的恶意更新,其中大约 100 个组织受到了影响。这是历史上此类性质最深远、最重大的违规行为之一。

A09:2021 – 安全日志记录和监控失败 概述

安全日志记录和监控来自行业调查(#3),比 2017 年 OWASP 前 10 名中的第十位略有上升。日志记录和监控可能很难测试,通常涉及采访或询问是否在渗透测试期间检测到攻击。此类别的 CVE/CVSS 数据不多,但检测和响应漏洞至关重要。尽管如此,它对于可见性、事件警报和取证仍然非常有影响力。此类别扩展到CWE-778 日志记录不足之外,包括CWE-117 日志的不当输出中和CWE-223 安全相关信息的遗漏CWE-532 将敏感信息插入日志文件

安全日志记录和监控失败 - 描述

回到 2021 年 OWASP 前 10 名,该类别旨在帮助检测、升级和响应主动违规行为。如果没有日志记录和监控,就无法检测到漏洞。任何时候都会发生日志记录、检测、监控和主动响应不足的情况:

  • 不记录可审计的事件,例如登录、失败登录和高价值交易。
  • 警告和错误不会生成、不充分或不清楚的日志消息。
  • 不会监控应用程序和 API 的日志是否存在可疑活动。
  • 适当的警报阈值和响应升级流程没有到位或有效。
  • DAST 工具(例如 OWASP ZAP)的渗透测试和扫描不会触发警报。
  • 应用程序无法实时或接近实时地检测、升级或警告主动攻击。

通过使用户或攻击者可以看到日志记录和警报事件,您很容易受到信息泄漏的影响(请参阅 A01:2021 – 损坏的访问控制)。

安全日志记录和监控失败 - 如何预防

开发人员应实施以下部分或全部控制措施,具体取决于应用程序的风险:

  • 确保所有登录、访问控制和服务器端输入验证失败都可以用足够的用户上下文来记录,以识别可疑或恶意帐户,并保留足够的时间以允许延迟取证分析。
  • 确保以日志管理解决方案可以轻松使用的格式生成日志。
  • 确保日志数据编码正确,以防止对日志或监控系统的注入或攻击。
  • 确保高价值交易具有带有完整性控制的审计跟踪,以防止篡改或删除,例如仅追加数据库表或类似的。
  • DevSecOps 团队应该建立有效的监控和警报,以便快速检测和响应可疑活动。
  • 制定或采用事件响应和恢复计划,例如 NIST 800-61r2 或更高版本。

有商业和开源应用程序保护框架(例如 OWASP ModSecurity 核心规则集)和开源日志关联软件(例如 ELK 堆栈)具有自定义仪表板和警报功能。

安全日志记录和监控失败 - 攻击场景示例

场景#1:由于缺乏监控和日志记录,一家儿童健康计划提供商的网站运营商无法检测到违规行为。外部方通知健康计划提供者,攻击者访问并修改了超过 350 万儿童的数千份敏感健康记录。事后审查发现网站开发人员没有解决重大漏洞。由于没有对系统进行日志记录或监控,数据泄露可能自 2013 年以来一直在进行,时间超过七年。

场景#2:印度一家大型航空公司发生数据泄露事件,涉及数百万乘客超过十年的个人数据,包括护照和信用卡数据。数据泄露发生在第三方云托管服务提供商处,该提供商在一段时间后将泄露事件通知了航空公司。

场景 #3:一家主要的欧洲航空公司遭遇了 GDPR 可报告的违规行为。据报道,该漏洞是由攻击者利用的支付应用程序安全漏洞引起的,他们收集了超过 400,000 条客户支付记录。该航空公司因此被隐私监管机构罚款 2000 万英镑。

此类别是从行业调查 (#1) 中添加的。数据显示发生率相对较低,测试覆盖率高于平均水平,利用和影响潜力评级高于平均水平。由于新条目可能是用于关注和意识的单个或一小部分 CWE,因此希望它们受到关注,并且可以在未来版本中纳入更大的类别。

每当 Web 应用程序在未验证用户提供的 URL 的情况下获取远程资源时,就会出现 s-s-rF 缺陷。它允许攻击者强制应用程序将精心设计的请求发送到意外目的地,即使受到防火墙、VPN 或其他类型的网络 ACL 的保护也是如此。

随着现代 Web 应用程序为最终用户提供方便的功能,获取 URL 成为一种常见情况。因此,s-s-rF 的发病率正在增加。此外,由于云服务和架构的复杂性,s-s-rF 的严重性越来越高。

开发人员可以通过实施以下部分或全部深度防御控制来防止 s-s-rF:

  • 在单独的网络中分段远程资源访问功能以减少 s-s-rF 的影响
  • 强制执行“默认拒绝”防火墙策略或网络访问控制规则,以阻止除基本 Intranet 流量之外的所有流量

服务器端请求伪造 (s-s-rF) - 从应用层:

  • 清理和验证所有客户端提供的输入数据
  • 使用肯定的允许列表强制执行 URL 架构、端口和目标
  • 不要向客户端发送原始响应
  • 注意 URL 一致性,以避免 DNS 重新绑定和“检查时间、使用时间”(TOCTOU) 竞争条件等攻击

不要通过使用拒绝列表或正则表达式来缓解 s-s-rF。攻击者拥有有效负载列表、工具和技能来绕过拒绝列表。

服务器端请求伪造 (s-s-rF) - 攻击场景示例

攻击者可以使用 s-s-rF 攻击受 Web 应用程序防火墙、防火墙或网络 ACL 保护的系统,使用的场景包括:

场景#1:端口扫描内部服务器。如果网络架构是未分段的,攻击者可以绘制内部网络,并根据连接结果或连接或拒绝 s-s-rF 负载连接所用的时间来确定内部服务器上的端口是打开还是关闭。

场景#2:敏感数据暴露。攻击者可以访问本地文件,例如 或内部服务以获取敏感信息。

场景#3:访问云服务的元数据存储。大多数云提供商都有元数据存储,例如http://169.254.169.254/。攻击者可以读取元数据来获取敏感信息。

场景#4:破坏内部服务——攻击者可以滥用内部服务进行进一步的攻击,例如远程代码执行 (RCE) 或拒绝服务 (DoS)。

}

我要回帖

更多关于 数据库应用系统核心 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信