acc-check-csrf-protection

📁 dykyi-roman/awesome-claude-code 📅 2 days ago
1
总安装量
1
周安装量
#51858
全站排名
安装命令
npx skills add https://github.com/dykyi-roman/awesome-claude-code --skill acc-check-csrf-protection

Agent 安装分布

opencode 1
claude-code 1

Skill 文档

CSRF Protection Security Check

Analyze PHP code for Cross-Site Request Forgery vulnerabilities.

Detection Patterns

1. Missing CSRF Tokens

// CRITICAL: Form without CSRF token
<form method="POST" action="/transfer">
    <input name="amount" value="1000">
    <input name="to" value="attacker">
    <button>Transfer</button>
</form>

// CRITICAL: No token validation
public function transfer(Request $request): Response
{
    $amount = $request->get('amount');
    $to = $request->get('to');
    $this->bankService->transfer($amount, $to);
    // No CSRF check!
}

2. State-Changing GET Requests

// CRITICAL: Modification via GET
#[Route('/user/delete/{id}', methods: ['GET'])]
public function deleteUser(int $id): Response
{
    $this->userService->delete($id);
}

// CRITICAL: Toggle via GET
#[Route('/user/activate/{id}')]
public function activateUser(int $id): Response
{
    $user = $this->userRepository->find($id);
    $user->setActive(true);
}

// VULNERABLE: Logout via GET (session hijacking)
<a href="/logout">Logout</a>

3. Token Validation Gaps

// VULNERABLE: Token not validated server-side
public function handle(Request $request): Response
{
    // Frontend sends token but backend doesn't check
    $this->processPayment($request);
}

// VULNERABLE: Weak token validation
if ($request->get('_token')) { // Just checks existence
    $this->process();
}

// VULNERABLE: Token not regenerated after login
session_start();
$_SESSION['user'] = $user;
// CSRF token remains same from anonymous session

4. AJAX/API CSRF Issues

// VULNERABLE: No CSRF for AJAX
fetch('/api/update', {
    method: 'POST',
    body: JSON.stringify(data)
});

// VULNERABLE: Only Origin check, no token
if ($_SERVER['HTTP_ORIGIN'] === 'https://example.com') {
    $this->process(); // Origin can be spoofed in some scenarios
}

// VULNERABLE: CORS misconfiguration
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Credentials: true');

5. Cookie-Based Token Issues

// VULNERABLE: Token in cookie only
setcookie('csrf_token', $token);
// Attacker can't read but browser sends automatically

// CORRECT: Double Submit Cookie pattern
// Token in cookie AND in request header/body
// Server compares both values

6. Token Per-Session vs Per-Request

// LESS SECURE: Same token for entire session
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));

// MORE SECURE: New token per form
$token = bin2hex(random_bytes(32));
$_SESSION['csrf_tokens'][] = $token; // Store multiple

7. Subresource Integrity

// VULNERABLE: Third-party script without SRI
<script src="https://cdn.example.com/lib.js"></script>

// CORRECT: With subresource integrity
<script src="https://cdn.example.com/lib.js"
        integrity="sha384-abc123..."
        crossorigin="anonymous"></script>

8. SameSite Cookie Missing

// VULNERABLE: No SameSite attribute
setcookie('session_id', $sessionId);

// CORRECT: SameSite=Strict
setcookie('session_id', $sessionId, [
    'samesite' => 'Strict', // or 'Lax'
    'secure' => true,
    'httponly' => true
]);

Grep Patterns

# Forms without csrf token
Grep: '<form[^>]*method=["\']post["\'][^>]*>' -i --glob "**/*.php"
Grep: 'csrf|_token|token' --glob "**/*.php"

# GET routes that modify state
Grep: '#\[Route.*methods:.*GET.*\]' --glob "**/*.php"
Grep: 'public function delete|update|create' --glob "**/*.php"

# Cookie without samesite
Grep: "setcookie\([^)]+\)\s*;" --glob "**/*.php"

# CORS allow all
Grep: "Access-Control-Allow-Origin.*\*" --glob "**/*.php"

Severity Classification

Pattern Severity
State change via GET 🔴 Critical
No CSRF token on forms 🔴 Critical
Token not validated 🔴 Critical
Missing SameSite cookie 🟠 Major
Token per session only 🟡 Minor

Best Practices

Framework CSRF Protection

// Symfony
{{ csrf_token('authenticate') }}

// Laravel Blade
@csrf

// Validation
$request->validate([
    '_token' => 'required|string'
]);

Manual CSRF Token

// Generate
$token = bin2hex(random_bytes(32));
$_SESSION['csrf_token'] = $token;

// Include in form
<input type="hidden" name="_token" value="<?= $token ?>">

// Validate
if (!hash_equals($_SESSION['csrf_token'], $_POST['_token'])) {
    throw new CsrfException();
}

API CSRF Protection

// Use custom header (can't be set cross-origin)
fetch('/api/update', {
    method: 'POST',
    headers: {
        'X-Requested-With': 'XMLHttpRequest',
        'X-CSRF-Token': csrfToken
    },
    body: JSON.stringify(data)
});

// Server validates header
$token = $request->headers->get('X-CSRF-Token');
if (!$this->csrfManager->isValid($token)) {
    throw new CsrfException();
}

SameSite Cookies

session_start([
    'cookie_samesite' => 'Strict', // Prevents cross-site sending
    'cookie_secure' => true,
    'cookie_httponly' => true,
]);

Output Format

### CSRF Vulnerability: [Description]

**Severity:** 🔴/🟠/🟡
**Location:** `file.php:line`
**CWE:** CWE-352 (Cross-Site Request Forgery)

**Issue:**
[Description of the CSRF weakness]

**Attack Vector:**
Attacker creates malicious page that submits form to victim's browser.

**Code:**
```php
// Vulnerable code

Fix:

// With CSRF protection