我目前检查每个GET和POST变量,isset()并在isset()返回false 时抛出异常.
例1:
if(!isset($_GET['some_var']))
throw new Exception('GET variable [some_var] is not set.');
$someVar = $_GET['some_var'];
Run Code Online (Sandbox Code Playgroud)
例2:
if(!isset($_GET['some_num']))
throw new Exception('GET variable [some_num] is not set.');
if(!ctype_digit($_GET['some_num']))
throw new Exception('GET variable [some_num] is not a number.');
$someNum = $_GET['some_num'];
Run Code Online (Sandbox Code Playgroud)
在我的生产应用程序中,我有一个全局异常处理程序,它将异常和错误发布到日志文件,然后重定向到一个通用的道歉页面.
这是一个好的做法吗?是描述性异常和错误消息,例如上面的安全风险(黑客是否有可能读取异常通知,然后使用该信息来操作我的脚本)?
谢谢!
记录错误并禁止输出正是您应该做的。错误报告可能会令人讨厌。
在2007年的OWASP前10名中,有“ 信息泄漏和不正确的错误处理”,但是在2010年已删除。通过dispaly_errors=On在php.ini中进行设置,您容易受到CWE-200的攻击。您的Web应用程序的完整路径将泄露给攻击者。更糟糕的是,通过启用错误报告功能,可以更轻松地通过查找sql错误消息来查找SQL注入。
在PHP / MySQL应用程序上结合使用时,您可能会执行非常严重的攻击
$vuln_query="select name from user where id=".$_GET[id];
Run Code Online (Sandbox Code Playgroud)
如果
http://localhost/vuln_query.php?id=1 union select "<?php eval($_GET[e])?>" into outfile "/path/to/web/root/backdoor.php"
Run Code Online (Sandbox Code Playgroud)
这使得这个完整的查询:
select name from user where id=1 union select "<?php eval($_GET[e])?>" into outfile "/path/to/web/root/backdoor.php"
Run Code Online (Sandbox Code Playgroud)
我将确保display_errors=Off并且已将文件FILE特权撤消到您的Web应用程序的MySQL用户帐户中。
“黑客是否有可能读取异常通知,然后使用该信息来操纵我的脚本?”
或许。
通常,您希望在错误情况下向最终用户提供尽可能少的信息。在这种情况下,如果您告诉某人特定的 get 变量不存在,那么他们可能会尝试向该变量提供随机值以查看应用程序的行为。
当然,您还必须平衡这一点与真实用户的需求。如果该变量是他们通常可以控制的变量,那么给出有关该值的问题的响应是完全可以接受的。
更新
最近遇到了大量的 Web API,它们似乎认为抛出通用错误消息是正确的方法,我想稍微更新一下。
Web API 向使用系统返回适量的信息至关重要,以便他们能够找出问题所在并修复它。
在最近的一个支付处理 API 案例中,他们的文档完全是错误的。他们显示的测试交易数据始终返回“服务器错误 500”,我们别无选择,只能让他们的一位开发人员打电话并煞费苦心地逐步检查 XML 中的每个元素。在 50 个元素中,只有一个与其“开发人员文档”中的名称相同。
在另一项集成中,我们收到了“服务器错误 402”。-- 这不是支付网关。尽管从未在他们的文档中引用过,但显然该消息意味着缺少 JSON 参数。顺便说一句,这是他们的文档中未引用的参数,并且再次需要开发人员花时间来识别它。
在上述两种情况下,如果错误消息以有效文档帖子的示例进行响应,那将会非常有帮助。类似于当您传递错误参数时旧的 Unix/DOS 命令将返回帮助信息。我真的不想和其他程序员说话。我知道他们的时间很昂贵,他们宁愿做一些事情而不是接听支持电话;但更重要的是,如果我在晚上 10:00 工作并且需要 RFN 的答复,那么等到第二天程序员接电话是很少的选择。