How to not allow browser to store previous values in flask-form StringField? - flask

After submitting my flaskapp form to make a new response, there is appears a 'quick-suggested' form contains previous input values. How can I restrict appearing this? In fact, I don't understand where it comes from and where it's stores so can't make a relevant ask to google. Dont be sarcastic - it was surprisingly for me, that it's disappear when I try to make this image with scissors!
it's all about that
P.S. all happens in google chrome

Your "google term" would be form autocomplete. This is a feature of your browser not flask or any web framework.
You can ask the browser to not autocomplete a form.
<form ... autocomplete="off">
or an individual field
<input type="text" autocomplete="off">
Keep in mind that the browser doesn't have to respect your wishes. Specifically in the case of login fields where browsers will autofill usernames and passwords regardless of autocomplete="off".

Related

amp-form session based backend and 3rd party cookies

Trying to grok this e-commerce scenario...
I build an amp product page in amp that has the new amp-form
The add to cart button is an XHR to my backend (that is session based, using
cookies by default)
User searches for product and results take them
to my amp product page, but they've never been to my site
They submit the add to cart form
the CORS preflight makes it's way to my backend, and i set all the correct allows as per https://github.com/ampproject/amphtml/blob/master/spec/amp-cors-requests.md
Now the actual request is made... backend initializes a session,
returns session identifier as a cookie, but since user never went to
my site...just the google amp cache it's treated as a 3rd party
cookie and browser discards it (cause user disables 3rd party cookies)
users session is lost, as is their add to cart action
So the question is, how do i keep the session around and the item in the cart?
Am i missing something? is there a trick i'm not seeing?
appreciate any insights.
Associating the shopping cart with the CLIENT_ID would be the best way to solve this problem. Unfortunately, transferring the CLIENT_ID via forms is not yet supported in AMP. It's currently being implemented, you can watch this issue for the current status.
Here is an approach that works right now: the idea is to encode the shopping cart content into a string that is returned in the form result. This way we can generate "View Cart" and "Checkout" links including the shopping cart content. Once the user clicks on one of those links, you can create the actual shopping cart in your backend and store the user id in a cookie.
For example:
<form action-xhr="/add-to-cart" method="POST">
<input type="hidden" name="itemId" value="headphones-123">
<!-- Hide after form submit success -->
<input type="submit" name="add" value="Add to Cart">
<div submit-success>
<template type="amp-mustache">
<!-- shopping cart contents, e.g headphones-123 -->
{#shoppingCartContent}
View In Cart
Checkout
{/shoppingCartContent}
</template>
</div>
<div submit-error>
<template type="amp-mustache">
{{message}} <!-- e.g. Only 2 Headphones are left. -->
</template>
</div>
</form>
The disadvantage of this approach is that the shopping cart will be lost when the user leaves the page without viewing the cart first. This will be solved once the CLIENT_ID can be passed via amp-form.
I also know very limited info about AMP pages but I suggest that you please read through the use of User identification and try using an AMP-generated client ID. As mentioned in the documentation:
By default, AMP will manage the provision of a client ID whether the page is accessed from the publisher's original website or through a cache.
Likewise, learn more about client ID substitution, including how to add an optional user notification ID, in Variables supported in AMP analytics.
Hope that helps!

Django redirect page does not update the view

I'm using the Django Framework on Google App Engine.
I have multiple forms on the same view, to submit to different URL.
Trouble is after I get a form submitted: even if the called method update the datastore and some data, the previous page (where the forms are put in) is not refreshed, showing the updated data.
I could solve this problem using jQuery or some javascrip framework, appending dinamically content returned by the server but, how to avoid it?
Suggestions?
Am I wrong somewhere?
A part of "secure.html" template
<form action="/addMatch" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
Matches:
<br />
{% for m in matches%}
{{m.description}} ---> {{m.reward}}
{% endfor%}
the "/addMatch" URL view:
def addMatch(request):
form = MatchForm(request.POST)
if form.is_valid():
user = User.all().filter('facebookId =', int(request.session["pbusr"]))
m = Match(user=user.get(),description =form.cleaned_data["description"],reward=form.cleaned_data["reward"])
m.save()
return HttpResponseRedirect("/secure/")
else:
logging.info("Not valid")
return HttpResponseRedirect("/secure")
The view method whose seems not working:
#auth_check_is_admin
def secure(request):
model={}
user = User.all().filter('facebookId =', int(request.session["pbusr"]))
u = user.get()
if (u.facebookFanPageId is not None and not u.facebookFanPageId == ""):
model["fanPageName"] = u.facebookFanPageName
model["form"] = MatchForm()
model["matches"] = u.matches
else:
....
return render(request,"secure.html",model)
Francesco
Based on what you posted, it seems like you're redirecting properly and are having database consistency issues. One way to test this would be to look at the network tab in the Google Chrome developer tools:
Click on the menu icon in the upper right
Click on "Tools"
Click on "Developer Tools"
Click on "Network" in the thing that opened up at the bottom of the screen.
Now, there will be a new entry in the network tab for every request that your browser sends and every response it receives. If you click on a request, you can see the data that was sent and received. If you need to see requests across different pages, you might want to check the "Preserve log" box.
With the network tab open, go to your page and submit the form. By looking at the network tab, you should be able to tell whether or not your browser issued a new GET request to the same URL. If there is a new request for the same page but that request has the old content, then you have a datastore consistency issue. If there was NOT a new request that yielded a response with the data for the page, then you have a redirect issue.
If it turns out that you have a datastore consistency issue, then what's happening is the data is being stored, but the next request for that data might still get the old data. To make sure that doesn't happen, you need what's called "strong consistency."
In a normal App Engine project, you get strong consistency by putting entities in the same entity-group and using ancestor queries. I'm not certain of what database/datastore you're using for Django and how the different database layers interact with App Engine's consistency, so this could be wrong, but if you can give your users the right key and then fetch them from that key directly (rather than getting all users and filtering them by key), you might get strong consistency.

Form action and its usage in Django

First Quesiton:
This form submits to demo_form?name=ABC
<form action="demo_form" method="get">
name: <input type="text" name="name"><br>
<input type="submit" value="Submit">
</form>
Is there a way to make it submit to demo_form/ABC/?
Second Question:
Even if users don't use my form, if they use a web crawler to simply visit demo_form?name=ABC or demo_form/ABC/, it would yield the same result. I want to prevent that. What's the best way of making those two URLs only valid if the user submit the name via my form? I am learning django so hopefully the solution would work with django framework.
Thanks in advance!
Is there a way to make it submit to demo_form/ABC/?
You could intercept the submission in JavaScript, construct the URL manually, then set location. That would break if JS wasn't available.
More sanely, you could send an HTTP 301 redirect response when you get the request for demo_form?name=ABC
What's the best way of making those two URLs only valid if the user submit the name via my form?
Generally speaking, visiting a form should not be a pre-requisite for anything involving a GET request. A large portion of the point of GET is that the results are bookmarkable, linkable, etc.
It would be more understandable if it was a POST request, as those are intended to change data on the server and you will want to protect against CSFR. The standard protection against CSRF is a token stored in the form and in a cookie

Cross Site Scripting with Hidden Inputs

My company gave me the task of resolving all security issues with a particular application. The security tream reported a cross site scripting error. The error lies in the following input field:
<input type="hidden" name="eventId" value="${param.eventId}"/>
The report from security wasn't very detailed, but the say they can make a POST request to the page that has the above tag including the following malicious code:
eventId=%22%3e%3csCrIpT%3ealert(83676)%3c%2fsCrIpT%3e
And that when the page reloads, it will have the following:
<input type="hidden" name="eventId" value=""><sCrIpt>alert(83676)</sCrIpt></value>
I am trying to "be the hacker" and show the vulnerability. But I can't figure out how they manage to get that script in there. I am guessing they include it as a URL parameter in the GET request for the form, but when I try to do it myself I get a 403 error. Does anyone know how the vulnerability can be shown?
I know there is a number of XSS questions on the site, but none seem to hit this topic.
So, I am not sure why, but my original hunch was correct. The script can be put on as a URL parameter. For some reason though, this was not working with our staging site. Only with running the application locally. I am not sure why, but this works (only locally):
http://localhost:8080/myUrl/MyAction.do?eventId=%22%3e%3csCrIpT%3ealert(83676)%3c%2fsCrIpT%3e
Doing that, you see an alert box pop up. I am planning to fix it using JSTL functions.
<%# taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
...
<input type="hidden" name="eventId" value="${fn:escapeXml(param.eventId)}"/>
Install [TamperData][1] add-on in firefox browser which let you edit the data before submitting. Doesn't matter if it's in POST or GET.
By using this hidden fields can be edited.
What you want to do to fix the problem, is to HTMLAttributeEncode the value before putting it inside the value-attribute. See OWASP ESAPI or MS AntiXSS for methods for doing HTML attribute encoding.
Seeing how the attack string is URL encoding, I think you guess about including it as a GET parameter seems reasonable.
I used the OWASP ESAPI API as the legacy jsp's didn't have JSTL available. This is what I used:
<input type="hidden" name="dataValue" value="<%=ESAPI.encoder().encodeForHTMLAttribute(dataValue)%>">
You can also use the API to filter request.Parameter() which I also needed, as in:
String userURL = request.getParameter( "userURL" )
boolean isValidURL = ESAPI.validator().isValidInput("URLContext", userURL, "URL", 255, false);
if (isValidURL) {
link
}
and:
String name = (String) request.getParameter("name");
name = ESAPI.validator().getValidInput("name ", name , "SafeString", 35, true);

Prevent XSS in HTML forms from third party site

The basics:
I have a contact form that uses
php to validate the
forms. (in addition to client side) This could be done in any server side language though.
The server side only allows
A-z 0-9 for certain fields (it is
acceptable to validate this field to
English only with that extremely limited range)
If the form contains errors, I repopulate the fields so the user doesn't have to retype before submitting again
I am willing to not let other sites post to my form, even if legitimate use could be found there.
I can easily make a form on a different web site that posts a dirty word to a field. Certain dirty words are perfectly legit according to the validation rules, but my employeer obviously wouldn't like that to happen.
I am under the impression that dedicated hackers can affect cookies, php sessions and of course hidden fields are easy to spoof along with referrers and such. How can I block third party sites from posting to my page?
Please feel free to help me Google for this too. My search terms are weak and bringing up methods I know will fail.
What if somebody submits "d03boy eats cats" via a form on their site and gets people to click a link that submits it to my form? (Admit it is possible, and my company cannot accept any risk) Then when a user clicks the link they see inside the "name" field "d03boy eats cats" and gets super offended and contacts PETA about our site's content. We just cannot explain to the user what happened. True, nothing happened, but upsetting a single users isn't acceptable to my employer.
Our current solution is to not report any user input, which in my opinion is a big usability issue.
This sounds like you need a moderation system in place for user generated content, not a technical solution. Obviously you can check the referrer field, content scrub and attempt to filter the profane, but enumerating badness never works. (It can be an acceptable "first pass", but humans are infinitely resourceful in avoiding such filters).
Put the user submitted content into a queue and have moderators review and approve content. To lighten the load, you can set trusted users to "pre approved", but you have said your client can't accept any risk.
Frankly, I find that impossible: even with moderators there is the risk that a moderator will subvert your system. If that is actually true (that they have zero risk tolerance) then I suggest they not accept any user input, don't trust moderators and in fact eliminate the site itself (because an insider could go rogue and put something improper up). Clearly every act has risk; you need to find out how much they can accept, such as a moderator based approval queue.
I'm not sure I entirely understand your question but I'll do my best to give you a basic answer.
Cross Site Scripting (XSS) happens generally when someone else puts in HTML into your forms. Your website allows this to happen because it isn't escaping the HTML properly. If you use PHP you probably want to make use of the htmlentities($str, ENT_QUOTES) function.
htmlentities($str, ENT_QUOTES)
PHP htmlentities
My attempt
...
<?
$form_token = "";
$token = "";
$encoded_token = "";
$salt = "ThiséèÞ....$ÖyiìeéèÞ"; //it is 70 characters long
...
...
$blnGoodToken = false;
...
...
//Check for the encoded token
session_start();
$encoded_token = GetSuper('POST', 'TOKEN');
if (isset($_SESSION['TOKEN'])) {
if (sha1($_SESSION['TOKEN'] + $salt) === $encoded_token) {
$blnGoodToken = true;
//echo "Good Token";
}
else {
//echo "Bad Token";
$blnGoodToken = false;
unset($_SESSION);
session_unset();
session_destroy();
session_start();
}
}
else {
$blnDoit = false;
echo "No Token, possible no session";
}
$token = uniqid(rand(), TRUE);
$_SESSION['TOKEN'] = $token;
$form_token = sha1($token + $salt);
...
...
?>
...
...
<form action="request.php?doit=y" method="post">
<input type="text" name="TOKEN" id="TOKEN" value="<?=$form_token?>" />
<!--
form stuff
-->
<input type="reset" value="Clear" />
<input type="submit" value="Submit" />
</form>
Since I don't use sessions anywhere else on the site, I don't think we are exposed much to session hijacking. The token changes each load, and to get the token to match the session you would have to know
I am using SHA. An easy guess to
make on my php code
I keep it in the session. I suppose
the session is gettable
My salt. I think this is a good
secret. If they know my salt they already
owned my server