PHP 代码审计与安全编码

日就完事了

Posted by RTL on August 7, 2018

PHP 代码审计与安全编码

代码审计的目的

  • 目的决定行为
  • 代码审计前的准备
    • 得到代码
      • 开源程序
      • 非开源程序(黑盒扫描)
    • 得到平台信息
      • php 版本及 php.ini 一些基本配置, os配置, web 服务信息, 数据库应用

代码审计的本质

  • 两大根本:变量与函数
  • 漏洞现成的条件
    • 可以控制的变量(一切输入都是有害的)
    • 变量到达有利用价值的函数(一切进入函数的变量都是有害的)

函数导致的漏洞

  • 文件包含 -> 包含漏洞
  • 代码执行 -> 执行任意代码漏洞
  • 命令执行 -> 执行任意命令漏洞
  • 文件系统操作 -> 文件(目录)读写等漏洞
  • 数据库操作 -> SQL注射漏洞
  • 数据显示 -> XSS等客服端漏洞

代码审计通用思路

  • 找漏洞 -> 找对应变量与函数
  • 通过变量找函数(正向跟踪变量)
  • 通过函数找变量(逆向跟踪变量)

补丁对比技术

  • 基于源代码
  • 对比工具
    • 系统命令: fc; diff
    • 专业工具: Beyond Compare; UltraCompare
  • 常见的安全补丁方式
    • 变量初始化
    • 变量过滤

业务功能与漏洞

  • 实现业务功能的同时引入安全风险
    • 上传功能 -> 上传漏洞
    • 数据存储与查询 -> SQL注入漏洞
    • 后台或者 API 接口 -> 安全认证绕过
    • 数据库备用 -> 导出 webshell
  • 新的功能必定带来新的安全隐患
  • 功能越强大说明漏洞的几率越大

相似性漏洞挖掘

  • 天下武学同出少林[天下代码一把抄]
    • 最经典的 asp: 动网上传漏洞
  • 每个程序员都有自己的代码风格习惯
  • 相同的功能带来同样的漏洞
  • 寻找相似性漏洞

基于白盒的 fuzz

  • 变量的储存
  • 对于数据库储存查询

常用变量与函数

  • 如 include/require; eval; system 等函数

高级的代码审计

  • 寻找新的 “变量与函数”

PHP 代码审计漏洞发现与安全编码

注入

普通的 SQL 注入

  • 字符串拼接

变量的传递与二次漏洞

  • 什么是二次漏洞
    • 通过一个现有漏洞,创造新的漏洞使漏洞利用最大化
<?php
highlight_file(__file__);
function dbconnection(){
  @$con = mysql_connect("localhost","root","root");
  if (!$con){
    echo "Failed to connect to MySQL: " . mysql_error();
  }
  @mysql_select_db("ctf",$con) or die ( "Unable to connect to the database");
  mysql_query("SET character set 'UTF8'");
}
dbconnection();
Session_start();
function reg(){
  $username = addslashes($_GET['username']);
  $password = addslashes($_GET['password']);
  $sql = "insert into users values(null,'$username','test@test.com','$password')";
  echo $sql;
  mysql_query($sql);
}

function login(){
  $username = addslashes($_GET['username']);
  $password = addslashes($_GET['password']);
  $sql = "select * from users where username='$username' and password='$password'";
  echo $sql;
  $result=mysql_query($sql);
  if(@$row = mysql_fetch_array($result)){
    //登录成功
    $_SESSION['userid'] = $row['id'];
    $_SESSION['username'] = $row['username'];
  }
}
function insert_news(){
  $content = addslashes($_GET['content']);
  $username = $_SESSION['username'];
  $sql = "insert into news(author,content) values('$username','$content')";
  echo $sql;
  mysql_query($sql);
}
function show_news(){
  $sql = "select * from news";
  $result=mysql_query($sql);
  while(@$row = mysql_fetch_array($result)){
    echo 'author:'.$row['author'].'  content:'.$row['content'].'<br>';
  }
}

$action = $_GET['action'];
if(in_array($action,array("reg","login","insert_news","show_news"))){
  call_user_func($action);
}

SQL 注入通用防治

  • 预编译
  • 对类型判断

X-Forwarded-For 注入防范

  • 检测 ip

XSS

CSRF

不安全的反序列化

  • php 反序列化漏洞又称对象注入,可能会导致远程代码执行。php 中执行 unserialize 函数,调用某一类并执行 magic method,之后执行类中函数,可能会产生安全问题。

  • 反序列化常用的 magic method

    • _destruct()
    • _wakeup()
    • _toString()
    • _get()
    • _set()
    • _isset()
    • _unset()
    • _call()
    • _invoke()

XML 外部实体 (XXE)

  • 另一篇博文
  • 如何修复
    • 禁用外部实体
    • 过滤用户提交的 xml 数据

拓展我们的字典