对于php代码审计我也是从0开始学的,对学习过程进行整理输出沉淀如有不足欢迎提出共勉。对学习能力有较高要求,整个系列主要是在工作中快速精通php代码审计,整个学习周期5天 ,建议花一天时间熟悉php语法。
?
我是直接phpstudy2019一键搭建小白首选
所谓工欲善其事必先利其器,找一款适合自己的php开发工具自行百度搭建,我用的是phpstrom .
?
初级篇主要讲
1. php历史版本漏洞。
2. 变量配置缺陷。
3. 函数缺陷。
4. 弱语言缺陷。
?
PHP配置漏洞
?
我们要熟知php各版本漏洞
Register_globals? 全局变量注册开关
在该选项为on情况下,会直接把用户GET,POST等方式提交的参数注册成全局变量并初始化值为参数对应的值
Php小于4.2.3默认打开 5.3废弃 5.4移除
?
Allow_url_include? 是否允许包含远程文件
Php 5.2 后默认设置off
?
Magic_quotes_gpc 魔术引号自动过滤
会自动在get post,cookie 变量对单引号,双引号,反斜杠,空字符的前面加反斜杠
缺陷不会过滤$_SERVER 变量?
Php5.3后废弃,5.4移除 小于4.2.3 默认打开
?
Magic_quotes_runtime? 魔术引号自动过滤
和上面一样 却是对从数据库取出的数据进行转义? 防止二次注入 同样在5.4取消
?
?
Safe_mode? 安全模式
在开启时做命令执行操作会提示执行命令失败,和一些敏感操作. 可以查看配置是否开启。
?
Open_basedir? 可访问目录
默认web目录,查看配置是否出现全目录可访问情况
?
Disable_functions 禁用函数
禁用敏感函数如exec? 可以通过dl()函数来绕过自定义php扩展方法实现命令执行,这个函数并不安全。
?
Display_errors? 错误显示
生产环境关闭错误回显 display_errors=off
?
PHP漏洞函数
?变量覆盖
? ? ? extract()
该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。条件:若有EXTR_SKIP则不行。
<?php $a = "Original";$my_array = array("a" => "Cat", "b" => "Dog", "c" => "Horse");extract($my_array);echo "$a = $a; $b = $b; $c = $c";?>
#结果:$a = Cat; $b = Dog; $c = Horse
? ? ? parse_str()
解析字符串并注册成变量
$b=1;Parse_str('b=2');Print_r($b);#结果: $b=2
? ? ? import_request_variables()
将 GET/POST/Cookie 变量导入到全局作用域中,全局变量注册。在5.4之后被取消,只可在4-4.1.0和5-5.4.0可用。
//导入POST提交的变量值,前缀为post_
import_request_variable("p", "post_");//导入GET和POST提交的变量值,前缀为gp_,GET优先于POST
import_request_variable("gp", "gp_");//导入Cookie和GET的变量值,Cookie变量值优先于GET
import_request_variable("cg", "cg_");
? ? $$变量覆盖
## 提交参数chs,则可覆盖变量"$chs"的值。$key为chs时,$$key就变成$chs
$chs = '';if($_POST && $charset != 'utf-8'){$chs = new Chinese('UTF-8', $charset);foreach($_POST as $key => $value){
$$key = $chs->Convert($value);
}unset($chs);
}
绕过过滤的空白字符
" "%00"(ASCII 0 (0x00)),空字节符。
制表符""(ASCII 9 (0x09)),水平制表符。
空白字符:"
"(ASCII 10 (0x0A)),换行符。"v" "x0b"(ASCII 11 (0x0B)),垂直制表符。"f" "%0c"换页符"" "%0d"(ASCII 13 (0x0D)),回车符。
空格:" " "%20" (ASCII 32 (0x20)),普通空格符。
Trim 函数过滤
缺少了f(%0c)
从而绕过%0c过滤
截断
? ?
? ???Iconv 异常字符截断问题
## 因iconv遇到异常字符就不转后面的内容了,所以可以截断。## 这里chr(128)到chr(255)都可以截断。
$a='1'.char(130).'2';echo iconv("UTF-8","gbk",$a); //将字符串的编码从UTF-8转到gbk
echo iconv('GB2312', 'UTF-8', $str); //将字符串的编码从GB2312转到UTF-8
? eregi、ereg可用%00截断
功能:正则匹配过滤 条件:要求php<5.3.4可以把非法的数据放在%00后面进行绕过我们可以看一个ctf题就是考察了这个知识
##?http://127.0.0.1/Php_Bug/05.php?password=1e9%00*-*
#GET方式提交password,然后用ereg()正则限制了password的形式,只能是一个或者多个数字、大小写字母,继续strlen()限制了长度小于8并且大小必须大于9999999,继续strpos()对password进行匹配,必须含有-,最终才输出flag
#因为ereg函数存在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则匹配。
#对于另一个难题可以使用科学计数法表示,计算器或电脑表达10的的幂是一般是e,也就是1.99714e13=19971400000000,所以构造 1e8 即 100000000 > 9999999,在加上-。于是乎构造password=1e8%00*-*,成功得到答案
{echo '
You password must be alphanumeric
';}else if (strlen($_GET['password']) < 8 && $_GET['password'] > 9999999)
{if (strpos ($_GET['password'], '*-*') !== FALSE)
{die('Flag: ' . $flag);
}else{echo('
*-* have not been found
');}
}else{echo '
Invalid password
';}
}
);
var_dump('0xABCdef' == ' 0xABCdef');