Manual CSRF Verification - python

I have a e-commerce Django application that automatically verifies all incoming POST requests with CSRF token using the CSRFViewMiddleware.
Now, for payments, I'm using a payment gateway where I pass the relevant details along with the csrfmiddlewaretoken so that it is returned back to me when the transaction on 3rd party site is complete. So, when the user is re-directed back to my site, I get a
403 Forbidden
CSRF verification failed. Request aborted.
How do I fix this? Is there any way I can manually check csrftoken using request.POST.get('csrfmiddlewaretoken') or something like that.
I would prefer not to bypass csrf totally as I want it to be secure (atleast, as much as possible).
Edit I understand csrfmiddleware token needs to be passed in the header but I cannot do that as there are only limited things I can do with a 3rd party payment gateway.

From this snippet, I get a feeling that you may not quite understand what is CSRF:
I have a e-commerce Django application that automatically verifies all
incoming POST requests with CSRF token using the CSRFViewMiddleware.
That's part your problem right there. CSRF is only for those requests that are made from your site, to your site (see OWASP's definition of CSRF):
Cross-Site Request Forgery (CSRF) is a type of attack that occurs when
a malicious Web site, email, blog, instant message, or program causes
a user’s Web browser to perform an unwanted action on a trusted site
for which the user is currently authenticated.
You need CSRF tokens only on those forms that are generated by your site, and post to your site. In addition, any javascript code that sends a POST request should also be properly protected.
For all other end points - for example, if some payment provider is posting the result back to your application - you do not want to enable CSRF protection otherwise the requests will continue to fail.

Related

How to redirect cognito login to website that requires authentication?

What I'm trying to do is create a seamless transition where you login to cognito and one way or another you get redirected to your API Gateway resource that requires cognito token authorization automatically.
my understanding of how to solve this problem:
you login to cognito and are redirected to a public API Gateway endpoint that is a lambda function. The lambda function takes the code that cognito passed as a header and uses that to generate a token. Next I want it to redirect to my website that requires cognito authentication and be logged in.
I'm not even quite sure if this approach is the appropriate one to take but I'm struggling to find resources out there explaining how you go about this.
one more questions that might help me understand the problem better:
Are headers held by your current session when you redirect to another link? I ask this because I thought (or atleast this is what I've seen in the youtube tutorials I've watched) that authentication is essentially JUST a header. If you have a valid header token="long random key" then you're authenticated. You want this header to stay in your session when you hop around your website right?
Can you redirect to a different url from lambda and hold onto your headers? Cause this is essentially what I'm trying to do.
Also I highlight the word automatically because every single youtube video I've seen shows them saying oh just change the word code in the login url to token like this: "https://domain123.auth.us-west-2.amazoncognito.com/login?client_id=19shq1tf1n1&response_type=token&scope=aws.cognito.signin.user.admin+email+openid+phone+profile&redirect_uri=https://actuallywebsiteIwanttogoto.com"
but then the problem is that it gives the access_token in the hash of the url when you login successfully. These people showing how to use cognito are manually extracting the access_token from the url and calling a get request on there demo website with the access_token as a header manually. I wanna know how to automate this!!!

How to login by oauth to third party app with python

I am having trouble authenticating against a web service that has Oauth provided by google.
Basically, I want to login with my google account to a web page to do some scraping on it.
As the web service is not mine, I don't have the app secret_key, only the clientID, redirect_URL and scope that I could recover from seeing the parameters of request method used while being logged in.
Once authenticated, the web page only requieres a cookie named SID (Session ID I would guess) to answer back as an authenticated user. There is no Bearer token, just the SID cookie.
Is it possible to automate this type of authentication? I've read many topics related but they all need the secret_key which I don't have because I'm not the owner of the app.
(Cannot comment due to rep)
Yes, what you're asking is possible. You could theoretically follow and match all the requests to authenticate yourself successfully to get the SID and perform scraping, albeit this would be a very difficult task for some basic web-scraping, it's like programming a full-blown scientific calculator to do 5 + 5. What you are asking is a really difficult task, you're going to run into all sorts of security issues and be asked for phone/authenticator app/email verification when attempting to login to your account with Python requests and then you'd need to keep track of those security cookies and keeping them updated, it's a real mess and would be extremely difficult for anyone.
I think the better method would be to manually authenticate yourself and get the SID cookie and hard-code that into your scraper within the cookie HTTP header.
I understand this brings up the concern of what to do when the SID cookie expires. Since you haven't said the site, It would be hard for me to imagine a site that makes you authenticate yourself with Google often rather than having their own internal SID/JWT refreshing system to keep you logged in.
My recommendations would be:
Check the expiration of the SID cookie, if it's viable to manually copy-and-paste it after authenticating yourself, do that.
If the SIDs expire soon, check if there's an API request anywhere to get yourself a new SID (Without going through the OAuth again), in your Network panel look for the set-cookie response header setting a new SID, you might need to change and keep track of these inside your program but it'll be much easier than writing a program to login to Google.
If there's no way to refresh the SID and they expire often and you need to do long-term web scraping and sitting there getting a new cookie manually every 30 minutes isn't enough, I'd recommend looking into doing this with Puppeteer/Chromium as it'll be much easier than doing it via Python HTTP requests.

What are some examples where programmers might want to use csrf_exempt?

By default, Django offers protection against Cross-Site Request Forgery (CSRF) attacks by sending a CSRF token to webpages it generates, which is then sent back with requests to validate them. This is detailed here.
Django provides the csrf_exempt decorator to disable this behaviour. What are some good reasons programmers might want to use it?
This details why it could be dangerous, I'm interested in how it could be useful.
I'm looking for answers that are not obvious (e.g. not knowing how to use the CSRF protection or disabling it temporarily).
For instance, we use it for an interface where another party posts data programmatically. Thus, they can never get a csrf token. The page is, however, basic-auth secured.
Project I am working on has tiny embedded devices talking HTTP to a django application server over a VPN. The HTTP client on these is very primitive, so we disable CSRF.
Whenever your client sends a request to the server, some confidential information will be send along with the request. The CSRF token prevents a malicious site from abusing that information. Particularly, this prevents a malicious site from sending a forged request that uses your cookies and/or session to authenticate your client and authorize the action. Any information that is automatically and implicitly send on every request by your client is vulnerable to a CSRF attack (though not all information might actually be useful in such an attack).
The #csrf_exempt decorator can safely be used to avoid the CSRF protection mechanism if and only if the server-side actions that are the result from the request do not depend on the authentication and authorization that is sent implicitly by the client. Examples are token-based authentication and HTTP Basic authentication. For these forms of authentication, the client must explicitly sent the token or credentials for each request. If a malicious site forges a request, it cannot send the required authentication information to the server (unless a different vulnerability exposes that information), and the request is denied. In such cases, CSRF does not offer any extra protection.

Django: Forcing CSRF token on all responses

My website has an AJAX POST view that can be called from any page on the app (event tracking). This view is protected by CSRF. In some cases, the CSRF cookie is not set, and the POST call fails.
Instead of manually decorating all views with #ensure_csrf_cookie, I'm thinking of writing I created a middleware that enforces Django to set the CSRF cookie on all responses. Is this approach correct? Does it create a security flaw I'm not aware of?
Update: here is the middleware code:
from django.middleware.csrf import get_token
class ForceCsrfCookieMiddleware(object):
def process_request(self, request):
get_token(request)
No, there is no problem as long as you're not rendering the csrf token inside a form that posts to an external site (but that would be a problem anyways, no matter where you implement it). You can set it on a middleware, or some views, or on all views, it doesn't matter.
The CSRF protection is only made to ensure that the request is coming from your site. No matter how often you set the cookie, if the request includes the correct CSRF token it means that the request is indeed coming from your site, because only your site can access your cookies. (of course this only holds if you are not leaking the CSRF token to third parties, for example by sending it to other sites)
In few words, this is how it works:
The server sets a cookie with a random value in the response
Your site reads that value and sends it to the server when posting data
Since cookies can only be accessed from the same domain that set them, there is no way for another site to read that cookie. Therefore, whenever you receive a request that has the right csrf token, you are assured that that request is coming from your site.
For a very good explanation of CSRF, have a look at this article: http://www.gnucitizen.org/blog/csrf-demystified/

How to get an initial CSRF token when working with Django Rest Framework

I am creating an API with the Django Rest Framework. Users are still going to need to get a CSRF token to make POST, PUT, PATCH and DELETE calls. What is the best practice for the user initially getting a CSRF token? I am using TokenAuthentication. So I just need to allow the API to take and username and password and send back the Token. After that I don't need the CSRF token.
Do I have to add a step that will allow them to get CSRF token using a GET method call which will return a token?
I am looking for suggestions on how to best approach this.
With an API you are just about to open a gate to process requests on your server without any session and browser. CSRF tokens are just validating form requests to make sure it's sent from your website. As far as I know it's absolutely ok to turn off CSRF protection for APIs.
You can use csrf_exempt decorator for this.
Read this article to learn more about CSRF and Web API protection.

Categories