1 情况简述

WEB运用系统漏洞造成 的侵入经常发生,扫描枪和WAF并不可以处理全部的难题,因此试着在服务器侧对于PHP自然环境干了一个防御计划方案。很荣幸的邀约到TSRC一部分白帽干了一次抵抗演练,文中关键共享一下防御构思。

防御计划方案关键想处理的难题是getshell、服务器比较敏感文档泄露等难题。因此出了下边那样一个题型:布署了防御计划方案的Nginx PHP 的WEB自然环境,出示一个上传到口,可提交随意文档。寻找WEB文件目录下的一个flag文件载入到內容即算提升。

2 PHP扩展

防御计划方案应用了PHP扩展来进行阻隔。PHP核心适用C/C 开发设计一些扩展作用,而且出示了一个架构 – ext_skel协助形成基础的编码简单化开发设计,因为PHP扩展并不涉及到最底层的资源优化配置,因此 撰写一个PHP扩展和撰写一个C应用软件是一样的。下面的图展现了PHP扩展所处的结构层级,扩展坐落于PHP核心ZEND 和 PHP网络层编码中间,那麼运用PHP扩展能够:

1) 监管PHP网络层编码的执行关键点,包含执行CGI、涵数名、主要参数等;

2) 启用PHP核心ZEND出示的API接口,包含禁止使用类、改动配备选择项等。

分享PHP场景中getshell防御思路 防御思路 getshell 脚本攻防  第1张

图1 PHP語言的构造

3 有关专业知识

3.1 HOOKPHP编码

PHP是解释型语言,编码被汉语翻译为正中间字节码由ZEND模块分析执行。PHP把正中间字节码称作OPCODE,每一个OPCODE相匹配ZEND最底层的一个处理函数,ZEND模块最后执行这一处理函数。完成HOOK作用只必须更改HOOK OPCODE相匹配的处理函数就可以,而ZEND事先就出示了一个现有的接口:zend_set_user_opcode_handler。防御计划方案只必须HOOK下列三个OPCODE:

ZEND_INCLUDE_OR_EVAL — eval、require等

ZEND_DO_FCALL — 涵数执行system等

ZEND_DO_FCALL_BY_NAME — 自变量涵数执行 $func = “system”;$func();

举例说明:

ZEND_DO_FCALL这一OPCODE相匹配的作用是调用函数,假如必须HOOK全部的调用函数:

1) 在控制模块复位涵数中应用zend_set_user_opcode_handler改动ZEND_DO_FCALL新的处理函数为mysub:

PHP_MINIT_FUNCTION(phpips){

zend_set_user_opcode_handler(ZEND_DO_FCALL, mysub);

return SUCCESS;

}

2) 在自定义函数中完成自身必须的作用并回到原先的处理函数:

void mysub(){

自定作用;

return ZEND_USER_OPCODE_DISPATCH;

}

3.2 ZEND接口

HOOK以外还必须获得一些基本资料或作用,例如:

1) 获得执行的PHP脚本制作名,可启用ZEND的接口zend_get_executed_filename:

char *cgi_name = (char*)zend_get_executed_filename(TSRMLS_C);

2) 禁止使用一些类库,可应用zend_disable_class接口;

ZEND出示了许多 丰富多彩的接口,可依据要求挑选启用。

3.3 算法设计

PHP是弱种类語言,其顶层并不区别变量类型,自变量最底层相匹配的是一个union结构体,以php-5.3.6版本号举例说明,结构体在Zend/zend.h文件中界定;內容以下:

typedef union _zvalue_value {

long lval; /* longvalue */

double dval; /* double value */

struct {

char *val;

int len;

} str;

HashTable *ht; /* hash table value*/

zend_object_value obj;

} zvalue_value;

PHP是在最底层区别开过变量类型;在union结构体中有一个十分关键的结构体HashTable,PHP中的数组构造便是运用HashTable这一结构体完成,假如自变量是个数组,获得自变量內容必须解析xml这方面HashTable,算法设计这方面不做过多详细介绍。ZEND最底层用zval这一结构体储存自变量,另外ZEND出示了好多个宏能够便捷的变换zval到实际的基本数据类型,例如把zval类型转换字符串数组 – zval el; Z_STRVAL_P(el),常见的也有:

Z_LVAL_P、Z_DVAL_P、Z_ARRVAL_P等,之上宏目录在 Zend/zend_operators.h有界定。

4 标准对策

4.1 理论依据

大家必须处理的难题是getshell、服务器比较敏感文档泄露等难题。假如限制住PHP脚本制作执行指令 和 阅览文档的作用,就做到了目地。另外,因为读取文件的接口十分多,应用情景也较多,因而采用禁止使用开启文件目录接口来侧边做到严禁阅览文档的目地,不可以解析xml文件目录便没法获得文件夹名称,能够合理的实现目标。故最后产生的最后对策以下:

1) 禁止使用掉执行指令的接口

2) 禁止使用掉开启文件目录的接口

禁止使用涵数有一些必须留意的难题:

1) PHP接口還是较为多种多样繁杂的,除开system、exec、opendir、scandir常用函数以外,一些冷僻涵数例如glob等涵数必须考虑到全方位,此外也有一些回调函数、反射面类(PS:一部分考虑到不全被blackeye和雪娃娃绕开)

2) PHP SPL出示的一些类库有文档管理的作用,也必须严禁,例如DirectoryIterator(但是仿佛沒有白帽应用过SPL)

4.2 抵抗形变

PHP应用assert或preg_replace /e执行编码,启用zend_get_executed_filename获得的PHP脚本制作名时会含有鉴别标志,assert相匹配的是assert code,preg_replace相匹配的是regexp code;当发觉这种独特的脚本制作执行了system等4.1中提升 的高风险涵数立即阻隔。下列图的nonalphanumeric -webshell举例说明:

形变webshell分析后的方式和$_GET[1]($_GET[2])相近,例如传到1=assert&2=system(whoami)执行编码,PHP扩展层监管到system涵数执行,而且发觉PHP脚本制作名带regexp code标志,清楚的了解是preg_replace的编码执行了启用了system,阻隔system。Assert涵数同样。汇总:扩展并不关心在静态数据层怎样编号计算或数据加密,扩展只监管最终的个人行为,因此 能够非常好的解决目前的形变难点。

分享PHP场景中getshell防御思路 防御思路 getshell 脚本攻防  第2张

图2nonalphanumeric – webshell

4.3 降低误伤

有时候一切正常的PHP脚本制作也必须采用指令执行的作用,怎样确保其一切正常运作,不被大家的防御对策阻隔呢?这儿出示三种构思:

1) 载入管理权限和执行指令管理权限相互独立

充分考虑侵略者运用提交系统漏洞或是别的0DAY getshell获得的文档大多数会出现W写管理权限,防御方通常期待阻拦这些文档有着过高的管理权限。

那麼,我们可以除去一切正常PHP脚本制作的应写管理权限,随后只对有写管理权限的PHP脚本制作执行指令执行等防御对策的阻隔逻辑性。那样即不容易危害到业务流程的应用,又做到了预置情景的安全防护总体目标。但是那样的构思,必须禁止使用chmod等能够改动文件权限的涵数。

2) 应用授权管理逻辑性

粗鲁一点的可以用文件夹名称授权管理,也就是业务流程上报过的文档不会受到阻隔,其他不认识的文档一律严禁。雅致一点的能够对函数参数做授权管理,例如获取一切正常PHP脚本制作执行指令的主要参数或是编码特点,对其开展海关放行,不认识的特点一律阻隔。

3) 应用信用黑名单逻辑性

设置一些已经知道故意脚本制作的黑特征参数,类似电脑杀毒软件初期的机器码构思。

所述构思在企业品牌推广时,必须和业务流程有充足充足的相互配合,也都是有有缺憾的地区,假如大伙儿有大量计划方案或是构思,热烈欢迎和我相互讨论。

5 将来

运用PHP扩展能够做的事儿還是比较多,例如在网站漏洞扫描层面、对数据库查询函数参数过虑、阻隔SQL引入、阻隔储存型XSS等情景都是有十分大的想像室内空间。乃至在代码审计这方面还可以考虑到,中国有一个大神早已有较为完善的开源系统商品,TAINT (创作者:laruence),大伙儿很有可能都早已较为了解了,就临时不做过多阐释了。

写作较为匆忙,有不够的地区请谅解,有随意疑惑或提议热烈欢迎联络pandas(小毛驴)PK沟通交流。