PHP密码加密存储
PHP密码加密存储
引言
用户密码绝不能明文入库,泄露即灾难。MD5、SHA1是哈希算法但速度快、可被彩虹表破解,不适合存密码。PHP 5.5以后内置password_hash和password_verify,用bcrypt自带盐值和成本因子,是现在注册登录系统的标准做法。
注册:生成哈希入库
$pwd = $_POST['password'];
$hash = password_hash($pwd, PASSWORD_DEFAULT);
// $2y$10$.... 直接把这串哈希存数据库
$db->insert('users', ['password' => $hash]);
PASSWORD_DEFAULT默认bcrypt,自动生成随机盐,算法和成本因子都记录在哈希串里,不需要单独存盐字段。
登录:校验密码
$row = $db->find('users', ['username' => $username]);
if ($row && password_verify($inputPwd, $row['password'])) {
// 密码正确,登录成功
} else {
// 用户名或密码错误
}
password_verify自动识别哈希里的算法和盐,比对用户输入的明文,返回布尔值。
指定成本因子
$hash = password_hash($pwd, PASSWORD_BCRYPT, ['cost' => 12]);
cost越高计算越慢、抗暴力破解越强,默认10。服务器性能允许可适当调高,太慢会影响登录接口响应。
判断哈希是否需要升级
if (password_needs_rehash($row['password'], PASSWORD_DEFAULT)) {
$newHash = password_hash($inputPwd, PASSWORD_DEFAULT);
$db->update('users', ['password' => $newHash], $row['id']);
}
算法或成本升级后,老用户登录时校验通过顺便重算哈希,平滑迁移不用强制改密。
错误做法对比
# 不要这样
md5($pwd); # 无盐,彩虹表秒破
sha1($pwd . $salt); # 自制盐方案,仍可GPU爆破
crypt($pwd); # 旧接口,参数难控
自己拼盐、用通用哈希函数存密码都是安全隐患,直接用内置密码函数。
注意事项
- 数据库密码字段长度留够60字符以上,bcrypt哈希约60位;
- 别自己实现加盐哈希,密码函数已封装随机盐和算法版本;
- 登录失败统一提示"用户名或密码错误",别区分哪个不存在;
- 密码强度前端后端双重校验,长度、复杂度、常见弱密码黑名单;
- 哈希不可逆,忘记密码只能重置,不能找回原密码;
- 配合HTTPS传输,密码在传输层也要加密保护。
总结
注册用password_hash生成bcrypt哈希入库,登录用password_verify校验,自带随机盐无需单独存盐。cost成本因子按服务器性能调整,password_needs_rehash在用户登录时平滑升级旧哈希。禁止用MD5、SHA1或自制盐方案存密码,密码字段预留60字符以上,登录失败提示统一,配合HTTPS和密码强度校验构成完整账号安全体系。
PHP文件上传校验
PHP文件上传校验
引言
文件上传是网站高频功能,也是最容易出安全问题的地方。只判断后缀名,黑客可以把木马改名为图片绕过,上传到服务器执行。上传必须做多层校验。
必须校验的内容
- 检查上传错误码,确认文件确实上传成功;
- 限制文件大小,防止超大文件占满磁盘;
- 白名单校验扩展名,只允许jpg/png等指定类型;
- 读取文件真实MIME类型,不能只信前端传的type;
- 重新生成随机文件名,避免原文件名覆盖或路径穿越;
- 上传目录禁止执行PHP脚本。
基础校验示例
<?php
$allow = ['jpg','png','gif'];
$ext = strtolower(pathinfo($_FILES['file']['name'],PATHINFO_EXTENSION));
if(!in_array($ext,$allow)){
exit('类型不允许');
}
if($_FILES['file']['size'] > 2*1024*1024){
exit('文件过大');
}
//获取真实类型
$info = getimagesize($_FILES['file']['tmp_name']);
if(!$info) exit('不是合法图片');
//随机重命名
$newName = uniqid().'.'.$ext;
move_uploaded_file($_FILES['file']['tmp_name'],'./upload/'.$newName);
服务端加固
- Nginx/Apache配置上传目录禁止解析php;
- 图片上传后重新压缩生成,破坏木马脚本;
- 关闭上传目录的执行权限;
- 定期扫描上传目录文件。
总结
文件上传安全核心:不信任前端、白名单、校验真实类型、随机改名、目录隔离。多层校验才能防止webshell上传,保护服务器安全。
Web XSS攻击分类
Web XSS攻击分类
引言
XSS跨站脚本是最常见的Web漏洞,黑客注入JS代码,在用户浏览器执行,盗取cookie、劫持页面。建站开发必须了解XSS三种类型,针对性做好防护。
XSS三大类型
- 存储型XSS:代码存入数据库,所有访问页面的用户都会触发,危害最大。例如评论区没有过滤,提交恶意js存入数据库。
- 反射型XSS:恶意代码放在URL参数,用户点击链接,页面直接输出参数触发,不会存入数据库。
- DOM型XSS:前端JS直接读取URL参数修改DOM,不经过后端服务,后端日志看不到攻击载荷。
基础防护方案
- 后端输出页面使用htmlspecialchars转义;
- 前端渲染数据不要直接innerHtml,优先textContent;
- 设置Cookie HttpOnly,防止JS读取cookie;
- 配置CSP内容安全策略。
简单示例漏洞代码
<?php
//危险代码,直接输出参数,存在反射XSS
echo $_GET['name'];
//安全写法
echo htmlspecialchars($_GET['name'],ENT_QUOTES);
?>
总结
XSS核心成因:把外部可控数据当成页面代码执行。存储型风险最高,DOM型容易被忽略。前后端配合做输出转义、CSP、HttpOnly Cookie,多层防护抵御XSS。
PHP请求参数过滤
PHP请求参数过滤
引言
Web接口接收GET、POST参数,如果不做过滤校验,容易出现SQL注入、XSS、业务逻辑漏洞。PHP开发接口时,参数过滤是安全第一道防线,所有外部输入都不可信。
基础过滤思路
- 类型强制转换:数字参数直接转为int;
- 长度限制,防止传入超大字符串;
- 正则匹配手机号、邮箱等固定格式;
- 输出到页面时做html转义,防止XSS;
- 入库前转义或者使用PDO预编译防止注入。
代码示例
<?php
// 获取GET参数
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
$name = trim($_GET['name'] ?? '');
// 长度校验
if(mb_strlen($name)>50){
exit("参数过长");
}
// 输出到页面,防XSS
echo htmlspecialchars($name,ENT_QUOTES);
框架层面最佳实践
TP6、Laravel等框架自带验证器,推荐优先使用框架验证,不用手写大量if判断。
// ThinkPHP6验证示例
$validate = new \think\Validate([
'id'=>'require|integer',
'name'=>'require|max:50'
]);
避坑点
不要简单依靠addslashes防御注入,推荐PDO预处理语句;参数过滤不要只在前端校验,后端必须二次校验,前端校验可被绕过。
总结
任何外部传入的数据都要校验,区分类型校验、长度校验、格式校验、输出转义四层防护,降低Web安全漏洞风险,是PHP项目开发的基础规范。
Nginx防盗链原理
Nginx防盗链原理
引言
网站图片、视频、静态资源经常被其他站点直接引用,消耗服务器流量与带宽。Nginx防盗链通过校验请求来源Referer,阻止第三方网站直接嵌入你的资源链接,降低服务器流量损耗。
原理说明
浏览器访问页面加载图片时,请求头会携带Referer,代表来源页面地址。Nginx读取该请求头,判断域名是否属于本站,非信任域名直接返回403拒绝访问。
局限:Referer可被客户端伪造,防盗链属于基础防护,不是100%安全,重要资源建议搭配token鉴权。
Nginx配置示例
location ~* \.(jpg|png|gif|mp4)$ {
valid_referers none blocked *.0454.wang;
if ($invalid_referer) {
return 403;
}
}
配置解释:
valid_referers配置允许的来源;none允许直接浏览器地址栏访问资源;- 匹配不到白名单,
$invalid_referer生效,返回403。
进阶优化
- 重要资源可使用url签名,生成带时效token的资源地址;
- CDN环境,需要同步在CDN配置防盗链;
- 部分爬虫、APP请求不带Referer,按需调整规则。
总结
Nginx Referer防盗链是低成本的静态资源保护手段,适合图片博客、素材站点。适合作为第一层防护,高安全场景需要结合URL签名二次校验。
网站被黑了怎么排查,后门查杀方法
前言
网站突然被挂了黑链、被跳转、内容被篡改?别慌,本文讲网站被黑后怎么排查、怎么找后门、怎么清理。
一、怎么判断被黑了
常见现象
- 网站打开变成别的页面(赌博、色情)
- 网站里多了很多不认识的页面
- 百度搜索显示的标题不对
- 网站突然变慢、CPU飙升
- 后台密码被改了
二、第一步:找最近修改的文件
黑客一般会往网站目录里传后门文件。
找最近24小时修改的文件
find /www/wwwroot/你的站/ -mtime -1 -type f
找最近7天修改的文件
find /www/wwwroot/你的站/ -mtime -7 -type f
找最近修改的PHP文件
find /www/wwwroot/你的站/ -name "*.php" -mtime -7
重点看: 你不认识的、突然冒出来的PHP文件。
三、第二步:找可疑代码
找一句话木马
黑客常用的一句话后门:
<?php @eval($_POST['cmd']); ?>
搜索:
grep -r "eval(" /www/wwwroot/你的站/
grep -r "assert(" /www/wwwroot/你的站/
grep -r "base64_decode(" /www/wwwroot/你的站/
grep -r "str_rot13(" /www/wwwroot/你的站/
找加密的后门
很多后门是加密的:
grep -r "gzinflate(" /www/wwwroot/你的站/
grep -r "gzuncompress(" /www/wwwroot/你的站/
grep -r "strrev(" /www/wwwroot/你的站/
找下载文件的后门
grep -r "file_put_contents(" /www/wwwroot/你的站/
grep -r "fwrite(" /www/wwwroot/你的站/
四、第三步:看Web日志
看Nginx访问日志,找可疑的请求。
看最近的访问
tail -100 /var/log/nginx/access.log
找可疑的POST请求
grep "POST" /var/log/nginx/access.log | tail -50
找访问可疑文件的
grep ".php" /var/log/nginx/access.log | grep "cmd"
五、第四步:看进程
看有没有可疑进程在跑。
ps aux
重点看:
- 不认识的进程
- 占CPU很高的进程
- 从/tmp目录跑的进程
杀掉可疑进程:
kill -9 进程ID
六、第五步:看定时任务
黑客会加定时任务,维持后门。
crontab -l
看有没有不认识的定时任务。
还有系统级的:
cat /etc/crontab
ls /etc/cron.d/
七、第六步:看后门文件特征
常见后门文件名
- shell.php
- cmd.php
- 1.php
- x.php
- upload.php
- webshell.php
看文件权限
后门一般是777权限:
find /www/wwwroot/你的站/ -perm 777
八、清理方法
方法1:删除可疑文件
确认是后门的直接删:
rm -f /www/wwwroot/你的站/可疑文件.php
方法2:重新上传程序
最安全的方法: 备份数据库,重新上传干净的程序,再恢复数据库。
方法3:改所有密码
- 后台密码
- 数据库密码
- FTP密码
- SSH密码
九、预防措施
1. 程序及时更新
WordPress、ThinkPHP等程序有漏洞要及时更新。
2. 上传目录禁执行
location ~* /upload/.*\.php$ {
deny all;
}
3. 定期备份
每天自动备份网站文件和数据库。
4. 改后台地址
不要用默认的admin后台地址。
5. 用安全插件
WordPress可以装Wordfence等安全插件。
十、常见坑
坑1:只删文件不改密码
黑客可能已经留了别的后门,删一个没用。
正确: 删文件 + 改所有密码 + 看定时任务。
坑2:备份也被感染了
备份文件里也有后门,恢复后又被黑了。
解决: 备份也要查。
坑3:只查网站目录
黑客可能在系统里留了后门(比如/tmp目录)。
解决: 也要查系统进程、定时任务。
总结
记住:
- 先找最近修改的文件
- 再找可疑代码(eval、base64_decode)
- 看Web日志和进程
- 看定时任务
- 删后门 + 改所有密码
- 最安全是重新上传干净程序
最快排查:
find /www/wwwroot/你的站/ -name "*.php" -mtime -7
grep -r "eval(" /www/wwwroot/你的站/
遇到问题加QQ23979811 协助处理