php代码审计参考

代码审计思路:

从个人角度出发,如果环境允许的话,可以先选择做一个"程序员"再来做代码审计。因为从开发者的位置去思考问题,可以快速定位问题。学习面向对象编程以及面向过程编程,编写一些 项目提升对代码的理解能力,再是对各种漏洞可以独立挖掘利用并能理解漏洞的危害,这里我们主要针 对PHP源码做审计。

接下来我们从三个层次开始我们的源码审计思路:

  • .确定要审计的源码是什么语言
  • 确定该源码是单入口还是多入口
  • 确定该语言的各种漏洞诞生的函数

PHP核心配置

一个漏洞在不同环境造成的结果也是不一样的。

由于关于php.ini配置的内容过于多,这里推荐浏览官方文档 https://www.php.net/manual/zh/ini.ph p,我们在这里主要列下php.ini 主要使用的安全配置。

代码审计环境

PHP源码部署环境:Phpstudy 2018等

集成开发环境:Zend Studio/Phpstorm

数据库管理工具:Navicat for MySQL 12

MySQL实时监控工具:MySQLMonitor

文本编辑工具:Sublime_Text3

代码审计辅助工具:Seay源代码审计系统、Search and Replace、Rips 0.55

代码审计辅助安全工具:渗透版火狐、BurpSuite、Sqlmap

手动调试代码

复制代码
echo
exit();
print_r
var_dump();
debug_zval_dump();
debug_print_backtrace();
echo "<script>alert($estr);</script>"";
die("<script>alert($estr);</script>");

PHP的弱类型

1.比较符号 == 与 === == 在进行比较的时候,会先将字符串类型转化成相同,如果整型跟字符型比较字符或从左往右提取 整型直到遇到字符结束,再比较。 === 在进行比较的时候,会先判断两种字符串的类型是否相等,当等号两边类型不同时,会先转换 为相同的类型,再对转换后的值进行比较,如果比较一个数字和字符串或者涉及到数字内容的字符 串,则字符串会被转换成数值并且比较按照常数值进行比较.。

复制代码
//字符串和数字比较
var_dump(0=="admin"); //true
echo '<br>';
var_dump(1=="1admin"); //true
echo '<br>';
var_dump(1=="admin1"); //false
echo '<br>';
var_dump(0=="admin1"); //true
echo '<br>';
//数字和数组
$arr = array();
var_dump(0==$arr); //false
echo '<br>';
//字符串和数组
$arr = array();
var_dump("0"==$arr); //false
echo '<br>';
//"合法数字+e+合法数字"类型的字符串
var_dump("0e123456"=="0e4456789"); //true
echo '<br>';
var_dump("1e1"=="10"); //true

2.array_search 与 is_array

is_array:判断传入的是不是一个数组。 array_search(x,$数组):在数组中寻找与指定值(x)相等的值,array_search函数 类似于"==", 会进行类型的转换。

复制代码
if(!is_array($_GET['test'])){
exit();
}
$test = $_GET['test'];
for($i = 0;$i<count($test) ;$i++ ){
if($test[$i] === "admin"){
echo "error";
exit();
}
$test[$i] = intval($test[$i]);
}
if(array_search("admin",$test) === 0){
echo "flag";
}else{
echo "false";
}

我们可以传入test[]=0来进行绕过,首先test是一个数组,符合is_array的判断,然后test=0;在 array_search中0==admin为true,绕过了array_search。

3.in_array()函数

array_search()与in_array()也是一样的问题。

复制代码
$array=[0,1,2,'3'];
var_dump(in_array('abc', $array)); //true
var_dump(in_array('1bc', $array)); //true

4.is_number()函数

检测变量是否为数字或数字字符串,如果var是数字和数字字符串则返回TRUE,否则返回FALSE

复制代码
$temp = $_GET['password'];
is_numeric($temp) ? die("no numeric") : NULL;
if($temp>9999){
echo '我giao';
}

在这里我们的payload需要的是一个大于9999的数字后面加上字符就可以了 这里构造的是10000+ 。

5.strcmp()函数

比较函数如果两者相等返回0,string1>string2返回>0 反之小于0。在5.3及以后的php版本中,当 strcmp()括号内是一个数组与字符串比较时,也会返回0。

函数接受到了不符合的类型,发生了错误,但是还是判断其相等。

6.switch()语句

如果switch是数字类型的case的判断时,switch会将参数转换为int类型

复制代码
$pwd = "1ad";
switch($pwd){
case 1:
echo "giao";
break;
case 2:
echo "?";
break;
}

7.md5()函数

0e开头的全部相等(绕过==判断),两个字符串转换成MD5值时都是0e开头,0e 纯数字这种格式 的字符串在判断相等的时候会被认为是科学计数法的数字,先做字符串到数字的转换。 md5()中的需要是一个string类型的参数。但是当你传递一个array时,md5()`不会报错,只是会无 法正确地求出array的md5值,返回false,这样就会导致任意2个array的md5值都会相等。

复制代码
var_dump(md5('240610708') == md5('QNKCDZO'));//true
$array1=[1,2,3];
$array2=[4,5,6];
var_dump(md5($array1)===md5($array2)) //true

8.sha1()函数

sha1函数和md5函数一样不能判断数组的值。

复制代码
$array1=[1,2,3];
$array2=[4,5,6];
var_dump(sha1($array1)===sha1($array2)); //true

9.empty与isset

变量为:0,"0",null,'',false,array()时,使用empty函数,返回的都是true

变量未定义或者为null时,isset函数返回的为false,其他都为true

复制代码
$a = null;
$b = 0;
$c = "";
var_dump(empty($a));
var_dump(empty($b));
var_dump(empty($c));
var_dump(isset($a));
var_dump(isset($b));
var_dump(isset($c));

学习漏洞函数

1.全局变量/超全局变量

全局变量:

定义在函数外部的就是全局变量,它的作用域从定义处一直到文件结尾。

函数内定义的变量就是局部变量,它的作用域为函数定义范围内。

函数之间存在作用域互不影响。

函数内访问全局变量需要 global关键字或者使用 $GLOBALS[index]数组。

超全局变量:

超全局变量 在 PHP 4.1.0 中引入,是在全部作用域中始终可用的内置变量。

PHP 中的许多预定义变量都是"超全局的",这意味着它们在一个脚本的全部作用域中都可用。在函 数或方法中无需执行 global $variable; 就可以访问它们。

常用的超全局变量有9个:

$GLOBALS

$_SERVER

$_REQUEST

$_POST

$_GET

$_FILES

$_ENV

$_COOKIE

$_SESSION

2.SQL注入

select update insert into delete

注:此处非函数,主要找常用的SQL语句

3.代码执行

复制代码
eval()
usort()
uasort()
assert()
array_map()
preg_replace()
array_filter()
call_user_func()
create_function()
call_user_func_array()
文件操作函数:
fputs(fopen('shell.php','w'),'<?php eval($_POST[cmd])?>');
动态函数:$_GET['a']($_GET['b'])
  1. 命令执行

system() exec() passthru() shell_exec()

  1. XSS跨站脚本攻击

print print_r echo printf die var_dump var_export

6.文件上传漏洞

move_uploaded_file()

7.文件包含漏洞

include() include_once() require() require_once()

伪协议

file:// --- 访问本地文件系统

http:// --- 访问 HTTP(s) 网址

ftp:// --- 访问 FTP(s) URLs

php:// --- 访问各个输入/输出流(I/O streams)

zlib:// --- 压缩流 data:// --- 数据(RFC 2397)

glob:// --- 查找匹配的文件路径模式

phar:// --- PHP 归档 ssh2:// --- Secure Shell 2

rar:// --- RAR ogg:// --- 音频流 expect:// --- 处理交互式的流

8.任意文件下载

fopen() readfile() file_get_contents()

9.任意文件删除

unlink()

10.任意文件读取

file() fgets() fgetss() fopen() readfile() fpassthru() parse_ini_file() file_get_contents()

11.变量覆盖

extract() parse_str() import_request_variables()//此函数只能用于PHP4.1 \~ PHP5.4 12.反序列化漏洞 unserialize() 魔术方法 * __construct()//每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作 * __destruct()//某个对象的所有引用都被删除或者当对象被显式销毁时执行 * __call() //在对象上下文中调用不可访问的方法时触发 * __callStatic() //在静态上下文中调用不可访问的方法时触发 * __get() //用于从不可访问的属性读取数据 * __set() //用于将数据写入不可访问的属性 * __isset() //在不可访问的属性上调用isset()或empty()触发 * __unset() //在不可访问的属性上使用unset()时触发 * __sellp() //使用serialize时触发 * __wakeup() //使用unserialize时触发 * __toString() //把类当作字符串使用时触发 * __invoke() //当脚本尝试将对象调用为函数时触发 * __set_state()//当调用 var_export() 导出类时,此静态方法会被自动调用。 * __clone()//当使用 clone 复制一个对象时自动调用 * __debuginfo()//使用 var_dump() 打印对象信息时自动调用 审计入门总结 先从Web漏洞原理开始理解再到漏洞的挖掘以及利用,我们就来到了PHP代码审计这个方向进行进修。 这里我们开始学习PHP开发,以及熟悉下开发者的开发思想,站在开发者角度去思索代码。再是掌握漏 洞对应发生函数使用,再是学习正则表达式。 审计路线:Demo-\>综合漏洞靶场-\>网上审计过的CMS-\>多入口CMS-\>单入口CMS-\>框架-\>函数缺陷

相关推荐
ServBay8 小时前
告别面条代码,PSL 5.0 重构 PHP 性能与安全天花板
后端·php
JaguarJack3 天前
FrankenPHP 原生支持 Windows 了
后端·php·服务端
BingoGo3 天前
FrankenPHP 原生支持 Windows 了
后端·php
JaguarJack4 天前
PHP 的异步编程 该怎么选择
后端·php·服务端
BingoGo4 天前
PHP 的异步编程 该怎么选择
后端·php
JaguarJack4 天前
为什么 PHP 闭包要加 static?
后端·php·服务端
ServBay5 天前
垃圾堆里编码?真的不要怪 PHP 不行
后端·php
用户962377954485 天前
CTF 伪协议
php
BingoGo8 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack8 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端