企业站 SQL 注入实战:PCRE 正则回溯绕过关键词 WAF 完整实战 | 进阶02

目录

[正则回溯绕过 SQL 注入过滤:原理、实战与代码修正](#正则回溯绕过 SQL 注入过滤:原理、实战与代码修正)

[一、从正则回溯看 PHP 代码过滤](#一、从正则回溯看 PHP 代码过滤)

[1. 贪婪匹配如何触发回溯](#1. 贪婪匹配如何触发回溯)

[2. 回溯次数限制与绕过条件](#2. 回溯次数限制与绕过条件)

二、从一个实际站点分析过滤逻辑

[1. 推测 WAF 的正则](#1. 推测 WAF 的正则)

[三、寻找 POST 注入点](#三、寻找 POST 注入点)

[四、使用 AI 与浏览器 MCP 辅助测试](#四、使用 AI 与浏览器 MCP 辅助测试)

[1. Chrome DevTools MCP 的能力](#1. Chrome DevTools MCP 的能力)

[2. MCP 的工作架构与权限](#2. MCP 的工作架构与权限)

五、模型发现注入点后的进一步分析

六、手工构造注入请求

[1. 用注释符替代空格](#1. 用注释符替代空格)

七、把回溯载荷放进注释

[1. 使用 LIMIT 与偏移量逐条读取](#1. 使用 LIMIT 与偏移量逐条读取)

八、第一种绕过思路总结

[九、正确处理 preg_match 返回值](#九、正确处理 preg_match 返回值)

[1. 为什么 === 能避免绕过](#1. 为什么 === 能避免绕过)

图片序号---截图内容对照表


正则回溯绕过 SQL 注入过滤:原理、实战与代码修正

一、从正则回溯看 PHP 代码过滤

正则回溯是 2018---2019 年间就被反复讨论、但现在依然有效的议题。先看这个表达式:它试图判断输入内容是否包含 PHP 代码。

【插入图1】

为了理解它的行为,先看它匹配的对象。表达式中的任意字符都可以被点号匹配,也就是说,在这个位置写入什么内容,都有可能被匹配到。

如果一开始看不懂这类表达式,以前可能要研究很久;现在可以直接让 AI 解释每个匹配部分,再回到代码中验证。

【插入图2】

【插入图3】

复制代码
function is_php($data) {
    return preg_match('/\<\?.*[\'\?>].*/is', $data);
}

它防御的目标,是阻止用户写入 PHP 代码:一旦输入不是 false,程序就会继续执行写入操作。

【插入图4】

php 复制代码
if (!is_php($input)) {
    file_put_contents('shell.php', $input);
    // fwrite($f, $input); ...
}

如果输入是一段 PHP 语句,程序就会把它写入文件,这就是典型的后门写入风险。file_put_contents 的第一个参数是文件名,第二个参数是要写入的文件内容。

【插入图5】

如果前面没有防御,攻击者就能把一句话后门直接写进文件。因此,程序需要在写入之前进行限制。

【插入图6】

问题在于,这种限制和前面使用 replace 的限制一样,仍然是基于同一类匹配逻辑完成的。接下来观察它的匹配过程,以及它到底匹配了多少次。

【插入图7】

1. 贪婪匹配如何触发回溯

按步骤分析:

  1. 第一步,表达式先匹配尖括号。

  2. 第二步,继续向后匹配。点星是贪婪匹配,会一次性把后面的内容尽可能全部匹配完。

  3. 匹配完成后,表达式发现中括号中的值无法匹配。

  4. 匹配失败后,正则引擎只能回到前面的匹配位置,逐步向前退回。

【插入图8】

它会一点一点地回退,直到找到可以继续匹配的位置。正常情况下,这段内容不应该需要这么多步,但由于发生了多次回溯,实际匹配次数会显著增加。

2. 回溯次数限制与绕过条件

PHP 可以看作一个有限状态机。回溯次数过多会带来拒绝服务风险:如果一次输入让正则引擎回溯一亿次,那么用户每提交一次内容,服务器都要重复执行大量回溯操作,网站就可能被拖成 DoS。

DoS 是大量请求造成服务不可用;DDoS 则是分布式拒绝服务攻击。为了避免正则表达式造成这类问题,PHP 对回溯次数设置了上限,按英文文档通常为 1,000,000 次。

当回溯次数超过上限时,正则函数会返回 false。如果代码这样判断:

php 复制代码
if (!preg_match($pattern, $input)) {
    file_put_contents('shell.php', $input);
    // 旧示例中也使用过 fwrite($f, $input)
}

函数返回 false 后,!false 会变成 true,程序反而会进入写入分支,形成绕过。

【插入图9】

这个绕过有一个重要前提:不能依赖 GET 传参。GET URL 的长度受限制,参数过长时中间件(例如 Nginx、Apache)可能直接返回 400。因此,这类测试通常要适配 POST 参数。

PHP 限制回溯次数,本来就是为了防止正则表达式拒绝服务。很多 WAF 也采用类似的正则过滤逻辑:只要找到一个 POST 注入点,再用 Python 脚本让提交参数超过 100 万次,就可能触发这个返回值异常。

【插入图10】

中文资料中有时会写成 10 万次(100000),英文资料通常写成 100 万次(1000000),实际分析应以英文文档和运行环境为准。超过限制后,函数返回 false,依赖松散判断的 WAF 就可能被绕过。

具体做法是编写 Python 脚本,把提交参数构造到超过 100 万次回溯的规模。

二、从一个实际站点分析过滤逻辑

有同学遇到过一个非常简陋、看起来问题很多的站点,却始终无法绕过。原因是它使用 GET 进行注入:前面的注入点没有问题,但一旦使用 SELECT ... FROM,返回结果就一直为空。

【插入图11】

【插入图12】

使用 UNION SELECT 或 SELECT FROM 时页面变成空白。第一次测试 ORDER BY 可能还能成功,继续操作后却再次报错。

这里还要确认参数类型。它不一定是字符型,因此不一定要用单引号闭合。通过 ORDER BY 逐步测试列数:第 10 列不存在,回退到第 9 列后成功,说明查询有 9 列。

【插入图13】

确认列数后,理论上应该能在前端找到回显列,再向该列写入查询内容。但现在最大的可能是 ORDER BY 没有过滤,而 SELECT、UNION SELECT 被过滤了。

可以继续测试其他关键词。例如,某个位置能够回显 user,但一旦开始使用 SELECT ... FROM 查询库、表、列,结果仍然为空,因此没有必要在同一路径上反复尝试。

1. 推测 WAF 的正则

第一次遇到 SELECT ... FROM 直接返回空时,需要依次考虑:

  • 只过滤了 SELECT;

  • 只过滤了 UNION;

  • 过滤了 SELECT 与 UNION 的组合;

  • updatexml 同样可能因为 SELECT、FROM 或 SELECT FROM 被过滤。

还要确认 information 是否被过滤。经过多次测试后,可以推测 WAF 可能使用了类似下面的正则:

【插入图14】

php 复制代码
if (preg_match('/(?:union(.*?)select)/i', $uid)) {
    die('fuck off');
}

三、寻找 POST 注入点

接下来要寻找 POST 注入点。GET 注入点受 URL 长度限制,参数过长时中间件会报错,而中间件通常不在当前测试范围内。POST 注入点大多位于表单提交位置。

SQL Labs 的 POST 注入点也通常在表单中,因此需要重点查看在线订购、在线收费等表单。

【插入图15】

打开思路后会发现,页面上的在线订购等区域本质上都是 form 表单,需要逐个确认其中是否存在注入点。

第一种方式,是让 AI 直接打开目标站点并测试 POST 注入点。

【插入图16】

【插入图17】

第二种方式,是使用扫描器扫描站点,例如 WPScan、AWVS 等工具。

【插入图18】

渗透测试的重点不只是最后的执行。现在 AI 可以帮助编写代码,真正困难的是能否想到要测试的方向。

当然,也可以手工测试,但这更依赖基本功。更稳妥的方式是用 Burp Suite 抓取提交的 form 表单,然后逐个字段测试,因为一开始并不知道到底是哪个字段存在注入点。

例如,页面中数量字段默认是 1,可以先提交一个简单值,再观察返回结果。

【插入图19】

页面对字段格式似乎没有太多限制。提交时曾经出现一闪而过的报错,这通常意味着该字段可能存在注入点。看不清瞬时错误时,可以让 AI 自动测试、使用扫描器,或者通过 Burp Suite 手工逐字段验证。

四、使用 AI 与浏览器 MCP 辅助测试

可以直接打开 AI 客户端,让它判断站点是否存在 POST 注入点。使用 Claude Code 或 Codex 都可以。

【插入图20】

【插入图21】

不同模型的套餐、额度和速度不同。课程中提到了 ChatGPT、ChatGPT 5.6、DeepSeek、M次方 M3(Mimas M3)、Kimi K3 等模型:有的价格较低(课程中提到 ChatGPT 5.6 曾经降价),有的响应较快,但额度消耗也快。

【插入图22】

【插入图23】

某些模型可能存在道德约束,测试时可以先让它继续运行。若选择手工测试,则通过 Burp Suite 抓包即可。发现漏洞时,手工测试同样是一条可行路径。

【插入图24】

有些模型会要求提供授权证明。课程中提到,可以使用 GPT 的 image2.0 生成看起来真实的授权证明以通过审核。

【插入图25】

DeepSeek 的道德约束相对较少。为了让模型更好地操作页面,可以安装 MCP。MCP 可以理解为大模型的"手和脚":模型拥有较强的分析能力,但实际操作浏览器的能力需要外部工具补足。

【插入图26】

1. Chrome DevTools MCP 的能力

课程演示使用 Claude Code,并安装了 chrome-devtools MCP。它可以帮助大模型打开 Chrome,并对浏览器执行操作。

【插入图27】

该 MCP 大约提供 29 个工具函数,包括:

  • 点击、关闭页面;

  • 填充 form 表单,例如自动填写登录表单;

  • 获取控制台信息;

  • 获取网络请求;

  • 对页面执行 hover 等鼠标操作;

  • 使用 pressKey 控制键盘;

  • 截图;

  • 列出页面内容(只读,不修改)。

【插入图28】

开发者工具中的控制台可以通过 F12 打开,网络面板则会记录刷新页面时产生的各种网络请求。

【插入图29】

2. MCP 的工作架构与权限

架构可以概括为:

  1. 大模型是客户端。

  2. MCP Server 是 Chrome 提供的服务端。

  3. Chrome 将浏览器能力和函数暴露给 MCP Server。

  4. 客户端连接 MCP Server 后,便可以调用这些函数操作 Chrome。

这个 Server 不是大模型编写的,而是 Chrome 方面提供的能力接口。安装时,可以在 GitHub 找到项目地址,交给 Claude,让它按照项目说明完成安装。

使用过程中,模型经常会询问是否允许某项操作。Codex 可以使用 Codex -Yolo 模式,获得最高权限并自动执行,不再逐次询问。

【插入图30】

最高权限也意味着更高风险:模型可能自作主张删除服务器或电脑上的内容。Claude 则有 dangerous 参数,含义同样是跳过权限设置,赋予模型更高权限。

【插入图31】

五、模型发现注入点后的进一步分析

DeepSeek 发现了一个注入点,而且发现的位置与人工测试得到的位置一致。

【插入图32】

如果换成 ChatGPT,效率可能更高、耗时可能更短。这并不是说国产模型不能完成任务,而是多次对比后,课程中的结论是 ChatGPT 在这类测试上的效率可能高于 DeepSeek。

大模型能够在现场找到有效注入点,意味着渗透测试的门槛明显降低:即使测试者不熟悉该方向、手工没有找到注入点,模型也可能代为发现。模型找到注入点后,还能自动获取库名和表名。

【插入图33】

但当模型继续获取表信息时仍可能出错,因为它没有绕过 SELECT FROM 的过滤。

【插入图34】

模型会猜测 WAF 过滤了 information,也会猜测过滤了 SELECT。它无法直接知道对方到底过滤了什么,只能不断试探。

【插入图35】

大小写绕过通常不现实,大小写变化并不能改变此类正则匹配。

【插入图36】

需要注意,Codex -Yolo 和 Claude 的 dangerous 模式存在副作用:如果真实探测的网站确实存在漏洞,模型可能继续执行删除库、删除数据等破坏性操作。线上网站一旦受到影响,业务方可能追究责任,使用时必须自行承担后果。

此时 AI 的测试思路和人工思路是一致的。最开始人工也可能误以为过滤的是 information,后来把关键词中的字母改掉,结果仍然返回空白,说明问题不是 information 本身,随后才转向判断 FROM 是否被过滤。

由于已经找到 GET 注入点,接下来可以按真实渗透流程分析:已确认 GET 注入点;查表、查列返回空白,需要思考具体过滤了什么;继续观察模型是否偏离方向。

【插入图37】

模型一度使用 load_file 读取服务器文件。load_file 对环境要求非常苛刻,无论读取还是上传文件,都需要较高权限和满足特定条件,通常很难成功。

【插入图38】

模型汇总出的信息包括:PHP 版本较旧(课程中提到可能是 PHP 5.5),可能存在历史漏洞;基于注入已经查到部分数据;同时还找到两个 POST 注入点,但没有绕过 WAF。

【插入图39】

【插入图40】

【插入图41】

最终能获取到的信息很少。

【插入图42】

在漏洞提交流程中,走到这一步通常已经可以确认存在注入点,但是否能被漏洞库接收并不确定。原因是没有绕过 WAF,能取到的数据较少。

模型还尝试了大小写、内联注释、双编码等方式,但这些方式没有成功绕过。

【插入图43】

这是 DeepSeek V4 Pro 的测试结果。它没有绕过 WAF,但已经找到了注入点。换用 Claude Code 或 ChatGPT,可能直接通过正则回溯整体绕过,也可能不需要人工参与。

模型没有明确说明究竟过滤了什么,因此人工仍需判断是 SELECT FROM,还是 UNION SELECT 被过滤。

六、手工构造注入请求

DeepSeek 的结果显示,p1m1c1 等多个字段都存在注入点。

【插入图44】

【插入图45】

这里选择 bs 字段作为示例,换成其他字段也可以。注入语句使用常见的报错注入,目标是查询 table_name,因为前面没有查到表名。

【插入图46】

查询逻辑是从 information_schema.tables 中读取表名,并限制数据库名为已经获取到的 truth,再通过 LIMIT 配合偏移量逐条读取。

sql 复制代码
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'truth'
LIMIT offset, 1;

【插入图47】

真正耗时的细节是单引号闭合。注释符可能被过滤,因此需要尝试闭合。按理说可以直接使用 1=1,但实际测试始终为空;当把闭合内容改成 1234 加 4 个 a,也就是让这一段形成 5 个字段时,查询反而成功。

【插入图48】

【插入图49】

如果最后卡在这一步,不能因为 1=1 失败就直接放弃。最初也无法预料到这个细节,只能逐步测试,直到发现这种写法可以执行。

原因在于,先向 bs 位置注入数据库名时,使用 1=1 闭合会报错。测试方法是先填写表单字段,再打开 Burp Suite 抓包。

【插入图50】

不会写抓包或利用代码时,可以让 AI 编写。只要把需求描述清楚,AI 就能生成代码。渗透测试中,找不到的注入点可以让 AI 找,绕不过的 WAF 可以让 AI 尝试,写不了的 EXP 和利用脚本也可以让 AI 编写。

抓到请求后,将内容放入 Burp Suite 中继续修改。

【插入图51】

【插入图52】

【插入图53】

当前请求中存在大量字段。可以直接提交,也可以先在 bs 字段中写入分号进行测试,因为当前使用的就是 bs 字段,其他字段理论上也可能存在同样问题。

提交后页面提示"购买信息已提交",但同时仍然报错。

【插入图54】

报错说明该位置存在注入点,接下来继续测试。前面使用的是 update 相关方式,因此仍可以使用 update 进行验证。

【插入图55】

具体写入内容可以逐步尝试。需要确认使用 # 还是其他注释符:# 可以闭合前面的单引号并注释掉后续语句,但当前写法是否成立,还需要继续观察。

【插入图56】

错误信息中的 near 片段显示,闭合结构可能是一个单引号和一个括号,后面还可能存在括号。暂时不用一次性解决所有括号,只先验证单引号闭合是否能让后续内容失效。

【插入图57】

挖洞过程不是一步到位,而是不断提交、观察、修正。第一次提交没有返回数据时,需要检查写法是否有误,还要注意页面颜色是否发生变化。

刚才的写法可能是:

复制代码
'/**/

【插入图58】

这个写法可能被直接带入 SQL 数据库执行。如果空格没有被正确识别,数据库就会报错。

【插入图59】

1. 用注释符替代空格

正常情况下,MySQL 能识别空格,但请求提交时可能经过 URL code 编码。空格会被编码成 %20,这个编码值如果继续进入数据库,就不再是空格。

【插入图60】

因此,%20 进入数据库后可能导致语法错误。解决方法是去掉编码后的空格,使用 /**/ 替代空格。

【插入图61】

在 MySQL 的常见绕过方式中,注释符可以承担空格分隔作用。URI 编码器通常不会再对这些注释字符进行处理,因此它们能够原样进入数据库。

重新提交后页面不再报错,至少说明这一部分格式已经接近正确。

【插入图62】

此时没有报错,但也没有注入结果。可以继续考虑 # 是否因为编码而失败:# 可能会被编码为 %23,即使改成 %23 仍然无效。

【插入图63】

注释符路径无效时要立即切换思路,尝试单引号闭合。此前已经闭合过一次,后面可能还缺少一个单引号。

【插入图64】

如果到这里仍没有返回数据,很多人会放弃。但当前思路、注入点和空格绕过都已经确认,真正的关键在下一步。

七、把回溯载荷放进注释

这一步要把用于触发回溯的内容放在注释里。

【插入图65】

继续尝试后仍可能暂时没有结果,不要因此停止。

【插入图66】

现在回到前面介绍的 100 万次回溯。需要把回溯载荷添加到注释内部,放在其他位置会破坏 SQL 语句。

【插入图67】

【插入图68】

回溯载荷放在注释中,不会影响 MySQL 的执行;注释中的大量 a 仍然能触发正则匹配过程。实际只需在一个位置加入即可,没有必要重复添加两处。

【插入图69】

继续提交。一旦出现报错信息,就说明数据已经取到。

【插入图70】

拿到数据后,就可以获取表名、列名等信息。

【插入图71】

这里先获取表名。只要能获取到表名,就说明当前闭合和绕过方式成立;如果无法获取,再回头检查前面的步骤。

【插入图72】

这个站点已经过了半年,理论上可能没有修复。虽然页面简陋,但重庆再生资源集团规模较大、营收较高,漏洞库可能因为目标规模而接收报告,只是其业务对这类安全问题的重视程度可能不高。

1. 使用 LIMIT 与偏移量逐条读取

接下来只需要调用查询。offset 表示偏移量:想获取第几个数据,就在 LIMIT 中传入相应的偏移量,不必一次读取全部内容。

【插入图73】

例如,从第一个表名开始读取,可以依次使用 LIMIT 0,1、LIMIT 1,1、LIMIT 2,1 等形式。我这里只读取 20 个,剩余内容不再继续执行。

只要成功获取一个表名,就说明绕过成功。

【插入图74】

结果显示,该数据库一共只有 11 个表,因此读取 20 个时实际会得到全部表名。之后可以继续查询管理员表的列和数据。

八、第一种绕过思路总结

这就是第一种 SQL 注入绕过思路:如果 WAF 使用正则限制 SELECT、SELECT FROM 或 UNION SELECT,需要优先想到正则回溯,通过超过回溯次数上限使函数返回异常值,从而绕过错误的判断逻辑。

九、正确处理 preg_match 返回值

如果现在让你重新编写前面的过滤代码,不能继续使用原来的写法,因为它已经被回溯绕过。

【插入图75】

应该把匹配逻辑封装为函数。

【插入图76】

官方文档指出,判断函数返回值时必须使用三等运算符进行严格比较。

【插入图77】

可以写成类似下面的结构:

php 复制代码
function is_php($data) {
    return preg_match('/\<\?.*[\'\?>].*/is', $data);
}

然后把匹配值直接放进函数中。

【插入图78】

判断时,不再使用模糊的 if 逻辑,而是直接返回严格结果:

【插入图79】

php 复制代码
function is_php($data) {
    $matched = preg_match('/\<\?.*[\'\?>].*/is', $data);
    return $matched === 1;
}
​
if (is_php($input) === true) {
    // 匹配到 PHP 代码时拒绝写入
}

匹配到时返回 true,匹配不到时返回 false。返回值必须使用三等运算符判断,不能再依赖弱类型转换。

【插入图80】

1. 为什么 === 能避免绕过

正则回溯超过限制后,函数可能返回 null 或 false。如果使用 ==,PHP 的弱类型机制会进行值转换:null 可以被转换成 false,也可以与 0 相等,于是错误判断就可能被绕过。

== 只比较值,不比较类型;=== 同时比较值和类型。因此,null 与 false 在严格比较下并不相等。

防御代码应该使用三等运算符判断函数返回值:

复制代码
if (preg_match($pattern, $input) === 1) {
    // 匹配到 PHP 代码
}

PHP 是弱类型语言,很多问题都来自强制的数据类型转换,例如把 null 转换成 false 或 0。在严格比较模式下,回溯异常返回的 null 无法伪装成正常匹配结果,因而不能再绕过 if 判断。

【插入图81】

因此,今天介绍的第一个绕过点就是正则回溯;对应的修正方式,是严格区分 preg_match 的返回值类型,使用 === 完成判断。


图片序号---截图内容对照表

图片序号 截图内容
1 PHP is_php 函数与正则表达式示例
2 正则表达式测试界面
3 preg_match 判断 PHP 代码的函数示例
4 file_put_contents 写入文件的示例
5 PHP 后门写入代码片段
6 正则过滤函数与写入逻辑组合
7 正则测试工具中的匹配过程
8 正则回溯逐步退回的匹配界面
9 PHP 正则回溯超限返回 false 的测试结果
10 PHP 中英文文档的 PCRE 回溯限制对照
11 目标站点使用 UNION SELECT 后的页面结果
12 目标站点页面与 SQL 错误显示
13 9 列查询与回显位置测试
14 WAF 过滤 UNION ... SELECT 的 PHP 代码
15 重庆再生资源集团站点首页
16 目标站点表单区域
17 站点表单字段与可测试位置
18 扫描器发现站点信息的界面
19 在线订购表单及字段输入
20 AI 客户端启动与测试界面
21 AI 工具运行窗口
22 模型命令行运行界面
23 AI 模型测试输出
24 AI 测试授权提示或运行界面
25 浏览器操作授权弹窗
26 MCP 配置或安装命令行
27 Chrome DevTools MCP 工具说明
28 MCP 提供的浏览器工具函数列表
29 Chrome 开发者工具网络面板
30 Codex 高权限模式参数说明
31 Claude dangerous 参数界面
32 DeepSeek 发现注入点的命令行输出
33 模型获取数据库与表信息的输出
34 模型查询表信息时返回空白
35 模型对 information / SELECT 过滤的推测
36 模型尝试大小写绕过的测试输出
37 模型偏向 load_file 的测试过程
38 模型对站点信息的汇总结果
39 模型发现 POST 注入点的输出
40 第二个 POST 注入点的测试结果
41 注入请求与 PHP 过滤代码
42 注入测试获取到的有限信息
43 DeepSeek V4 Pro 未绕过 WAF 的结果
44 多个字段存在注入点的扫描结果
45 字段注入测试代码或请求
46 查询 information_schema.tables 的 SQL 请求
47 表名查询与 LIMIT 偏移量参数
48 单引号闭合测试输入
49 5 个字段时成功的输入结果
50 Burp Suite 抓包前的表单与请求
51 Burp Suite 中的完整提交请求
52 浏览器开发者工具中的请求详情
53 bs 字段中的单引号输入
54 提交购买信息后的 SQL 报错
55 update 注入测试请求
56 注释符与闭合字符测试输入
57 单引号、括号闭合测试
58 /**/ 注释符替代空格的输入
59 注释符进入 SQL 查询的请求
60 URL 编码 %20 导致报错的示例
61 MySQL 使用 /**/ 替代空格的结果
62 空格绕过后不报错的请求结果
63 %23 注释编码测试
64 单引号闭合再次提交的请求
65 继续添加回溯载荷前的请求
66 回溯载荷测试流程
67 正则回溯次数载荷位置
68 将大量字符放入注释中的请求
69 添加回溯载荷后的请求片段
70 出现 SQL 报错并取得数据的结果
71 获取表名、列名的查询结果
72 表名查询脚本与返回结果
73 使用偏移量读取表名的代码
74 读取到 11 个表名的命令行结果
75 原始、可被绕过的 PHP 判断代码
76 将过滤逻辑封装为函数的代码
77 PHP 文档中关于严格比较返回值的说明
78 将 preg_match 返回值放入函数的代码
79 使用 return 直接返回布尔判断的代码
80 null、false 与严格比较说明
81 使用 === 防止回溯绕过的最终 PHP 代码
相关推荐
愚公搬代码1 小时前
【愚公系列】《Web应用安全》005-Visual Studio Code编辑器的使用
前端·安全·编辑器
安逸sgr2 小时前
卷积神经网络 CNN 是什么?为什么适合处理图像?
人工智能·ai·大模型·agent·智能体
吴声子夜歌2 小时前
网络安全——消息认证
安全·web安全·消息认证
weixin_BYSJ19872 小时前
springboot技能与工具共享小程序---附源码29657
java·javascript·spring boot·python·小程序·django·php
茶本无香2 小时前
通用报表自动化框架:Java调用Shell传参执行PostgreSQL SQL模板
java·sql·postgresql·shell
张小姐的猫2 小时前
【Linux】网络编程 —— 传输层协议 TCP(下)
linux·运维·服务器·网络·tcp/ip·http·php
weixin_BYSJ19872 小时前
flask民族服饰饰品商城小程序---附源码37399
java·javascript·spring boot·python·小程序·django·php
m4Rk_3 小时前
【论文阅读】Agent 记忆机制(40):HiAgent——通过子目标级记忆提升长程任务执行能力
论文阅读·人工智能·学习·开源·github
CoderJia程序员甲3 小时前
GitHub 热榜项目 - 周榜(2026-08-16)
ai·大模型·llm·github