代码审计_php
常用函数
函数名 | 返回值 |
---|---|
echo() | 输出一个字符串或变量,但是不能输出数组。 |
print_r() | 输出一个数组。 |
var_dump() | 输出一个变量的结构,这个变量包含普通变量,数组,对象等 |
$GLOBALS 变量 | 此函数返回所有的全局变量。 |
get_defined_vars(void) | 此函数返回一个包含当前可用的变量列表的多维数组,这些变量包括环境变量、服务器变量和用户定义的变量。 |
get_defined_functions(void) | 获取所有已经定义的函数,包含内部函数和用户定义的函数。 |
get_defined_constants(void) | 返回所有可用的常量,包含系统常量和用户定义的常量。 |
get_declared_classes(void) | 返回所有可用的类,包含系统类和用户定义的类。 |
get_included_files() | 返回所有的包含的文件路径的数组, |
addslashes
addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。
预定义字符是:
- 单引号(')
- 双引号(")
- 反斜杠(\)
- NULL
parse_str
本身会对 url 编码进行一次 decode
文件包含
文件包含相关函数
include() require() include_once() require_once() file_get_contents() fwrite() fread()
Include:包含并运行指定文件,当包含外部文件发生错误时,系统给出警告,但整个 php 文件继续执行。
Require:跟 include 唯一不同的是,当产生错误时候,include下面继续运行而 require 停止运行了
ps:
allow_url_fopen 和 allow_url_include 是决定包含属于本地文件包含(LFI)还是远程文件包含 (RFI)的条件,在 PHP4 中则只有 一个 allow_url_fopen 选择。其中 allow_url_fopen 和 allow_url_include 为 0n 的情况为远程文件包含漏洞,相反为本地文件包含漏洞。
文件包含相关文件
.htaccess
/var/lib/locate.db var/lib/mlocate/mlocate.db (linux 中这两个文件储存着所有文件的路径,需要 root)
/var/log/apache/error.log /usr/local/apache2/conf/httpd.conf(更多→http://wiki.apache.org/httpd/DistrosDefaultLayout)
/root/.ssh/authorized_keys
/root/.ssh/id_rsa
/root/.ssh/id_rsa.keystore
/root/.ssh/id_rsa.pub
/root/.ssh/known_hosts
/etc/shadow
/root/.bash_history
/root/.mysql_history
/proc/self/fd/fd[0-9]* (文件标识符)
/proc/mounts
/proc/config.gz
超全局变量$_SERVER
元素/代码 | 描述 |
---|---|
$_SERVER['PHP_SELF'] | 返回当前执行脚本的文件名。 |
$_SERVER['GATEWAY_INTERFACE'] | 返回服务器使用的 CGI 规范的版本。 |
$_SERVER['SERVER_ADDR'] | 返回当前运行脚本所在的服务器的 IP 地址。 |
$_SERVER['SERVER_NAME'] | 返回当前运行脚本所在的服务器的主机名 |
$_SERVER['SERVER_SOFTWARE'] | 返回服务器标识字符串(比如 Apache/2.2.24)。 |
$_SERVER['SERVER_PROTOCOL'] | 返回请求页面时通信协议的名称和版本(例如,“HTTP/1.0”)。 |
$_SERVER['REQUEST_METHOD'] | 返回访问页面使用的请求方法(例如 POST)。 |
$_SERVER['REQUEST_TIME'] | 返回请求开始时的时间戳(例如 1577687494)。 |
$_SERVER['HTTPS'] | 是否通过安全 HTTP 协议查询脚本。 |
$_SERVER['REMOTE_ADDR'] | 返回来自当前请求的请求头。 |
$_SERVER['REMOTE_PORT'] | 返回用户机器上连接到 Web 服务器所使用的端口号。 |
$_SERVER['SCRIPT_FILENAME'] | 返回当前执行脚本的绝对路径。 |
$_SERVER['SERVER_ADMIN'] | 指明了 Apache 服务器配置文件中的 SERVER_ADMIN 参数。 |
$_SERVER['SERVER_PORT'] | Web 服务器使用的端口。默认值为 “80”。 |
$_SERVER['SERVER_SIGNATURE'] | 返回服务器版本和虚拟主机名。 |
$_SERVER['PATH_TRANSLATED'] | 当前脚本所在文件系统(非文档根目录)的基本路径。 |
$_SERVER['SCRIPT_NAME'] | 返回当前脚本的路径。 |
$_SERVER['SCRIPT_URI'] | 返回当前页面的 URI。 |
应用层面
变量接收不安全的输入之后,没有做恰当的过滤又用在不同的地方,就可能造成不同的危害。如果直接进入数据库然后显示给用户就会导致跨站脚本攻击,如果用在 sql 语句中就可能导致 Sql 注射攻击, 这几种攻击都是是与具体的脚本语言无关的,在各种脚本语言里都可能存在。由于 php 的变量很灵活,这些有害的变量如果用在一些逻辑语句中,就会导致关键代码的跳过如身份验证失败和跳过一些变量的初始化从而导致程序逻辑混乱而产生其他漏洞。如果这个变量用在了危险的函数如 include 等等当中,当然就会出现文件包含漏洞,出现 在 fopen 函数里就会可能产生写文件的漏洞,出现在 mysql_query 函数中就是 Sql 注射漏洞,eval 以及 preg_replace 中可能导致代码的执行,出现在 htmlspecia 函数中可能导致出错而绝对路径泄露...... 变量出现的环境决定了它可能的危害。
总结为:
可以控制的变量【一切输入都是有害的 】
变量到达有利用价值的函数[危险函数] 【一切进入函数的变量是有害的】
审计流程
先用工具扫敏感函数再一个一个回溯
拿到源码之后,先从它开始的地方(一般是根目录下的 index 文件)按照执行的顺序去读代码,一直到它的初始化内容, 和基本功能实现完毕为止。这样,可以明确的了解整套源码的结构,哪一种函数文件放在哪个文件夹下;知道通用函数放在哪个文件中。这对我们在之后阅读“疑 似”有问题的代码时,有很好的帮助
ps:
留意url变化
对象名、事件名
曾经的漏洞和修复方案
曾经出现过的漏洞:
代码逻辑:
- header() 函数并不会结束之后的代码,相当于没有break,因此可重放修改【安装过程】中参数,重置管理员账号密码
- window.location.href 重定向后没有break
sqli
文件上传
文件包含
后门、RCE
逻辑漏洞
身份认证,鉴权