概述
代码审计是对应用程序源代码进行系统性检查的工作,目的是为了找到并且修复应用程序在开发阶段存在的一些漏洞,或者程序逻辑错误。
从代码级别上,也就是应用层次上考虑代码安全的话,程序安全问题就是函数和变量的问题。变量接收到不安全的输入后,没有做恰当的过滤,又用在不同的函数上,就可能造成不同的危害。
审计方法
- 通篇阅读代码:根据代码整体逻辑进行漏洞挖掘
- 查找危险函数:使用代码审计工具通过正则匹配危险函数,然后根据危险函数中的变量回溯到传入变量的方式
- 根据功能点进行审计:定位敏感功能点,分析功能是否存在安全缺陷
工具介绍
SeayPHP
seayPHP是一款针对PHP代码安全审计的系统,基于C#语言开发,主要用于windows系统,主要使用正则来匹配危险函数,直接新建项目,把源代码拖进工具即可
工具下载地址:https://github.com/f1tz/cnseay
RIPS
RIPS是一款基于PHP编写的静态代码分析工具,可检测PHP应用程序中的漏洞,并进行结构化输出,RIPS还提供了一个集成的代码审核框架。
工具下载地址:https://sourceforge.net/projects/rips-scanner/files/
超全局变量
PHP中预定义了几个超级全局变量,这意味着他们在一个脚本的全部作用域中都可用,不需要进行特别说明,就可以在函数即类中使用。
- $GLOBALS
是PHP的一个超级全局变量组,在一个PHP脚本的全部作用域中都可以访问。包含了全部变量的全局组合数组。变量的名字就是数组的键。
- $_SERVER
包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组。这个数组中的项目由 Web 服务器创建。
下面列出了所有 $_SERVER 变量中的重要元素:
- $_REQUEST
用于收集HTML表单提交的数据。
- $_POST
用于收集表单数据,在HTML form标签的指定该属性:"method="post"。
- $_GET
用于收集表单数据,在HTML form标签的指定该属性:"method="get"。
- $_FILES
通过 HTTP POST 方式上传到当前脚本的项目的数组
- $_ENV
通过环境方式传递给当前脚本的变量的数组。
- $_COOKIE
通过 HTTP Cookies 方式传递给当前脚本的变量的数组。
- $_SESSION
当前脚本可用 SESSION 变量的数组。
74cms v5.0.1前端sql注入
74cms源码下载地址:http://www.74cms.com/download/index.html
文件地址:
74cms_Home_Setup_v5.0.1/Application/Home/Controller/AjaxPersonalController.class.php
从代码中可以看出传入的$company_id参数未经过函数的过滤
public function company_focus($company_id) {
if (!$company_id) {
$this->ajaxReturn(0, '请选择企业!');
}
$r = D('PersonalFocusCompany')->add_focus($company_id, C('visitor.uid'));
$this->ajaxReturn($r['state'], $r['msg'], $r['data']);
}
注:
Public:表明该函数是对所有的用户开放的,所有用户可直接调用
Private:表示为私有的,除了class自己,任何人都不可以直接调用
Protected:受保护的类,对于它的继承类来说是公开的,没有任何限制,对其他外部的类,就会变为私有的,不可访问。
$this->ajaxReturn(0, '请选择企业!');
使用ThinkPHP的ajaxReturn方法返回数据,数据格式为
$this->ajaxReturn(返回数据,提示信息,操作状态);
data 返回数据 、info 提示信息 、status 操作状态
返回数据data可以支持字符串、数字和数组、对象,返回客户端的时候根据不同的返回格式进行编码后传输。如果是JSON格式,会自动编码成JSON字符串,如果是XML方式,会自动编码成XML字符串,如果是EVAL方式的话,只会输出字符串data数据,并且忽略status和info信息。
->符号用户引用对象的成员(属性与方法)
=>符号可以自定义任意字符键名
然后跟踪add_focus函数,发现SQL语句参数可控,造成sql注入漏洞
文件路径:/Application/Common/Model/PersonalFocusCompanyModel.class.php
public function add_focus($company_id,$uid){
$has = $this->check_focus($company_id,$uid);
if($has){
$this->where(array('company_id'=>$company_id,'uid'=>$uid))->delete();
return array('state'=>1,'msg'=>'已取消关注!','data'=>array('html'=>’关注','op'=>2));
}else{
$this->add(array('company_id'=>$company_id,'uid'=>$uid,'addtime'=>time()));
return array('state'=>1,'msg'=>'已关注','data'=>array('html'=>'取消关注','op'=>1));
}
}
public function check_focus($company_id,$uid){
return $this->where(array('company_id'=>$company_id,'uid'=>$uid))->find();
}
注:
Where:如需有条件的从表中选取数据,可将Where添加到SELECT语句
语法:SELECT 列名称 FROM 表名称 WHERE 列 运算符 值
74cms v4.2.3任意文件删除
文件位置: 74cms_v4.2.3/Application/Admin/Controller/DatabaseController.class.php
public function del(){
$name = I('request.name','','trim');
!$name && $this->error('请选择要删除的备份文件');
!is_array($name) && $name = array($name);
foreach ($name as $key => $val) {
rmdirs(DATABASE_BACKUP_PATH.$val,true);
}
$this->success('删除备份文件成功');
}
变量$name未经任何过滤,直接使用请求包中的文件名,把传进来的文件名生成 $name数组,并用foreach() 进行遍历,然后传输到rmdirs方法进行删除
注:
foreach ($name as $key => $val)
foreach是一种遍历数组的简便方法,而且只能用于数组,当用于其他数据类型,或者一个未初始化的变量时会产生错误。fareach有两种语法
foreach($name as $val)
遍历给定的 $name数组。每次循环中,当前单元的值被赋给 $val 并且数组内部的指针向前移一步(因此下一次循环中将会得到下一个单元)
foreach($name as $key => $val)
遍历给定的 $name数组。每次循环中,当前单元的值,键值被赋给 $val 并且数组内部的指针向前移一步(因此下一次循环中将会得到下一个单元)
- is_array($name),检测$name是否为一个数组
语法:bool is_array ( mixed $var )
$var:要检测的变量,如果检测的变量是数组,则返回 TRUE,否则返回 FALSE。