浅析接口安全之WebService
2020-04-13 09:45:00 Author: xz.aliyun.com(查看原文) 阅读量:499 收藏

0x0 前言

  关于这类型漏洞很少有人发表相关学习资料,最近笔者遇到了这种漏洞,并根据了网上寥寥无几的文章思路安装了工具来测试,结果却发现工具没办法成功攻击,但是漏洞真实存在,所以笔者就以此为基础展开了关于WebServices的学习,去了解相关的构造原理,改进工具化测试的不足。

0x1 WebService的架构

  笔者查阅了挺多的相关资料,提到了非常多很陌生的技术,这里我对其进行了自我总结,如有不对,欢迎师傅们指出改正。

什么是WebService?

Web Service是一个平台独立的,低耦合的,自包含的、基于可编程的web的应用程序,可使用开放的XML标准通用标记语言下的一个子集)标准描述、发布、发现、协调和配置这些应用程序,用于开发分布式的交互操作的应用程序

总结:

Web服务(WebService)是一种跨语言和跨平台的远程调用(RPC)技术

所谓跨编程语言和跨操作平台,就是说服务端程序采用java编写,客户端程序则可以采用其他编程语言编写,反之亦然!跨操作系统平台则是指服务端程序和客户端程序可以在不同的操作系统上运行。
所谓远程调用,就是一台计算机a上 的一个程序可以调用到另外一台计算机b上的一个对象的方法。

ps.WebService思想有点跟微服务很像,是一种比较"重"和“老”的Web接口技术,目前大部分应用于金融机构的历史应用和比较老的引用中,在内网里面遇到的机会还是挺多的。

WebService的工作流程

服务端应用程序首先向外界暴露出一个能通过Web进行调用的API,为了实现跨平台和跨语言,那么与这个API交互的时候,就需要有一套标准的类型系统来描述WebService这个接口,让用户通过这个标准来解析怎么调用这个接口,然后用户将解析结果封装上自己的数据发送到客户端,服务端统一采用这一套标准进行解析和返回。

WebService的技术实现与支持

1.SOAP(Simple Object Access Protocol, 简单对象访问协议)

SOAP协议 由特定的HTTP信息头和XML内容格式组成

SOAP = http协议 + XML数据格式

2.WSDL(Web Services Description Language, 网络服务描述语言)

给出了SOAP型Web Service的基本定义,WSDL基于XML语言,描述了与服务交互的基本元素,比如函数、数据类型、功能等,少数情况下,WSDL也可以用来描述REST型Web Service。

WSDL文件保存在Web服务器上,通过一个url地址就可以访问到他。客户端要调用WebService服务之前,要知道该服务的WSDL文件的地址。

3.REST(Representational State Transfer, 表征性状态转移)

REST型Web Service允许我们使用JSON格式(也可以使用XML格式)与服务器进行通信。与HTTP类似,该类型服务支持GET、POST、PUT、DELETE方法。

4.WADL(Web Application Description Language, 网络应用描述语言)

WSDL的REST版,一般用于REST型Web Service,描述与Web Service进行交互的基本元素。

PS.笔者目前接触的比较多就是第1.2种,所以就以经典SOAP协议的WebService作为学习目标了。

应用场景

webservice 经常使用在异构系统中,比如一个JAVA开发的OA系统与一个C#开发的CRM系统进行系统交互的时候就可以利用WebService来统一交互标准,当然也可以在同构系统中整合该服务,统一系统交互的标准。这就好比我们经常使用API接口使用JSON封装数据,但是JSON有点缺陷,emmm不算缺陷,是以为其自身的跨域性特点有可能会导致jsonp攻击。

0x2 编写WebService服务

这里笔者介绍两种最常见WebService开发环境。

0x2.1 JAVA下的CXF框架编写

简单介绍下CXF框架:

CXF(Celtix + XFire)

一个apache用于开发WebService服务端和客户端的框架。

1.安装CXF的依赖包

proxychains4 wget https://mirror-hk.koddos.net/apache/cxf/3.3.6/apache-cxf-3.3.6.tar.gz

2.创建一个项目,导入CXF lib下的依赖包

(1)ICalculator 接口类

package com.xq17.cxf;

import javax.jws.WebService;

@WebService
public interface ICalculator {
        int add(int a, int b);
        String concat(String a, String b);
}

(2)CalculatorImpl 接口实现类

package com.xq17.cxf;

import javax.jws.WebService;

@WebService(endpointInterface="com.xq17.cxf.ICalculator", serviceName="Calcutator")
public class CalculatorImpl implements ICalculator{
    @Override
    public int add(int a, int b) {
        return a + b;
    }
    @Override
    public String concat(String a, String b) {
        return a + b;
    }
}

(3) WebService服务端类

package com.xq17.cxf;

import javax.xml.ws.Endpoint;

public class WebService {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println("Web Service Start!");
        CalculatorImpl implementor = new CalculatorImpl();
        String address  = "http://127.0.0.1:8081/calculator";
        Endpoint.publish(address, implementor);
        // 这里就能加载已经定义为WebService接口的CalculatorImpl对象和发布网址
        System.out.println("web service started");
    }
}

(4) Run

(4) 访问URL

可以看到成功输出了相应的信息。

0x2.2 ASP.NET下编写简单的WebService

1.在空白窗体新建一个web服务WebService.asmx

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;

/// <summary>
/// WebService 的摘要说明
/// </summary>
[WebService(Namespace = "http://localhost/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。 
[System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService
{
    public WebService()
    {

        //如果使用设计的组件,请取消注释以下行 
        //InitializeComponent(); 
    }

    [WebMethod]
    public string HelloWorld()
    {
        return "Hello World";
    }

    [WebMethod]
    public int Power(int num)
    {
        return num * num;
    }

}

这里我们写了一个Power函数

2.然后发布到IIS,访问URL

当我们点击服务说明的时候跳转到:http://localhost:8089/WebService.asmx?WSDL

返回的就是WSDL,说明这个接口怎么使用。

访问http://localhost:8089/WebService.asmx?op=Power可以在浏览器直接调用,这里给出发出的协议,及其返回结果的例子,方便我们写对应的程序来进行调用该服务。

1.SOP1.1

POST /WebService.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://localhost/Power"

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <Power xmlns="http://localhost/">
      <num>int</num>
    </Power>
  </soap:Body>
</soap:Envelope>
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <PowerResponse xmlns="http://localhost/">
      <PowerResult>int</PowerResult>
    </PowerResponse>
  </soap:Body>
</soap:Envelope>

SOP1.2

POST /WebService.asmx HTTP/1.1
Host: localhost
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <Power xmlns="http://localhost/">
      <num>int</num>
    </Power>
  </soap12:Body>
</soap12:Envelope>
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <PowerResponse xmlns="http://localhost/">
      <PowerResult>int</PowerResult>
    </PowerResponse>
  </soap12:Body>

1.3 HTTP

这个仅是支持本机来测试,对外部是不开放的。

POST /WebService.asmx/Power HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: length

num=string
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<int xmlns="http://localhost/">int</int>

这里我们演示下soap1.2协议的发送过程。

我们可以直接复制SOAP12的包发送数据来进行请求。

可以看到这里返回了webservice

<PowerResult>9</PowerResult>

这个接口的结果。

PS:

CXF框架整合Spring发布的时候默认会有个services路径,里面存放了接口的文档说明,这个时候我们就可以获取所有的EndPoint了,笔者当时遇到的就是这个情况。

基于C#的ASP.NET编写的接口信息页就是当前接口的位置,所以我们只要找asm文件来测试就好。

0x3 服务接口手工测试思路

下面我们就来讲一下WSDL到底提供了什么样的解析标准,如何去进行手工构造。

我们首先需要学习下WSDL的描述结构,并尝试自己去解析,编写合法的数据包。

首先WSDL的组成标签:

definitions 根元素,其主要作用是提供了targetNamespace的命名空间

types 主要是用来描述传入的参数类型,和输出的结果类型,被信息定义使用

imports 用于在当前的WSDL文档中使用其他WSDL文档中指定的命名空间的定义元素,一般用在模块化多文件WSDL文档中使用。

message 抽象定义了两个信息(需要传递的数据),可以理解为相当于types的接口。

portType 定于了web服务的抽象接口,没有定义实现

operation 服务支持操作的抽象描述,同时包含input和output则表明该操作是一个请求、响应模式。

binding 将一个portType映射到一组具体的协议,描述特定端口类型的具体协议和数据规范。

service 相关端点的集合,包括其关联的接口、操作、信息等。

由此我们可以将WSDL文档划分为两部分:

1.抽象定义

2.具体定义

下面我们就以这个例子来解读下怎么解析:

1.

首先这里service标签描述了服务名称WebService,port name描述了可以支持soap协议,然后提供了访问地址(EndPoint)。这里可以看到每种协议都有自己的绑定。

2.

定位相关的绑定,我们可以看到这里绑定的类型引用了Type值得类型,然后使用operatation标签将porrtType中定义的operation同SOAP请求绑定,定义了操作名称soapAction

3.

这里inputoutput引用了<messgae>标签

4.

这里PART标签,引用messafg下的参数类型

然后我们再来看一个SOAP1.2协议的格式:

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope
 xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"
>
<soap12:Header>
</soap12:Header>
<soap12:Body>
<soap12:Fault>
</soap12:Fault>
</soap12:Body>
</soap12:Envelope>

1.1的话直接去掉12即可。

Envelope: 标识XML文档,具有名称空间和编码详细信息。
Header:包含标题信息,如内容类型和字符集等。
Body:包含请求和响应信息。
Fault:错误和状态信息。

而平时我们构造的SOAP请求数据包,不包含Fault部分(返回的SOAP出错就会有),解析的重点是在Body部分

POST /calculator HTTP/1.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:74.0) Gecko/20100101 Firefox/74.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: csrftoken=P2JwVlLK3L8PaHlSMJ927Sj7JgrIwBi4S82j9I25ZIJx3Vytf3c72Qi9Ehc75VXs; Hm_lvt_b393d153aeb26b46e9431fabaf0f6190=1576593337,1576724740,1577006110,1578371563
Upgrade-Insecure-Requests: 1
SOAPAction: 
Content-Type: text/xml;charset=UTF-8
Host: 127.0.0.1:8081
Content-Length: 352

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cxf="http://cxf.xq17.com/">
   <soapenv:Header/>
   <soapenv:Body>
      <cxf:concat>
         <!--type: string-->
         <arg0>gero et</arg0>
         <!--type: string-->
         <arg1>sonoras imperio</arg1>
      </cxf:concat>
   </soapenv:Body>
</soapenv:Envelope>

所以我们构造的时候只需要关注输入参数部分complexType即可,将一些值写入到SOAP的body即可。

我们确定下方法的命名空间然后根据参数类型就可以写出上面的SOAP数据包了。

0x4 工具实现半自动化测试

手工测试的时候其实很容易出错,因为SOAP1.1与SOAP1.2协议形成的HTTP协议并不相同,所以我更推荐大概理解其原理,然后让工具生成,然后我们在手工调整,来测试和发现,比如未授权漏洞,当我们没有传入值时,或者省略参数时,只调用方法时,默认会返回所有结果之类的

我平时使用的话应该是Burp比较多,然后导入wsdler这个插件。

这里简要说说自己的测试流程:

1.首先我们访问接口URL+?wsdl

2.获取解析的SOAP结果,存在两个方法

3.发到重放,注释部分说明参数部门,然后进行正常的接口测试,SQL注入、未授权等。

PS:

简单说一下一些小技巧,有些服务器可能访问不到WSDL文件,这个时候我们可以根据接口名字GetEnterpriseTransactionResult然后推测出方法名:getEnterpriseTransaction

然后根据返回的报错信息确定命名空间。

还有全自动化测试可以采用AWVS,这个我没测试过效果,我个人感觉应该很棒,或者crawgo+awvs,到时候笔者将挖洞框架建立后,会进行尝试添加这类型漏洞的检测,欢迎师傅们找我一起探讨挖洞技巧,主要是SRC吧。

0x5 总结

  基于SOAP协议的接口攻击技术,其实历史比较悠久的了,并且该技术运用到各种语言开发的程序中,在2017年的OWASP TOP 10也出现了它的身影,Penetration Testing with SOAP Service and Mitigation,可以看到一旦掌握了接口,那么攻击面的测试就可以变得很宽广,后面我遇到更多实例的话,我再进行一些骚操作的总结。

0x6 参考链接

Web Service 渗透测试从入门到精通

WebService到底是什么?

WebService学习总结

搭建调用 WebService 的 ASP.NET 网站 (VS2010, C#)

使用apache CXF和maven开发Web Service

CXF发布webService(一)

WSDL结构简单分析

从几道CTF题看SOAP安全问题

快速入门


文章来源: http://xz.aliyun.com/t/7541
如有侵权请联系:admin#unsafe.sh