Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么Jinja nl2br过滤器会溢出<;br>';s但不是<;p>';s_Python_Regex_Flask_Jinja2 - Fatal编程技术网

Python 为什么Jinja nl2br过滤器会溢出<;br>';s但不是<;p>';s

Python 为什么Jinja nl2br过滤器会溢出<;br>';s但不是<;p>';s,python,regex,flask,jinja2,Python,Regex,Flask,Jinja2,我正在尝试实现Jinjanl2br过滤器。它工作正常,只是它添加的正在转义。这对我来说很奇怪,因为没有被转义,它们都在同一个字符串中 我正在使用flask,因此Jinjaautoescape已启用。当我发现说autoescape和escape(value)可能会导致双重转义时,我真的很有希望,但是删除escape()没有帮助 这是我修改过的代码及其输出: @app.template_filter() @evalcontextfilter def nl2br(eval_ctx, value):

我正在尝试实现Jinja
nl2br
过滤器。它工作正常,只是它添加的

正在转义。这对我来说很奇怪,因为
没有被转义,它们都在同一个字符串中

我正在使用flask,因此Jinja
autoescape
已启用。当我发现说
autoescape
escape(value)
可能会导致双重转义时,我真的很有希望,但是删除
escape()
没有帮助

这是我修改过的代码及其输出:

@app.template_filter()
@evalcontextfilter
def nl2br(eval_ctx, value):
    _paragraph_re = re.compile(r'(?:\r\n|\r(?!\n)|\n){2,}')
    result = u'\n\n'.join(u'<p>%s</p>' % escape(p.replace(u'\r\n', u'<br>\n')) for p in _paragraph_re.split(value))
    if eval_ctx.autoescape:
        result = Markup(result)
    return result
输出:

<p>1&lt;br&gt;
2</p>

<p>3&lt;br&gt;
4</p>

<p>5&lt;br&gt;
6&lt;br&gt;
7</p>
1br
二,

3br 四,

5br 6br 七,

期望输出:

<p>1<br>2</p>

<p>3<br>4</p>

<p>5<br>6<br>7</p>
1
2

3
4

5
6
7


是什么原因导致

被转义,但允许
转义?

您是否在移除转义后尝试过?因为下面的方法对我有用吗

@app.template_filter()
@evalcontextfilter
def nl2br(eval_ctx, value):
   _paragraph_re = re.compile(r'(?:\r\n|\r(?!\n)|\n){2,}')
   result = u'\n\n'.join(u'<p>%s</p>' % p.replace(u'\r\n', u'<br/>') for p in _paragraph_re.split(value))
   if eval_ctx.autoescape:
       result = Markup(result)
   return result
给我下面的输出

<p>1<br/>2</p>

<p>3<br/>4</p>

<p>5<br/>6<br/>7</p>
1
2

3
4

5
6
7


nl2br
筛选器无法正确处理标记对象。如果
value
是标记,则插入的

标记将被转义。要修复它,

标记也必须是标记:

@app.template_filter()
@evalcontextfilter
def nl2br(eval_ctx, value):
    _paragraph_re = re.compile(r'(?:\r\n|\r(?!\n)|\n){2,}')
    result = u'\n\n'.join(u'<p>%s</p>' % p.replace(u'\n', Markup('<br>\n'))
                                         for p in _paragraph_re.split(value))
    if eval_ctx.autoescape:
        result = Markup(result)
    return result
根据:

标记字符串上的操作是标记感知的,这意味着所有参数都通过escape()函数传递

回顾
nl2br
的主要转换,我们可以看到发生了什么以及为什么它不起作用:

result = u'\n\n'.join(u'<p>%s</p>' % p.replace(u'\n', u'<br>\n')
                                     for p in _paragraph_re.split(value))
result=u'\n\n.加入(u'%s

'%p.replace(u'\n',u'
\n')) 对于段落中的p,关于拆分(值))
u'\n\n'
u'
\n'
是unicode字符串,但
p
Markup
已从作为标记对象的
值中拆分出来
p.replace
尝试将unicode字符串添加到标记对象
p
,但标记对象首先正确截取并转义该字符串


标记不会转义,因为Python是如何组合最终字符串的,因为对unicode字符串调用了
%
格式化方法,所以它使用传递给它的元素的unicode表示形式。标记元素已经被声明为安全的,因此它们不再被转义<代码>结果
以unicode字符串结束。

在我写这篇文章时,这里的其他两个答案不会转义

标记,但它们容易受到XSS攻击。使用以下输入字符串进行测试:

';alert(String.fromCharCode(88,83,83))//';alert(String.fromCharCode(88,83,83))//";
alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//--
></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>

您认为转义是不必要的,这是对的,但是如果传入的值是标记对象,那么转义就不起作用。标记文字是unicode字符串,不受标记转义函数的约束。我认为这容易受到XSS的攻击。我通过注入
”来测试它;警报(String.fromCharCode(88,83,83))/';警报(String.fromCharCode(88,83,83))/“警报(String.fromCharCode(88,83,83))/”;alert(String.fromCharCode(88,83,83))/->“>”>alert(String.fromCharCode(88,83,83))
我认为这容易受到XSS的攻击。我通过注入
';alert(String.fromCharCode(88,83,83))/';alert(String.fromCharCode(88,83,83))对其进行了测试/‌​/"; 警报(String.fromCharCode(88,83,83))/“;alert(String.fromCharCode(88,83,83))/-->“>”>alert(String.fromCharCode(88,83,83))
-1;正如@DavidXia所指出的,如果你做
{{一些用户提供的数据{nl2br}
,这会造成一个巨大的XSS漏洞。你不需要做任何像他在评论中显示的那样复杂的事情;我只是试着做
{{alert(1)}nl2br}
在一个模板中,当我刷新页面时,我确实看到了一个警报。这真的非常令人伤心,因为他改编的内容实际上是正确的。值得一提的是,演示其他两个答案中的XSS漏洞并不需要像您在这里测试的那样复杂的测试字符串。其他两个答案最终都是正确的t将
格式化为普通字符串,然后将其传递给
标记()
构造函数(因此错误),而不进行任何转义。
警报('pwned')
足以表明它们已损坏。请注意,虽然这修复了逃逸的错误,但将正则表达式从OP的调整版本更改回文档片段的原始版本会在处理文档中版本的Windows样式新行时重新引入错误。有关更多说明,请参阅。此文件的正常工作版本ter应将
'
\n'
字符串包装在
标记()
中,如图所示,并另外使用问题中所示的固定正则表达式,并在Alan Moore的回答中解释。
>>> Markup("hello there").split()
[Markup(u'hello'), Markup(u'there')]
result = u'\n\n'.join(u'<p>%s</p>' % p.replace(u'\n', u'<br>\n')
                                     for p in _paragraph_re.split(value))
';alert(String.fromCharCode(88,83,83))//';alert(String.fromCharCode(88,83,83))//";
alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//--
></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>
import re

from jinja2 import evalcontextfilter, Markup, escape

_paragraph_re = re.compile(r'(?:\r\n|\r|\n){2,}')

app = Flask(__name__)

@app.template_filter()
@evalcontextfilter
def nl2br(eval_ctx, value):
    result = u'\n\n'.join(u'<p>%s</p>' % p.replace('\n', '<br>\n') \
        for p in _paragraph_re.split(escape(value)))
    if eval_ctx.autoescape:
        result = Markup(result)
    return result
result = u'\n\n'.join(u'<p>%s</p>' % p.replace('\n', Markup('<br/>\n')) \
    for p in _paragraph_re.split(escape(value)))