Understanding CSRF and How to Prevent It in Your Application — Part 1
文章解释了跨站请求伪造(CSRF)攻击的工作原理:利用浏览器自动附带认证信息(如会话cookie)和服务器无法区分请求来源的特点,在用户不知情的情况下执行恶意操作(如银行转账)。 2025-8-9 05:33:8 Author: infosecwriteups.com(查看原文) 阅读量:18 收藏

No clicks. No alerts. Just your session doing the dirty work.

Gokul Karthik

Press enter or click to view image in full size

ChatGPT Generated Image

Imagine This:

You’re logged into your bank in one browser tab. Meanwhile, you’re casually browsing cat memes on a very suspicious website called CatsThatHack.com .

Suddenly, without clicking anything, a request is secretly sent from CatsThatHack.com to the bank that tells the bank to:
Transfer $1000 to Hacker”

Since you’re already logged in on your browser, your bank says:
“Oh, it’s you! Sure, transferring now!”

You never approved it. You never clicked anything.
But the hacker piggybacked on your bank’s login session to authorize a transaction on your behalf 😶.

In Part 1 of this series, we’ll explore how CSRF(Cross site request forgery) works and the techniques attackers use to exploit it without the user’s knowledge.

Cross-Site Request Forgery (CSRF) is a type of attack that tricks a user’s browser into performing unwanted actions on a web application in which the user is already authenticated to.

But what is the core flaw that introduces the vulnerability ? 🤔
The 2 points below should answer this question:

- Web Browsers Automatically Attach Credentials

Lets talk a bit about the normal operation of a web browser. When you’re logged into a site, your browser stores a session cookie so you stay authenticated across multiple requests/tabs. Anytime your browser makes a request to that site from the same domain or a different domain, it automatically includes that cookie.

If browsers didn’t work like this, the user would need to start a new session every time they opened the same site in a new tab in their browser. That would be clearly a terrible user experience!

🤷‍♂️️Browsers don’t differentiate between same-site and cross-site requests and send credentials(cookies) for both of the requests.

- Servers Couldn’t Tell Where Requests Came From

Historically, servers didn’t verify the source of incoming requests. If a request arrived with a valid session cookie, the server simply trusted it:
“Hey, this cookie checks out. This must be the real user.”

But that assumption allowed a issue to creep in .

A malicious site like CatsThatHack.com could trick the browser into sending a request to another site like bank.com. And the browser, doing what it’s supposed to, would attach the user’s bank.com session cookie — because the user was already logged in. Also from the web server’s point of view, it looks like:

  • A valid request from a logged in user.
  • With valid credentials(Session Cookie)

🤷‍♂️️Servers didn't know the difference between same-site and cross-site requests unless extra precautions were taken.

Alright enough of the theory and diagrams, lets see this in action!

I have created a simple and generic bank app to demonstrate the attack. Yep, my creativity definitely failed me here 🫠.

i. The Vulnerable Bank App

To start with, lets clone our demo bank application from here and run it. Detailed steps on how to run it is given in the README if you would like to follow along.

We have our vulnerable bank’s login page at http://insecure-bank.com/login. The victim will be the user alice who has 1000$ in her bank account. Lets simulate the victim authenticating to the bank with the username and password as alice.

Press enter or click to view image in full size

We have a simple form for transferring funds to other user accounts. Our goal will be to try to maliciously transfer this 1000$ amount to the attacker user using the CSRF attack.

ii. The Attacker’s Phishing Page

Now let’s simulate the phishing page which the attacker has sent to Alice at the link http://CatsThatHack.com/index-insecure.html. Well, Alice really seems to like cat pictures and she just had the sudden urge to click the Transfer Money button because the cats were urging her to (Of course, real phishing pages would not be like this 🙂).

Press enter or click to view image in full size

And boom, clicking on the button redirected alice to the bank with her balance of 0$ and saying that the transfer was successful 🫣.

Press enter or click to view image in full size

And just like that — with a single click, Alice’s money disappears. In fact, it doesn’t even have to be a button click , the form can be auto-submitted by the browser without any user interaction at all !!🫠.

iii. Understanding how and why the attack worked

Firstly, let’s look at the how the Bank App works.

app.use(
session({
secret: 'csrf-demo-secret',
resave: false,
saveUninitialized: false,
cookie: { httpOnly: true }, // "SameSite" attribute not set explicitly
})
);

// Helper: Check if the user is logged in
const requireLogin = (req, res, next) => {
if (!req.session.username || !users[req.session.username]) {
return res.redirect('/login?mustlogin=1');
}
next();
};

// You can only transfer if the user is logged in first
app.post('/transfer', requireLogin, (req, res) => {
const sender = req.session.username;
const { to, amount, coupon } = req.body;
let amt = parseInt(amount, 10);
/*
IRRELEVANT CODE...
*/
users[sender].balance -= amt;
users[to].balance += amt;
res.redirect(redirectUrl);
});

Some important points shown in the above code:

  • The session cookie is set with the HttpOnly flag enabled. However, it does not explicitly set the SameSite attribute, so it defaults to Lax. You can learn more about what this attribute does in Part 2 of this series.
  • After a successful login, this session cookie(connect.sid) is issued to the user. The transfer API relies on the presence of a valid session cookie to proceed.
  • The transfer API POST request accepts the transfer amount and the receiver’s username in the request body, then updates the account balances of both the sender and receiver accordingly.

Cool, now lets see how the attacker exploited this in his phishing page http://CatsThatHack.com/index-insecure.html. The attacker’s page code snippet is given below.

<!-- Sends a POST request with top level navigation. Since the cookie is 
set as LAX implicitly by the browswer, the POST request is allowed to
be sent for the first 2 minutes -->
<form id="csrfForm" method="POST" action="http://insecure-bank.com/transfer">
<input type="hidden" id="to" name="to" value="attacker">
<input type="hidden" id="amount" name="amount" value="1000">
<input type="hidden" id="coupon" name="coupon" value="">
<button type="submit">Transfer money!</button>
</form>

The hidden form sets the receiver as attacker and amount as 1000$ and sends a POST request to http://insecure-bank.com/transfer when the button is clicked. Top Level Navigation and LAX cookies will be discussed in Part 2 of this series so we can ignore that for now 🙂.

Alice’s session cookie is sent with this request by default because the browser automatically attached the session cookie and the web server could not tell that the request was a cross site request. Since the session cookie was sent, this request was assumed to be a legitimate request by our server and the money was sent to the attacker🫠.

We can also verify that the cookie is sent by looking at the developer tools of the browser. Once the Transfer button is clicked on CatsThatHack.com, we can see the Transfer API request being sent with the session cookie highlighted.

Press enter or click to view image in full size

Welp, now you’ve seen how attackers can exploit CSRF vulnerabilities and how the browser’s default behavior plays a surprisingly big role in making these attacks possible 🫠.

In Part 2 of this series, we’ll dive into how you can actually defend against these type of CSRF attacks. We’ll cover things like SameSite cookies, different CSRF token strategies, top-level navigation , and a lot more!

If you’re building anything that uses sessions, you won’t want to miss it!


文章来源: https://infosecwriteups.com/understanding-csrf-and-how-to-prevent-it-in-your-application-part-1-9178bbc828d7?source=rss----7b722bfd1b8d---4
如有侵权请联系:admin#unsafe.sh