Httpoxy漏洞看Java与CGI如何交互

具体漏洞httpoxy详情可以先参考在https://httpoxy.org/

1  什么是CGI

CGI是外部应用程序(CGI程序)与Web服务器之间的接口标准,是在CGI程序和Web服务器之间传递信息的过程。CGI规范允许Web服务器执行外部程序,并将它们的输出发送给Web浏览器,CGI将Web的一组简单的静态超媒体文档变成一个完整的新的交互式媒体。

2 CGI的运行方式

⑴  通过Internet把用户请求送到服务器

⑵  服务器接收用户请求并交给CGI程序处理 

⑶  CGI程序把处理结果传送给服务器 

⑷  服务器把结果送回到用户

3 CGI的交互方式

Web 服务器和CGI交互,CGI 是独立的程序,为了方便web服务器和CGI的交互,web服务器获得http参数后fork子进程,部分参数通过设置环境变量于CGI交互。

RFC 3875 规范里定义了一些交互的环境变量的名称,而针对HTTP传递的头,通常web服务器设置成HTTP_HeaderName环境变量进行交互

 

在这个漏洞中,将PROXY 设置成了CGI的环境变量HTTP_PROXY

CGI代码本身如果是获取HTTP_PROXY环境变量用于获取资源的代理,或者运行的第三方的组件也使用这个环境变量作为代理,这样黑客可以通过设置http 请求中的PROXY, 控制CGI 里的环境变量HTTP_PROXY

4  Java web容器如何和CGI交互

在3中已经提到了服务器和CGI的交互方式,主要以起子进程交互的方式,对java来说可以使用Runtime.getRuntime().exec()的方式,通过perl 来执行.cgi 

1)        通过参数和cgi交互

在执行cgi的时候也可以添加额外的参数,可以作为perl执行的参数命令

常见的可以通过请求的url的参数进行传递

http://www.test.com/cgi?parameter

而针对后面parameter,可以直接通过命令拼接的方式进行运行

perl test.cgi parameter

 

java 示例

Runtime.getRuntime().exec(“perl test.cgi parameter”);

 

2)        通过环境变量和cgi交互

在3中提到的环境变量于CGI交互,比如在http请求中的头,默认以HTTP_ heade大写=value的格式设置环境变量

 

例子:以前面的PROXY为例

PROXY:www.test.com

 

Java 示例

 

Runtime.getRuntime().exec(“perl test.cgi parameter”, new String[]{“HTTP_PROXY=www.test.com”});

3)        通过输入流和cgi交互

通常GET请求可以通过querystring 或者header来传递值和cgi交互,但是如果是post呢?

对post 的参数为了避免覆盖header, 所以不使用HTTP_前缀的方式设置环境变量,而是通过流的方式传递

获取子进程的输入流

Process proc= Runtime.getRuntime().exec(“perl test.cgi parameter”, new String[]{“HTTP_PROXY=www.test.com”});

OutputStream stdin = proc.getOutputStream();

获取web的post的流

InputStream stdout =request.getInputStream();

 

将stdout.read的内容复制到strout中

byte[] buf = new byte[4*1024];

int numRead;

while ( (numRead = stdout.read(buf) ) >= 0) {

     stdin.write(buf, 0, numRead);

 }

 

 

这样cgi获取的是urlencoder的parameterName = parameterValue&parameterName = parameterValue 的内容

4)        通过输出流获取cgi的执行内容

 

 

InputStream cgiOutput = proc.getInputStream();

OutputStream out = response.getOutputStream();

 byte[] buf = new byte[4*1024];

int numRead;

while ( (numRead = cgiOutput.read(buf) ) >= 0) {

     out.write(buf, 0, numRead);

 }

 

如果CGI里返回的标准http协议的话,可以直接用流对拷输出


5 解决Httpoxy 漏洞

考虑到HTTP_PROXY 环境变量很多组件里已经使用的默认的环境变量参数,主要防御方式以过滤http头proxy,因为proxy并不是一个标准的http 头

写个 filter 过滤器

public class PoxyFilter implements Filter {

 

    public void doFilter(ServletRequest request, ServletResponse response,

                         FilterChain chain) throws java.io.IOException,

                                                   ServletException {

 

 

        HttpServletRequest req = (HttpServletRequest)request;

        HttpServletResponse res = (HttpServletResponse)response;

        String poxy = req.getHeader("proxy");

        if (poxy == null) {

          chain.doFilter(request, response);

        } else {

          …………

        }

    }

}


你可能感兴趣的:(httproxy漏洞,java和cgi)