突发:宕机崩溃OOM

突发:宕机崩溃OOM

 

事故背景:我们的项目每年都进行一次三级等保认证,2024年*月*日认证公司对我们的项目进行渗透测试时,我们系统出现无法访问和使用的情况。出现问题后我们联系认证公司停止测试,系统依然没有恢复。

事故分析: 

1. 出现问题后我第一时间检查了日志,发现了OOM

java.lang.OutOfMemoryError: Java heap space

at org.apache.tomcat.util.threads.TaskThreadFactory.newThread(TaskThreadFactory.java:42) 

由于没有dump日志所以不好排查OOM的原因,我便加上了启动参数:

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/heapdump-9001.hprof 

然后联系对方公司再测试一遍 

  1. OOM再次出现,我拿到了heapdump-9001.hprof,开始用MemoryAnalyzer 进行分析,首先查看大对象(Dominator Tree)

 

大对象在这儿看,点进去发现最大的是 数据库相关

 

最大的这个对象有1个多G,有200多万条数据,都在内存里

 

 

怎么可能有200多万呢,肯定是查错了,难道SQL注入导致把数据库里所有数据都查出来了?

再去数据库查下,果然是所有数据:

  1. 再尝试找找代码是哪儿运行的,

 

点开LeakSuspects

 

找到

 

好多都是框架代码,我们尝试在里面找到 认识的业务相关代码: 

 

 

  1. 找到getFiles代码:

 

 

这里都是拼接的SQL,有SQL注入问题,应该就是这儿的问题了。

 

  1. 那么对方公司是怎么注入的呢,每个请求在Ngnix Acess日志里有记录,我尝试到Ngnix里查找日志,发现了 

/request?view&cgFormField=-1'%20OR%202%2B663-663-1=0%2B0%2B0%2B1%20or%20'BApebRcZ'='

 

添加日志发现 该参数传入后,SQL变成了这样:

 

 

注意两个or 之间 变成了 1=1 永恒true,也就导致把所有数据都查出来了。 

原因已经找到了,那么该如何解决呢,之前知道用预编译prepareStatement就行, 但这里的代码 不适合大动,查了下用StringEscapeUtils.escapeSql()  比较合适,改成这样

 

 

 

同样的参数再次测试

 

相当于整个字符串 是个value ,不会被恶意拆掉 

事故复盘:

查看了该处代码提交记录,很久之前就是这么写的,往年渗透测试时并没有测出来。比起追究责任,更重要的是给我们提醒:

  1. 注意SQL注入问题,不要拼接原生SQL,可以用上面的注入字符串自测。
  2. 每个应用都应该加上-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath,免得出现宕机无法复现,无法排查问题
posted @ 2024-10-14 10:49  changlong2022  阅读(18)  评论(0编辑  收藏  举报