突發:當機崩潰OOM

changlong2022發表於2024-10-14

突發:當機崩潰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,免得出現當機無法復現,無法排查問題

相關文章