I´m currently working on a code review of a friend and I found an XSS-Vulnerability I´d like to understand properly:
Lets say i I have a Variable foo.bar with the input <h1>test</h1>
I now figured out this pattern:
{{foo.bar}} -> no XSS
{% trans with { '%var%': foo.bar } %} My "%var%" {% endtrans %} -> XSS
{% trans with { '%var%': foo.bar | e('html') } %} My "%var%" {% endtrans %} -> no XSS
I thought I´ll run a Regex Pattern trough his whole code to find potential other places for bad encoding of HTML Character, but I did not quite understand when twig is encoding HTML tags and when not. I do understand the "e" (Encoding) function which decodes my variable value in html entities, but why is {{foo.bar}} encoding the characters while {% trans with ... is not?
I would search with this pattern for Coding mistakes in Twig:
Regex:
'\{%(.){0,2}[trans](.){0,2}[with].*'
-> Searching for "{%[space?]trans[space?] with"
as I guess everytime he missed the |e('html') there might be an issue. Am I on the right track? Do I miss something??
I hope i can find more clarification on this topic here :)
Twig always escapes but "trans with" is part of symfony and not twig. It is not autoescaped because it is passed to a tag, and the tag may output it but that is not a certainty so this is why they refuse to autoescape.
I personally always use the |trans() filter instead so by default you know you are safe, you can still ofcourse use |raw if needed.
https://symfony.com/doc/current/translation/templates.html
Using the translation tags or filters have the same effect, but with one subtle difference: automatic output escaping is only applied to translations using a filter. In other words, if you need to be sure that your translated message is not output escaped, you must apply the raw filter after the translation filter:
Related
I'm making a theme for Bolt (CMS) and it uses the Twig engine.
The website contains articles so I get an article's field like this {{ article.body }}
Now what I wanted to achieve was get the first letter of the body of the article and make it big and then display the rest of the article's body (without this first character) normally, you sometimes see this in books. I managed to do that and I successfully change the style of the first character.
However, using most functions that Twig offers in the documentation, I most often get a "<" as the first symbol as when typing the body of the article in the administration panel it automatically puts a <p> tag to the start.
Is there a way to overcome this?! I wouldn't want my client to have to delete the <p> tag every time. I thought there would be an easy way to get the body without any html in it or something else suitable for my use case.
The way it currently works beautifully:
<span class="firstcharacter">{{ article.body[:1] }}</span> {{ article.body[1:] }}</p>
but this relies on the article not starting with any html
There is a css pseudo-selector for first letter:
.firstcharacter::first-letter{font-size: 50px;}
Would this work for you?
You can use the striptags filter. As example:
{{ article.body| striptags [:1] }}
Here a working example
Hope this help
You shouldn't need to extract the first letter if you use CSS e.g.
Template:
<div class="dropcap">{{ article.body }}</div>
CSS:
div.dropcap p:first-of-type::first-letter {color: #f00;}
That will alter the first letter of the first paragraph.
Twig has the {% spaceless %} tag, which removes all the white space between HTML tags.
However, it does this with a preg_replace when you render the template. Fine on small files, but if you have a large complex template there's a performance hit.
I feel like it should be possible to strip the whitespace out at compile time?
My compiled template is full of stuff like
echo " <h2>Heading</h2>
";
Where the template has included the following:
<section>
<h2>Heading</h2>
</section>
What I want on the final rendered HTML is
<section><h2>Heading</h2></section>
Why couldn't twig (very simply) add a trim in when building the compiled template, to give us:
echo "<h2>Heading</h2>";
in the compiled template php code.
I get that there could still be whitespace in whatever data I populate the template with inside {{ }}, but I can control that from my PHP easily.
OK, after much digging in the library trying to work out which files generate which bits of the output, I've finally found this "fix".
Change
->string($this->getAttribute('data'))
to
->string(trim(preg_replace('/>\s+</', '><', $this->getAttribute('data'))))
On line 30 of /lib/Twig/Node/Text.php.
Doing that correctly gives me a "spaceless" output, but without requiring the expensive template-render-time preg_replace call.
Will it cause problems? Possibly in some use cases, maybe with a partial <pre> or <textarea> tag. I can't see either of those being an issue for me though.
Any gotchas that I've not thought of?
Try to use trim function from Twig library
trim - Documentation - Twig - The flexible, fast, and secure PHP template engine
The right tool for your needs if the spaces are in the template source is the whitespace control feature of Twig: http://twig.sensiolabs.org/doc/templates.html#whitespace-control
If the spaces are in a variable being displayed in the output, you should use the trim filter (or trim the variable before passing it to Twig, which will do the same anyway)
I started to use twig as template engine and I like it somehow.
The only thing I don't know how to disable it, is the optimized html that it renders (newest version of twig).
Twig seems to remove all unused white spaces and line breaks.
In Productive Mode it is quite useful if you have a page that should have a high rank in google.
But during Development it is not really usefull.
So my question: How do you disable this?
If you use the spaceless tag twig remove whitespace between HTML tags, not whitespace within HTML tags or whitespace in plain text:
{% spaceless %}
<div>
<strong>foo</strong>
</div>
{% endspaceless %}
output will be <div><strong>foo</strong></div>
For more information on whitespace control, read the dedicated section of the documentation and learn how you can also use the whitespace control modifier on your tags.
Your twig version is 1.18.1 ?
I've just discovered that my website (html/php) is vulnerable to XSS attacks.
Is there any way to sanitize my data besides manually adding htmlspecialchars to each individual variable that I send to the webpage (and proably missing a few thereby leaving it still open to attack)?
No, there is no shortcut. Data escaping always needs to happen on a case by case basis; not only with regards to HTML, but to any other textual format as well (SQL, JSON, CSV, whathaveyou). The "trick" is use tools which do not require you to think about this much and hence may allow you to "miss" something. If you're just echoing strings into other strings, you're working at the bare metal level and you do need a lot of conscious effort to escape everything. The generally accepted alternative is to use a templating language which implicitly escapes everything.
For example, Twig:
The PHP language is verbose and becomes ridiculously verbose when it
comes to output escaping:
<?php echo $var ?>
<?php echo htmlspecialchars($var, ENT_QUOTES, 'UTF-8') ?>
In comparison, Twig has a very concise syntax, which make
templates more readable:
{{ var }}
{{ var|escape }}
{{ var|e }} {# shortcut to escape a variable #}
To be on the safe side, you can enable automatic output escaping globally or for a block of code:
{% autoescape true %}
{{ var }}
{{ var|raw }} {# var won't be escaped #}
{{ var|escape }} {# var won't be doubled-escaped #}
{% endautoescape %}
This still lets you shoot yourself in the foot, but is a lot better.
One step up still is PHPTAL:
<div class="item" tal:repeat="value values">
<div class="title">
<span tal:condition="value/hasDate" tal:replace="value/getDate"/>
<a tal:attributes="href value/getUrl" tal:content="value/getTitle"/>
</div>
<div id="content" tal:content="value/getContent"/>
</div>
It requires you to write valid HTML simply to compile the template, and the template engine is fully aware of HTML-syntax and will process all user data at the level of a DOM, instead of a string soup. This relegates HTML to a pure serialisation format (which it should be anyway) which is produced by a serialiser whose only job it is to turn an object oriented data structure into text. There's no way to mess up that syntax through bad escaping.
I'm using someones PHP file.
And it has text like:
<html>
... regular HTML
{% if (some condition){
<another regular html tag>
</another regular html tag>
}%}
</html>
And I don't get it if these {% tags %} are javascript or PHP, or something else?
thx.
It is some templating language. Most likely a server-side one, i.e. one that is based on PHP.
Looks like a template to me. The {% and %} is the templating's system of identifying where it has to do its work.
It can think of two reasons:
User might have changed "<?" to "<%"
It is a template language