跳转至

使用不存在的正则表达式捕获组

Gixy 检查 ID:invalid_regex

在 NGINX 指令(如 rewriteif 条件)中使用带有捕获组的正则表达式时,您可以在替换字符串或后续指令中使用 $1$2 等引用这些捕获的组。但是,如果您引用的捕获组在正则表达式模式中不存在,NGINX 会将其视为空字符串,这可能导致意外行为。

如何发现?

您应该检查: - rewrite 指令,其中替换字符串引用了正则表达式模式中不存在的捕获组(例如 $1$2) - if 块内的 set 指令,引用了 if 条件正则表达式模式中的捕获组 - 非捕获组如 (?:...) 或内联修饰符如 (?i),它们不会创建编号的捕获组

示例

示例 1:非捕获的内联修饰符

有问题的配置:

server {
    location / {
        # (?i) 是大小写不敏感标志,不是捕获组
        rewrite "(?i)/" $1 break;
    }
}

问题: 模式 (?i)/ 使用 (?i) 启用大小写不敏感匹配,但它不创建捕获组。$1 引用将为空。

修复:

server {
    location / {
        # 添加括号创建捕获组
        rewrite "(?i)/(.*)" /$1 break;
    }
}

示例 2:缺失捕获组

有问题的配置:

server {
    location / {
        rewrite "^/path" $1 redirect;
    }
}

问题: 模式 ^/path 没有捕获组,所以 $1 将为空。

修复:

server {
    location / {
        # 要么删除不必要的 $1 引用
        rewrite "^/path" /newpath redirect;
        # 要么在需要时添加捕获组
        rewrite "^/path/(.*)$" /newpath/$1 redirect;
    }
}

示例 3:引用错误的组号

有问题的配置:

server {
    location / {
        # 模式只有 1 个捕获组,但引用了 $2
        rewrite "^/(.*)$" /$1/$2 break;
    }
}

问题: 模式只有一个捕获组 (.*),但替换引用了 $1$2$2 将为空。

修复:

server {
    location / {
        # 如果需要,添加第二个捕获组
        rewrite "^/([^/]+)/(.*)$" /$2/$1 break;
        # 或删除无效引用
        rewrite "^/(.*)$" /prefix/$1 break;
    }
}

示例 4:if 块中的 Set

有问题的配置:

server {
    location / {
        if ($uri ~ "^/path") {
            set $x $1;  # $1 不存在
        }
    }
}

问题: if 条件中的正则表达式模式没有捕获组,所以 $1 是未定义的。

修复:

server {
    location / {
        if ($uri ~ "^/path/(.*)$") {
            set $x $1;  # 现在 $1 包含捕获的值
        }
    }
}

我能做什么?

  1. 在正则表达式模式中添加捕获组,如果您需要引用匹配字符串的部分
  2. 删除不必要的捕获组引用,如果您实际上不需要它们
  3. 使用正确的组号 — 记住组编号从 1 开始,NGINX 中没有 $0
  4. 记住非捕获组不创建引用 — 像 (?:...)(?i)(?=...) 这样的模式不创建编号组
  5. 测试您的正则表达式模式,确保它们捕获您期望的内容

加固 NGINX,使用维护的 RPM

使用 GetPageSpeed 提供的 NGINX Extras 在 RHEL/CentOS/Alma/Rocky 上获取持续更新的 NGINX 与模块。 了解更多.