PHP核心配置文件:
1.register_globals=Off(全局变量注册开关)
2.allow_url_include=Off(是否允许包含远程文件)与此类似的还有allow_url_fopen
3.magic_quotes_gpc=On(魔术引号自动过滤)会自动在单引号、双引号、反斜杠、空字节(NULL)的前面加上反斜,但是在PHP5中不会过滤$SERVER变量所以可以利用client-ip、referer等漏洞
4.magic_quotes_runtime(魔术引号自动过滤)和上面一样,只是它只对从数据库或者文件中获取的数据进行过滤
5.magic_quotes_sybase(魔术引号自动过滤)只是将单引号转为双引号,转义空字节
6.safe_mode=on(安全模式)PHP5.4之后取消
7.open_basedir(PHP可访问目录)多个用;
隔开
8.disable_functions(禁用函数)例如可以=phpinfo、eval、passthru、exec、system
9.display_errors和error_reporting=Off(错误显示)
常见的代码审计思路
1.根据敏感关键字回溯参数传递过程
2.查找可控变量,正向追踪变量传递过程
3.寻找敏感功能点,通读功能点代码
4.直接通读全文代码
文件上传时可以测试文件名是否存在SQL注入.
二次注入原理图,实例请看sqli-labs-24
SQL请求头注入:user-agent/referer/client-ip/x-forward-for
对宽字节注入的挖掘主要看如下关键字:
SET NAMES
character_set_client=gbk
mysql_set_charset('gbk')
二次urldecode注入:1.php?id=1%2527
intval等字符转换intval("1' union select ")
输出:1
关于宽字节注入的推荐解决方法:
1.在执行查询前先执行SET NAMES 'gbk'设置编码,设置character_set_client=binary
2.使用mysql_set_charset('gbk')设置编码,然后使用mysql_real_escasp_string()函数过滤参数
3.使用pdo方式,在PHP5.3.6及以下版本需要设置setAttribute来禁用prepared statements的防真效果
对于CSRF的防御:
1.增加token/referer验证避免img标签请求的攻击
2.增加验证码
Token实现测试代码:
<?php
session_start();
function set_token() {
$_SESSION['token'] = md5(time()+rand(1,1000));
echo $_SESSION['token'];
echo '</br>';
}
function check_token() {
if(isset($_POST['token'])&&$_POST['token'] === $_SESSION['token'])
return true;
else
return false;
}
if(isset($_SESSION['token'])&&check_token()) {
echo "success";
echo '</br>';
}
else {
echo "failed";
echo '</br>';
}
set_token();
?>
<form method="post">
<input type="hidden" name="token" value="<?=$_SESSION['token']?>">
<input type="submit"/>
</form>
文件包含函数的区别:
include()、include_once()在文件包含时即使遇到错误,下面的代码依然会继续执行
require()、require_once()则会直接报错退出程序
windows下可以包含日志文件
linux下可以包含/proc/self/environ(链接当前正在运行环境的进程)、/etc/passwd(密码文件) 等文件
php://filter/
PHP输入输出流读取文件
文件上传函数move_uploaded_file()
在上传文件时,在文件名后面加个空格(%20,或者%81-%99),有时候可以绕过黑名单限制。
文件上传防御:
1.白名单方式过滤文件扩展名,使用in_array或者===来对比扩展名
2.保存文件时重命名文件,文件命名规则采用时间戳的拼接随机数的MD5方式"md5(time()+rand(1,1000))".
代码执行漏洞函数:
eval(),assert(),preg_replace(),call_user_func(),call_user_func_array(),array_map()
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject )
搜索subject中匹配pattern,用replacement替换。如果pattern处存在/e参数,则replacement的值会被当成PHP代码来执行。
命令执行漏洞函数:
system(),exec(),shell_exec(),passyhru(),pcntl_exec(),popen(),proc_open(),`
命令执行防注入函数:
escapeshellcmd(),过滤整条命令(加^)
<?php
echo (escapeshellcmd($_GET['cmd']));
?>
?cmd=whoami()
输出:whoami^()
escapesshellarg(),保证传入命令的参数是以字符串的形式存在
<?php
echo 'ls '.escapeshellarg('cmd"');
?>
输出:ls "cmd "
is_numeric()函数使用十六进制绕过
==在判断之前先做变量类型转换,即只判断值
===不会转换,即既判断值还判断类型
%00=NULL=0
http头注入常见的:user-agent,referer,client-ip/x-forward-for
$_SERVER和$_FILES变量不受GPC保护
显示错误信息的函数开关:display_errors和error_reporting
PHP是基于C开发,%00
在URL编码后市\0
,\0
在C语言中是字符串的结束符。
iconv函数字符编码转换过程中遇到不能处理的字符串则后续的字符串也不会处理,导致截断(char(128)到char(255)之间都可以)
php://输入输出流
php://input
可以访问请求的原始数据的只读流,即可以直接读取到POST上没有经过解析的原始数据。
php://output
是一个只写流,将流数据输出
php://filter
是一个文件操作协议,可以对磁盘中的文件进行读写操作
php://filter/write=string.rot13/resource=example.txt,"hello world"
php://filter/convert.base64-encode/resource=index.php
PHP代码解析标签
脚本标签: <script language="php">...</script>
短标签:<?...?>
,需要php.ini中short_open_tag=on,默认是on
asp标签:<%...%>
,需要php.ini中asp_tags=on,默认是off
client-ip的正则规则:^\d+\.\d+\.\d+\.\d+$
test.php%00jpg
mysql报错注入的函数:floor(),updatexml(),extractvalue()
具体介绍请参考:MySql注入总结
windows findfirstfile利用:即使用<
,>
来代替不可知的文件名部分,如123.txt可以使用1<<来替换。
PHP中单引号代表纯字符串,双引号则是会解析中间的变量:
<?php $a="${@phpinfo()}";?> #第一个字符为@
<?php $a="${ phpinfo()}";?> #第一个字符为空格
<?php $a="${ phpinfo()}";?> #第一个字符为TAB
<?php $a="${/**/phpinfo()}";?> #第一个字符为注释符
<?php $a="${
phpinfo()}";?> #第一个字符为回车换行
<?php $a="${+phpinfo()}";?> #第一个字符为+
<?php $a="${-phpinfo()}";?> #第一个字符为-
<?php $a="${!phpinfo()}";?> #第一个字符为!
此外还有~,\等
对称加密算法:DES,3DES,TDEA,RC2,RC4,IDEA,AES
非对称加密:RSA
单向加密:MD4,MD5,sha1
验证码绕过:
1.不刷新直接绕过
2.暴力破解
3.机器识别
4.打码平台
用户登录漏洞:
1.撞库漏洞
用户名密码错误次数都无限制
单时间段内用户的密码错误次数限制
单时间段内IP登陆错误次数限制
2.API登陆
最后附上一个搜集的PHP代码审计脑图