Form being randomly submitted as GET instead of POST - html

This is kind of crazy.
Here's a form on our OpenID provider:
<form method="post" action="/affiliate/form/login/submit?affId=7" autocomplete="off">
<table class="position-table">
<tr>
<td class="input-td">
<input class="framed-text-field" type="text" name="email" id="email" value="" maxlength="100" />
<span class="form-help">name#example.com</span>
</td>
<td class="input-td">
<input class="framed-text-field" type="password" name="password" id="password" />
<span class="form-help">Password</span>
</td>
<td></td>
<td class="input-td">
<input type="submit" class="affiliate-button" value="Sign In" />
</td>
</tr>
</table>
<input type="hidden" id="fkey" name="fkey" value="REDACTED" />
</form>
This form is part of a page (at /affiliate/form/login) hosted in an iframe. The iframe is served over HTTPS, the host page over HTTP. You can see this in action at /users/login using an incognito/private-browsing/porn-mode browser window.
So here's the problem, periodically (but not consistently) a user will GET instead of POST to this url. This is an absurdly low occurrence, affecting less than 50 total users to date.
I'm tempted to just dev/null these errors (no action method etc. etc.), but...
These look like real users: wide spread of IPs, varied and valid user agents, and believable timings. Frustratingly, the same users sometimes successfully POST the same form just a bit later.
Any ideas what might be causing this?
Ideas I've had and discarded:
HTTPS accelerator or load balancer munging requests
checked incoming logs, they match what's getting to the app
ASP/.NET request parsing error
Compared incoming to logged Request values, they match
Buggy browser
Logged occurrences in multiple Chrome versions, FireFox 4, Safari, and Mobile Safari
Bots, or crummy browser extensions
Wide browser, IP, and OS spread.
My current best guess is that the ?affId=# in the action is tripping something (though not consistently, again). This is basically voodoo debugging, so I'd love a more authoritative explanation.
Update: Tried my voodoo fix (<input type="hidden" name="affId" value="#" /> and so on), and deployed. Haven't got a repro, so I'm just letting it bake.
We see a couple a day on average, so if this bakes for 2+ without issue I'll post it as the answer.
Second Update: Nope, still occurring. Much less frequently however. I'm gathering more data to see if there is any commonality in terms of browsers or operating systems.
Operating theory as to why removing ?affId=# from the action has reduced occurrence is buggy proxies in front of clients optimistically fetching "things that look safe to GET". This is a wild guess, so treat it with a grain of salt.
Third Update: More evidence for bogus proxies. Querying logs for affected IPs (over a much longer period of time), and many of them have much higher request rates than most unaffected ones. Its not 100% cut and dry, and I'm sure some frustrated refreshing is increasing the counts a tad but... its still a reasonable indicator (the difference is 5x or so the # of requests in the same period for the affected IPs).
At this point, I'm moving onto detecting the error has occurred and providing better error messages and guidance. Rather unenthusiastic about actually getting an authoritative answer, especially as that answer seems likely to lie in the realm of "code I don't control".

Some ad-blocking browser extensions like AdBlock Plus Popup addon 'probe' companion pages to determine their real URL before deciding whether to block them. Specifically, the aforementioned Popup addon does this with HEAD queries by default but can be set up to do GET queries.

Had a similar problem with Chrome users and the cause was if someone submits a form using shift+enter in google Chrome, browser will open new tab and make GET request with no parameters. Since people often have uppercase / special character as last character of a password, they press enter before releasing the shift and then GET request is issued.
I see that you mentioned Chrome first when enumerating browsers so if issue happens in Chrome more often, it's probably because of this reason.
While this is probably not the only issue you have, it probably contributes.

Make sure the source HTML is well formatted by running it through a validator.

Related

Multiple dynamic dataLists and chrome

Running chrome 58.0.3029.110 under Linux similar issue reported under windows.
Data List dynamic (provided through websocket).
When attempting to hit a page with multiple dataLists none of the dataLists fill in.
At the time I found local solution was to simply switch from person 1 to person 2.
Whilst this appears to fix the issue for me this isn't exactly advice I can start handing out to users who so wish to use my site.
I have spent a good few hours trying to locate where the issue is and have found if i have only 1 instance of datalist on that page and under the broken profile . (aka Person 1) the data list appears to work absolutely fine:
<input name="something" list="someresults"/>
<datalist id="someresults"></datalist>
Working fine, I can change above to any of the datalists on the page and all works correctly.
The moment I start using a second dataList on the same page:
<input name="something" list="someresults"/>
<datalist id="someresults"></datalist>
<input name="something2" list="someresults2"/>
<datalist id="someresults2"></datalist>
Neither of them will load the content, the arrow fills up to say content, having a look within html the DOM has been updated with the user input matching results.
Just scratching my head as to what on earth can cause this its obviously not the code since as i say by changing chrome profiles the issue goes away.
Any insight / fix information will be much appreciated
PS process is rather complex if required I can create a few demo pages on the live site to show the problem at hand since I think the actual workings too complex to post all on here
In this case it turned out to be due to two things, maybe my own summary helped narrow it down a lot quicker.
Disable the main form : (if used in main form remove it)
autocomplete="off"
Disable the same tag used in any dataList inputs: (remove tag)
autocomplete="off"
Please note with single dataList and autocomplete="off" on a given field was workng fine.
(really strange)

Can hidden fields be edited by the user?

adding in security questions so that users may reset their passwords if they exceed maximum attempts. is it bad to do hidden fields such as these for authentication mechanism?
<input type="hidden" name="securityAnswered" value=true>
<input type="hidden" name="exceededAttempts" value=true>
could a user go in and edit these hidden fields from the client side?
could a user go in and edit these hidden fields from the client side?
Of course! Anything on the client side can be edited. You cannot stop users from doing that.
You have to keep in mind that the client can post to the server any content, any time.
yes of course , any one can change it by clicking in ctrl+maj+i
Yes, penetration testers do this all the time using intercepting proxies such as Burp or Zap.
https://portswigger.net/burp/proxy.html
https://www.owasp.org/index.php/OWASP_Zed_Attack_Proxy_Project
There are many other ways of modifying such data, including developer tools in the browser.

Input Type Password Security Benefits During Account Creation

What are the benefits (if any) of using type="password" vs. type="text" when creating a form for account creation on a website? Besides a create and confirm, is there a defined best practice?
The obvious reason is, that you can type the password, even if other people are watching the screen. Often i have this situation when i publish my desktop in a presentation, or if i need to give support to other users.
Besides hiding of the characters, the browser (or desktop application) will also prevent copying the content from the password box. This is one possibility less for other applications to misuse the passwords.
I might me wrong but as far as i know the only benefit of using type="password" is that another person can't see what you're typing. But the value behind that is transfered in plain text if you dont use https.
If you use the password type, the text will be hidden by black dots (or * or .) whilst text entries are displayed in plain text.
Also, if you're using forms with passwords, make sure to use HTTP POST as opposed to HTTP GET. Because on the latter, the entries are visible in plain text inside the options section of the URL (see the difference between HTTP GET and HTTP POST there: http://www.w3schools.com/tags/ref_httpmethods.asp).
You can do that by specifying method="post" as an attribute of the <form> tag.

Is it safe to use type="text" for password field?

I've researched it and cannot find a standard, dependable way to make a browser prevent autofill and not remember the password in a standard login form.
This is important to me as I'm working on a mobile web app, so if the user clicks logout and someone else gets hold of their phone, the browser shouldn't help them out by just handing them the password!
The only solution I can come up with is to make the password field type="text".
Sure, this would mean people can 'shoulder surf' and see what the user is typing in, but that same person could almost as easily just watch the user's fingers to see what password they're typing in...
I don't think spyware is a real issue here either, as I don't think a type="password" character mask is going to stop a malicious keylogger, etc. from doing its stuff.
So, I'm wondering if there are any other security concerns that I may have missed for using type="text" for a password field?
Maybe if I combined this idea with a dynamic/random 'name' attribute for the input, could I be onto a winner?
NB - The solution needs to be compliant with XHTML Mobile Profile.
Also, please refrain from advising me on what is semantically correct here. My priority is security, not semantics. :)
Bad idea - The browser will remember text fields, it just wont enter them automatically as it does with passwords. Instead it will suggest the password as an autocomplete for all to see. I also think reading a password over someones shoulder is much easier than reading their keystrokes.
The reason some browsers dont respect the autocomplete option for passwords is probably because passwords are handled by a separate (in theory more secure) method for handling/storing password data - obviously by using a text field you are bypassing this system with whatever risks that entails.
I dont think there is a definitive solution that doesnt involve js, since at the end of the day you have no real control over what their browser remembers. You can only provide hints and suggestions. Which will be handled in different ways by different browsers. Your best bet is to start by adding :
autocomplete="off"
to your form and input. Works in most browsers - but not all.
The above would go in your form tag and your password input tag, something like:
<form id="form1_randomstring" name="form1" method="post" action="process.php" autocomplete="off">
<input name="password_randomstring" type="password" value="">
As you said in your question, randomizing the form and input names will also trick some browsers into thinking it is dealing with a different form
Also, browser will be extra conservative about what they remember if you use ssl. So this may help.
Finally, as another layer of protection you could have a little onload jquery to clear the form field manually on docready:
$("input[type='password']").val('');
Obviously no help if not running js.
The Definitive solution (maybe?)
You could go a step further and inject the form field using an ajax call (plus generating the random form names + autocomplete and serving the page through ssl). Meaning js would be a requirement for logon but you could then make sure the field was clear and generate the form after page load. I would challenge any browser to complete it then.
If you went for that option both the outer page and the ajax loaded page would have to run through ssl - If you didnt want this an alternative might be to load the ssl form through an iframe (again trade-offs -user base would need to be considered.)
Depending on your requirements and userbase, this could present the most guaranteed option.
NOTE
Autocomplete="off" may not pass strict XHTML validation. An option then may be to add the autocomplete attribute after page load with jquery (again, obviously this wont work without js enabled):
$('#form1').attr('autocomplete', 'off');
As an added point, The simplest way to prevent a key logger would be to provide a select option drop down box and ask them to enter a letter/number from their password. Practically speaking you would have to limit passwords to alphanumeric and ask the user to enter at least three letters/numbers from their password in a series of drop downs.
Summary
No perfect solution but lots of options, you'll have to consider what is right for you. I would maybe go for the ajax call as the main method. You could initially load a link to the form and dynamically replace it with the ajax content so that there is still an option for non js users (less users compromised by autocomplete)

Remember user input from other website

A registration webpage impressed me by knowing all my name, address, email, telephone number.
This is the first time i visit this website.
I guess that it might remember from other website with same id or name such as id="firstname"
id ="telephone" but i don't know exactly what is going on. How to implement this ?
Edit - Add more information.
I have done nothing, value is just appeared as page load.
This is what i got from view source.
<div class="ui-form-field" id="ohfirstNameField">
<input class="ui-form-field-text ui-corner-all" name="ohfirstName" maxlength="4000" type="text" id="ohfirstName" required="required" value="Sarawut" />
</div>
I have seen that before as well, and here is my theory. I believe the browser is storing basic information for you. A separate website cannot read any cookies not generated by itself (that would be a huge security issue), so that can't be it.
I think it is just a few fields that the browser stores. How to get at them, I am not sure. Is this Google Chrome you're talking about?
You could use OpenId to get a similar effect. The user will be asked, if he allows the authenticating site to his data, but if admits it, you will be able to prefill your form with data from the user.