清理字符串以使其URL和文件名安全?

2022-08-30 06:53:25

我正在尝试提出一个函数,该函数可以很好地清理某些字符串,以便它们可以安全地在URL中使用(如post slug),也可以安全地用作文件名。例如,当有人上传文件时,我想确保从名称中删除所有危险字符。

到目前为止,我已经提出了以下功能,我希望它能解决这个问题,并允许国外UTF-8数据。

/**
 * Convert a string to the file/URL safe "slug" form
 *
 * @param string $string the string to clean
 * @param bool $is_filename TRUE will allow additional filename characters
 * @return string
 */
function sanitize($string = '', $is_filename = FALSE)
{
 // Replace all weird characters with dashes
 $string = preg_replace('/[^\w\-'. ($is_filename ? '~_\.' : ''). ']+/u', '-', $string);

 // Only allow one dash separator at a time (and make string lowercase)
 return mb_strtolower(preg_replace('/--+/u', '-', $string), 'UTF-8');
}

有没有人有任何棘手的样本数据,我可以针对此运行 - 或者知道一种更好的方法来保护我们的应用程序免受不良声誉的影响?

$is文件名允许一些额外的字符,如临时 vim 文件

更新:删除了星形字符,因为我想不出有效的用法


答案 1

我在Chyrp代码中发现了这个更大的函数:

/**
 * Function: sanitize
 * Returns a sanitized string, typically for URLs.
 *
 * Parameters:
 *     $string - The string to sanitize.
 *     $force_lowercase - Force the string to lowercase?
 *     $anal - If set to *true*, will remove all non-alphanumeric characters.
 */
function sanitize($string, $force_lowercase = true, $anal = false) {
    $strip = array("~", "`", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "=", "+", "[", "{", "]",
                   "}", "\\", "|", ";", ":", "\"", "'", "‘", "’", "“", "”", "–", "—",
                   "—", "–", ",", "<", ".", ">", "/", "?");
    $clean = trim(str_replace($strip, "", strip_tags($string)));
    $clean = preg_replace('/\s+/', "-", $clean);
    $clean = ($anal) ? preg_replace("/[^a-zA-Z0-9]/", "", $clean) : $clean ;
    return ($force_lowercase) ?
        (function_exists('mb_strtolower')) ?
            mb_strtolower($clean, 'UTF-8') :
            strtolower($clean) :
        $clean;
}

和这个在wordpress代码

/**
 * Sanitizes a filename replacing whitespace with dashes
 *
 * Removes special characters that are illegal in filenames on certain
 * operating systems and special characters requiring special escaping
 * to manipulate at the command line. Replaces spaces and consecutive
 * dashes with a single dash. Trim period, dash and underscore from beginning
 * and end of filename.
 *
 * @since 2.1.0
 *
 * @param string $filename The filename to be sanitized
 * @return string The sanitized filename
 */
function sanitize_file_name( $filename ) {
    $filename_raw = $filename;
    $special_chars = array("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}");
    $special_chars = apply_filters('sanitize_file_name_chars', $special_chars, $filename_raw);
    $filename = str_replace($special_chars, '', $filename);
    $filename = preg_replace('/[\s-]+/', '-', $filename);
    $filename = trim($filename, '.-_');
    return apply_filters('sanitize_file_name', $filename, $filename_raw);
}

2012 年 9 月更新

Alix Axel在这方面做了一些令人难以置信的工作。他的 phunction 框架包括几个很棒的文本过滤器和转换。


答案 2

关于解决方案的一些观察结果:

  1. 模式末尾的“u”表示模式,而不是它匹配的文本将被解释为 UTF-8(我假设你假设后者?)。
  2. \w 匹配下划线字符。您专门为文件包含它,这会导致假设您不希望它们在URL中,但是在代码中,您将被允许包含下划线。
  3. 包含“外部 UTF-8”似乎与区域设置相关。目前尚不清楚这是服务器还是客户端的区域设置。来自 PHP 文档:

“单词”字符是任何字母或数字或下划线字符,即可以作为Perl“单词”一部分的任何字符。字母和数字的定义由 PCRE 的字符表控制,如果进行特定于区域设置的匹配,则可能会有所不同。例如,在“fr”(法语)区域设置中,某些大于 128 的字符代码用于重音字母,这些字符代码由 \w 匹配。

创建数据块

您可能不应该在帖子中包含重音符号等字符,因为从技术上讲,它们应该是百分比编码的(根据URL编码规则),因此您将拥有看起来很丑陋的URL。

所以,如果我是你,在小写之后,我会将任何“特殊”字符转换为它们的等价物(例如é -> e),并将非[a-z]字符替换为“-”,限制为单个“-”的运行,就像你所做的那样。这里有一个转换特殊字符的实现:https://web.archive.org/web/20130208144021/http://neo22s.com/slug

一般消毒

OWASP具有其企业安全API的PHP实现,其中包括用于在应用程序中安全编码和解码输入和输出的方法。

编码器接口提供:

canonicalize (string $input, [bool $strict = true])
decodeFromBase64 (string $input)
decodeFromURL (string $input)
encodeForBase64 (string $input, [bool $wrap = false])
encodeForCSS (string $input)
encodeForHTML (string $input)
encodeForHTMLAttribute (string $input)
encodeForJavaScript (string $input)
encodeForOS (Codec $codec, string $input)
encodeForSQL (Codec $codec, string $input)
encodeForURL (string $input)
encodeForVBScript (string $input)
encodeForXML (string $input)
encodeForXMLAttribute (string $input)
encodeForXPath (string $input)

https://github.com/OWASP/PHP-ESAPI https://www.owasp.org/index.php/Category:OWASP_Enterprise_Security_API


推荐