安全解析 Markdown 链接

4

我已经编写了一些代码来匹配和解析这种样式的Markdown链接:

[click to view a flower](http://www.yahoo.com/flower.html)

我有一个代码,旨在提取链接文本,然后提取url本身,并将它们粘贴到A HREF链接中。但我担心可能会有人通过注入XSS的方式来攻击,因为我留下了相当多的字符。这样做安全吗?

$pattern_square = '\[(.*?)\]';
$pattern_round  = "\((.*?)\)";

$pattern = "/".$pattern_square.$pattern_round."/";

preg_match($pattern, $input, $matches);
$words = $matches[1];
$url   = $matches[2];

$words = ereg_replace("[^-_@0-9a-zA-Z\.]", "", $words);
$url   = ereg_replace("[^-A-Za-z0-9+&@#/%?=~_|!:.]","",$url);

$final = "<a href='$url'>$words</a>";

看起来它工作得不错,它确实排除了一些愚蠢的URL,包括分号和反斜杠,但我并不关心这些URL。


5
ereg库已经过时多年了,你应该真正转换到preg。 - Wouter J
5
为什么不使用其中一种 PHP Markdown 解析器呢?已经有十几个这样的解析器可供选择了。 - user557846
1个回答

3
如果您已经通过htmlspecialchars转义输入内容(您一定要这样做,对吧?),那么链接中已经不可能包含任何可能导致XSS的字符。
如果您还没有通过htmlspecialchars转义输入内容,那么无论您在解析链接时进行了什么过滤,都已经很危险了,因为可以轻松地在链接之外包含任意HTML或XSS。
此函数将安全地解析文本中的Markdown链接,并对其应用htmlspecialchars
function doMarkdownLinks($s) {
    return preg_replace_callback('/\[(.*?)\]\((.*?)\)/', function ($matches) {
        return '<a href="' . $matches[2] . '">' . $matches[1] . '</a>';
    }, htmlspecialchars($s));
}

如果你需要做任何比这更复杂的事情,我建议你使用现有的解析器,因为用这种方法很容易犯错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接