代码审计
1. 定义
- 根据应用程序源代码,从结构、脆弱性以及缺陷等方面进行审查,最终输出代码审计报告,完善应用程序,提高自身安全水平
2. 工具
(1). 辅助工具
- Notepad++编辑器
- Seay源码审计系统
(2). 其他工具
a. UltraEdit
- 轻量级代码编辑器,支持十六进制查看及编辑,可****直接修改exe等文件,支持打开大文件,可直接执行代码
b. ZendStudio
- 内置一个强大的****php代码调试工具,代码提示功能强大,支持6种以上语言。
c. RIPS(代码审计工具)
- 使用简单,可以****自动生成漏洞利用payload
- http://rips-scanner.sourceforge.net/
d. Burpsuite
e. 浏览器扩展
f. 编码转换及加解密
- seay代码审计系统****自带编码,burp的Decoder功能
g. 正则调试功能
- seay、灵者正则调试
3. 流程
- 获得源码
- 安装环境
- 查看网站结构
- 了解该程序的大致目录
- 查找程序入口
- 了解程序的业务逻辑
- 寻找配置文件
- 类似于config.php的文件,保存数据库相关信息,查看****数据库编码方式(宽字节注入)以及变量引用方式(双引号执行)
- 过滤功能
- 通过****公共函数文件和安全过滤等文件,了解过滤位置、绕过方式、过滤方式(GPC、正则、替换、addslasher)
4. 方法
- 通读源码
- 应用文件结构 => 关键文件代码 => 配置文件 => 首页文件 => 入口文件 => 功能审计
- 定向功能分析法
- 分析程序有哪些功能,****根据功能进行漏洞检测与测试
- 敏感函数参数回溯
5. 配置项和危险函数
(1). 配置项
- php.ini配置项规定了各种环境的条件
模式 | 设定范围 |
---|---|
PHP_INI_USER | 用户脚本(例如ini_set())、注册表(5.3起)、.user.ini |
PHP_INI_PERDIR | php.ini、.htaccess、httpd.conf |
PHP_INI_SYSTEM | php.ini、httpd.conf |
PHP_INI_ALL | 可在任何地方设定 |
(2). 常见配置
a. register_global
- 作用
- **设定全局变量的自动注册,**默认关闭
- 版本特性
- 自5.3.0废弃,5.4.0移除,5.2.0中默认开启
- 配置影响
- 变量覆盖漏洞,既可以成为下文绕过身份认证的方法,也可以突破其他已保护的变量产生新漏洞,如sql注入
- 不安全实例
<?php $username=$_GET['username']; $password=$_GET['password']; if(($username==='admin')&&($password==='123456')){ $authorized=true;//可以通过[URL]?authorized=1,直接传入authorized变量的值进行覆盖从而任意用户登录 } ?>
b. safe_mode
- 相似配置还有:safe_mode_exec_dir、disable_classes=、disable_functions=fopen、unlink
- 作用
- **禁用了php的一些危险的内置函数,如system、exec等,**默认关闭
- 版本特性
- 自5.3.0废弃,5.4.0移除
- 配置影响
- 在找到****可执行命令时,可以先检测环境的配置
- 不安全实例
<?php $commend=$_GET['commend']; system("{$commend}"); ?>
c. display_error
- 作用
- **将显示php产生的错误,**默认开启
- 版本特性
- 在php中默认开启,但是真实的站点发布后一般是关闭的
- 配置影响| 报错设置项 | 含义 |
| --------------------------------- | ---------------------------------------------------- |
| error_reporting=E_ALL | 将错误级别显示为最高 |
| error_log= [path] | 自定义错误日志的位置,必须对web用户可写入 |
| log_errors=on | 将错误日志输出到文件,而不是直接输出到前端 | - 不安全实例
站点关闭后未关闭display_error,呢么就会暴露服务器的目录信息,增加sql注入的风险
6. 危险函数
7. 类型
(1). 安装漏洞审计
a. 概述
- 一般php程序都有一个初始安装的功能,可能有以下漏洞
- 无验证功能,任意重装覆盖
- $_GET['step']跳过限制步骤
- 变量覆盖导致重装
- 判断lock后跳转无exit
- 解析install.php.bak漏洞
- 其他特定功能绕过漏洞
b. 审计思路
- 定向功能分析法,直接从安装问题找漏洞
- 判断Lock后面有没有exit(),如果没有,看代码重装部分有什么漏洞
(2). 命令注入漏洞
a. 分类
- 可以直接传入命令执行并返回结果
- system()、exec()、shell_exec()、passthru()、反引号
- 可以传入命令执行,但无结果返回
- popen()、proc_open()
- 需要开启pcntl扩展
- pcntl_exec()
b. 函数作用
c. 多命令执行语法
①windows
命令格式 | 含义 |
---|---|
command1**&**command2 | 先后执行,无论command1是否成功 |
command1**&&**command2 | 先后执行,command1成功,才执行command2 |
command1** | |
command1** | **command2 |
②Linux
命令格式 | 含义 |
---|---|
command1**;**command2 | 先后执行,无论command1是否成功 |
command1**&&**command2 | 先后执行,command1成功,才执行command2 |
command1**&**command2 | 先执行command1并放置后台,在执行command2 |
command1** | |
command1** | **command2 |
d. 审计思路
- **搜索目标函数 => 分析过滤 => 构造恶意字符串 => 执行 => 根据返回值判断 **
(3). XSS漏洞审计
a. 相关函数
- echo、printf、print、print_r、sprintf、die、var_dump、var_export等
b. 审计思路
①反射型、存储型
- 需要跟踪****输入输出位置是否有过滤
- 搜索输出函数 => 寻找是否有js代码 => 是否过滤,绕过 => 重复
1. 反射型: <?php $content = $_GET['content']; //没有做任何过滤 echo $content; //输出函数 ?> 2. 存储型: <?php $xss=$_POST['xss'];//没有做任何过滤 if($xss!==null){ $sql="insert into temp(id,payload) value('1','$xss')"; $result=mysql_query($sql); echo $result;//输出函数 } ?>
② DOM型
- 要对js做审计,查看是否是直接输出的js代码
c. 漏洞修复
①简单修复
- **使用****htmlspecialchars()**函数,将内容转化为HTMl实体
-
$sql = "INSERT INTO 'test'('name') VALUES('".htmlspecialchars($name)"')"; $result=mysql_query($sql); echo $result;
②严格限制输入
- 以输入ip地址为例
if(is_numeric($octet[0]))&&(is_numeric($octet[1]))&&(is_numeric($octet[2]))&&(is_numeric($octet[3]))&&(sizeor($octet)== 4)){ $target=$octet[0].'.'.$octet[1].'.'.$octet[2].'.'.$octet[3]; }
(4). SQL注入漏洞
a. 相关类型
- 数字型注入、字符型注入、宽字节注入、编码注入、二次注入等
b. 审计思路
- 是否存在****过滤函数 => addslashes(字符型无法注入) => set **character_set_client=gbk**(宽字节)
①普通注入
观察sql语句的拼接,是否****对用户的输入进行处理
寻找数据库关键字
select from
、mysql_connect
等
- 搜索$query => 查看输入函数是否有过滤 => 查找数据库关键词 => 重复
$id = $_REQUEST['id']; $query = "SELECT * FROM users WHERE id = $id"; echo $query;
(5). 文件包含漏洞
a. 产生原因
- 服务器对要包含的来源文件没有进行审查,导致攻击者进行了任意文件的读取等危害
b. 原理
- 服务器开启了allow_url_include选项
- 利用php的某些特性函数,利用URL动态包含文件
c. 相关函数
- include、include_once、require、require_once
d. 审计思路
- 跟踪程序运行流程,查看模块加载时包含的文件****是否可控
- 直接****搜索相关函数,回溯查看变量是否可控
e. 漏洞修复
- **尽量不要使用动态变量调用文件,**直接写要包含的文件
- 进行****白名单匹配,但大型web维护起来很复杂
(6). 二次注入漏洞
a. 原理
- 利用Mysql数据库出库值****反转义功能,多次与数据库交互造成的注入问题
b. 相关函数
- 在数据库****第一次进入数据库时进行了转义后再存储,后续使用时未再次过滤或转义而直接使用
- 开发者对语言中的****函数理解不充分导致,例如is_numeric
c. 审计思路
- 有数据****insert/update到数据库
- 从数据库****select数据,没有再次转义,再将数据拼接到新的语句中
d. 防御和修复
- 正则过滤输入
if(!preg_match("/^[a-zA-Z0-9]+$/",$clean_name))
- 出库时数据过滤
(7). 任意文件读取
a. 原理
- 都具有****读取文件的函数
- 读取文件的****路径用户可控,且没有校验或者校验不严格
- 都会****输出文件内容
b. 相关函数
- file_get_contents()、fgetss()、fgets()、file()、fopen()、fread()、parse_ini_file()、readfile()、show_source()、highlight_file()
<?php $filename=$_GET['file']; echo file_get_contents($filename); ?>
c. 审计思路
- 先查看****功能点对应的文件,再去进行代码审计,分析原理
- 搜索文件读取的相关函数,用****变量溯源的方法,查看是否可以直接或间接控制变量
d. 防御与修复
- 尽量将****url写死
- 正则判断用户输入的参数格式,匹配输入的格式是否合格
- **少使用敏感函数,**控制敏感函数传参
- 对****变量进行过滤,将单引号或者其他敏感字符转化为斜杠
(8). 任意文件操作
a. 原理
- 文件操作相关****关键参数用户可控,导致的恶意操作
b. 分类
①文件/目录删除** **
-
相关函数
- unlink(路径):删除文件
- rmdir(路径):删除目录
-
相关手法
- 删除lock****文件锁,导致重复安装漏洞
- 删除网站****关键文件,导致数据丢失或网站拒绝服务
②文件写入/上传
- 相关函数
- file_put_contents(dir,content):直接将字符串写入文件
- $fp=fopen(dir,"w"):以写入模式打开一个文件
- fwrite($fp,content):向文件写入数据
- fclose($fp):关闭文件
- move_uploaded_file(tmp_dir,des_dir):移动临时上传的文件
③文件解压
-
审计思路
- ZipArchive扩展在windows平台php>5.6默认安装
- 查看是否有文件解压类,例如
$zip = new \ZipArchive
- 查看是否有相关操作函数,例如
$zip->open()
、$zip->addFile()
、$zip->addEmptyDir()
、$zip->addFromString()
、$zip->extractTo()
、$zip->close()
- **判断解压目录 **
- 是否在web目录下
- 是否检查压缩包内的文件类型
- 是否不在web目录下也可以使用
c. 常见函数及用法
(9). 越权漏洞
a. 常出现地方
- 根据订单号查订单
- 根据用户ID查看账户信息
- 修改/找回密码
b. 思维导图
c. 审计思路
- 先查看****前端的页面源码,查看一些操作的表单提交的值
- 查看****配置文件和一些过滤器,是否对URL有相关的筛选操作
- 最后查看****后台处理逻辑,是否存在身份验证机制,逻辑是否异常
- 查看服务器端是否进行****身份校验
d. 修复和防御
- 查看用户信息操作需要****额外的身份验证信息
- 从****加密的Cookie中获取当前用户id
- 在每个页面****加载前进行权限认证
- 进行敏感操作时****再次验证身份信息
(10). 暴力破解
a. 原理
- 穷举法
b. 审计思路
- 分别审计登录页面、验证码页面、二维码页面,判断二维码是否可以绕过
c. 防御与修复
- **每次进行身份校验时,**调用二维码的文件,从而刷新验证码
- 添加一个****判断session不为null的条件
- 前端验证码****加密,或使用高级验证码
- 后台对用户输入密码****次数进行限制,或封禁失败次数过多的IP
- 禁止用户使用弱口令密码