我们已经准备好了,你呢?

2026我们与您携手共赢,为您的企业形象保驾护航!

如何让PHP的代码更安全

更新时刻:2021年5月28日上午10点整,发布者:八重樱

尽管PHP被誉为全球最优秀的编程语言,然而它作为弱类型语言的安全隐患也不容忽视。对于以PHP为开发语言的网站,无论是规模大小,都普遍存在后台管理界面被绕过,从而直接进入后台的漏洞。而且,不同网站绕过后台的方式各不相同。本文将对此现象进行深入探讨。

目录

概述

攻击者能够通过构建有害的SQL指令并投递至数据库,一旦应用程序未能对用户提交的SQL指令进行有效的判断与过滤,那么这些SQL指令便有可能规避安全防护机制,进而嵌入旨在篡改后端数据库的其他指令,甚至可能执行系统层面的命令,最终对整个系统构成威胁。

例如删除 id 为 1 的帖子,sql 如下:

$post_id = $_POST['post_id'];
执行删除操作,针对posts表,条件是user_id等于1,同时id等于指定的$post_id。
\DB::statement($sql);

若有人于提交过程中输入“1 OR 1”,那么你的输入将会被拼接成如下形式:

执行删除操作,针对posts表,当user_id等于1且id也等于1时,或者当条件1成立时。

在原生SQL操作中,这种情况较为常见,大多数框架都能有效处理此类问题。一般通过参数设定或过滤特定字符来预防这类问题的发生。

越权漏洞1. 水平越权

同等地位的用户若越权行事,不仅可对自身数据享有访问与操作权限,更可擅自查阅他人物业信息,这一行为的核心在于对数据访问权限的滥用。

删除用户收款方式的场景如下:

graph LR

用户登录-->token

token-->获取收款方式列表

获取收款方式列表--token-->通过id删除

采用收款途径 {id} 进行操作,请求所指向的路径是:/api//{id}。

若用户A接受的支付手段包括{1,2,3},而用户B可接受的支付途径则是{4,5}。

若未进行数据管控,A 用户在登录后若使用其个人token访问并执行删除操作,将导致B用户的数据被误删,因此必须对这一操作方法实施数据管控。

# 1 删除前鉴权处理
public function destory($id){
此笔款项对应的数据记录,经查询,已被成功定位至数据库中。
若支付对象的用户ID与当前用户的ID不一致,{ }
            return ...
    }
    $payment->delete();
}
# 2 参入id查询删除
public function destory($id){
执行删除操作,针对的是与当前用户ID相匹配的记录,同时该记录的ID也必须与指定ID一致;该操作由Payment模型执行。
}
# 3 模型关联查询
class User extends Model{
    public function payments()
    {
返回当前模型与“App\Payment”模型之间的一对多关系。
    }
}
PaymentController 类继承自 Controller 类。
    public function destory($id)
    {
当前用户的相关支付记录,通过ID筛选,将被删除。
    }
}

建议采用第三种数据控制方法,否则之前学习的面向对象知识将付诸东流。在获取收款方式列表时,同样需要实施数据权限管理;用户与收款方式之间形成了一对多的关系。在模型建立关联之后,我们可以将获取用户收款方式列表的操作编写为:

class PaymentController extends Controller{
    public function index($id)
    {
        #带条件的查询
将当前用户的支付记录筛选出来,通过如下方式:使用闭包函数对查询进行限定,具体操作为:
                ...
        })->get();
        #不带条件的查询
当前用户的所有支付记录被赋值给了变量$payments。
    }
}

2. 垂直越权

某些角色权限较低者,若通过特定手段攫取了高于其原有权限的权限,便构成了越权行为。例如,一般用户guest擅自更改了管理员admin的密码;或者guest能够直接登录后台,进而获取包括域名管理、用户管理在内的所有权限。

要解决这一问题,我们必须将权限与职责进行细致划分,以最小的单元进行细分。在此基础上,采用基于 RBAC 的理念来构建权限管理系统。具体而言,该系统可划分为以下几个相互关联的模型。

graph LR

用户--多对多-->角色

用户--多对多-->权限

角色--多对多-->权限

在每次处理请求的过程中,前置中间件会首先评估该用户是否具备永久执行该请求的资格,若用户不具备相应权限,则将请求予以拒绝。

3. 上下文越权

攻击者可借助应用状态机存在的缺陷,窃取对重要资源的访问权,从而产生与上下文相关的越权问题。此类漏洞通常归类于业务逻辑漏洞。例如,在密码找回环节,攻击者可能利用自身账户信息成功通过验证,进而篡改了他人的密码。

graph LR

1.邮箱验证-->2.找回密码

步骤一完成之后,需进行密码找回操作,具体路径为 。若未对当前尝试找回密码的账户进行邮箱验证的核实,则可能引发越权的安全隐患。

路由:采用【PUT】方法访问/api/users/find-接口,需要传入参数email。

校验环节分为两个步骤,首先通过/api/email/check接口进行,随后再进行/api/users/接口的修改操作。

定义一个用户控制器类,使其继承自控制器基类。
    public function check($data)
    {
若经验证,该电子邮件地址与验证码匹配无误,则执行。
                return true;
        }
        ...
    }
公开方法查找密码
    {
User模型根据邮箱字段筛选,将匹配到的数据以first方法获取单条记录,并赋值给$user变量。
用户对象的新密码经过bcrypt加密处理后被赋值给其密码属性。
        $user->save();
    }
}

对已完成的邮箱验证账户进行复检,确保其与当前尝试找回密码的账号相符。

class UserController extends Controller{
    public function check($data)
    {
        if (checkEmail($data['email'], $data['code'])) {
                return true;
        }
        ...
    }
本函数旨在根据提供的数据进行密码查找。
    {
        if (checkEmail($data['email'], $data['code'])) {
获取用户信息,通过邮箱地址筛选,针对$data数组中的'email'键值,执行查找操作,并返回第一个匹配的User对象。
用户对象的用户密码被设置为数据数组中新的密码值。
                $user->save();
        }
        ...
    }
}

限制分页条目范围,防止恶意请求

如获文章列表的接口/api/

设定分页大小为参数中的“pagesize”值,若该值不存在,则默认为15条记录。
            ...
执行查询时,设定每页显示的记录数为$pageSize,跳过前面页数乘以每页记录数得到的偏移量,按照ID降序排列,最后获取结果集。
    ...
    ...
}

若该代码缺乏明确的限制条件,那些心怀恶意的人可能会提出将输入值设定为5000、10000甚至更高的数值,这种行为会对数据库造成不小的负担,例如在/api/?=0&=10000这样的请求中。

//用框架自带的分页方法
public function index(){
$builder变量被赋值为Article模型,通过关联category模型并指定只获取id和name字段,然后按照id降序排列,最后以每页8条数据的分页方式返回结果。
返回响应,状态设为真,计数为构建器总条目数,文章列表为构建器返回的文章集合。
}

JWT 的 Token 需要二次加密

许多拓展包生成的token安全性不高,他人可利用其进行解密,进而获取包括加密主键、载荷在内的关键信息,因此通常需要对JWT的token进行再次加密处理。

限制上传文件的类型

针对图片上传的接口,若未对上传文件的格式进行约束,攻击者便有可能将带有.php扩展名的文件传输至根目录下的/目录,进而利用根目录权限执行该文件。

需要设计安全的文件上传功能避免上述问题

1.文件上传的目录设置为不可执行

2.判断文件类型

3.使用随机数改写文件名和文件路径

4.单独设置文件服务器的域名

禁止或者避免写自动解压.zip 等压缩文件的代码

仅仅对文件或压缩包的体积进行限制是无效的,因为一个看似微小的ZIP炸弹文件,其体积可能仅为42KB,然而在展开之后,却能占据数GB的空间。

避免登录密码被暴力破解

设定严格的速率控制措施,例如对登录次数进行限定,一旦登录错误次数累计达到x次,将暂停用户登录权限n分钟。

2.密码加上随机盐

public function reg(){
    $user = new User;
    $salt = radom(6);
用户密码设置为通过bcrypt算法对数据中的密码与盐值进行拼接后的结果。
    ...
}

做好异常处理,避免在生产环境中不正确的错误报告暴露敏感数据

若你疏忽大意,在生产环节中,因错误报告的不当披露,有可能导致敏感资料的泄露,诸如文件夹布局、数据库架构、连接详情以及用户资料等。

1.在.env 文件中关闭调试模式

=true

2.php 错误控制 、


display_errors = Off

php 弱语言的设计缺陷如:

$array=[0,1,2,'3'];
执行var_dump函数,检查字符串'abc'是否存在于数组$array中,结果显示为真。
执行了检查函数,确认'1bc'是否存在于数组$array中,结果显示为真。
上述情况均返回 true,原因在于 'abc' 被转换成了 0,而 '1bc' 则被转换为了 1。
$a = null;
$b = false;
echo $a==$b;  //true
$c = "";
$d = 0;
echo $c==$d   //true

在一些重要的地方需要使用===来作数据判断。

LFI (本地文件包含)

LFI漏洞,即本地文件包含,指的是用户未经验证便从磁盘读取文件的安全缺陷。

不进行用户输入的验证,直接通过GET请求方式加载用户所需渲染的模板文件。


    

由于系统具备加载各类文件的能力,而不仅限于PHP,攻击者得以将系统中的任意文件设定为被包含的目标。

index.php?page=../../etc/

这将导致 /etc/ 文件被读取并展示在浏览器上。

为了有效抵御这类攻击,你需细致评估用户可输入的数据种类,同时剔除其中可能存在的危险字符,例如输入内容中的点号“.”、斜杠“/”以及反斜杠“\”。

XSS

XSS,亦称CSS(Cross Site),即跨站脚本攻击。这种攻击方式涉及恶意攻击者向网页中植入有害的HTML代码。当用户访问该网页时,这些嵌入的HTML代码会被执行,进而实现攻击者对用户的恶意目的。


    

You searched for:

由于我们直接将用户上传的内容予以打印,并未进行任何形式的筛选,不法分子便有可能通过拼接特定的URL:.php?q=%%(1)%3B%3C%%3E,实施恶意操作。

PHP 渲染出来的内容如下,可以看到 代码会被直接执行:


You searched for:

我们发现:彻底没有任何内容,因为这是一个演示版本。

可以:

使用()过滤特殊字符,防止大部分的 xss 攻击

CSRF (跨站请求伪造)

例如网站上有用户可以用来注销账户的链接。

销毁账户

二维码
扫一扫在手机端查看

本文链接:https://by928.com/9117.html     转载请注明出处和本文链接!请遵守 《网站协议》
我们凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求,请立即点击咨询我们或拨打咨询热线: 13761152229,我们会详细为你一一解答你心中的疑难。

项目经理在线

我们已经准备好了,你呢?

2020我们与您携手共赢,为您的企业形象保驾护航!

在线客服
联系方式

热线电话

13761152229

上班时间

周一到周五

公司电话

二维码
微信
线