Compartilhamento de tecnologia

Pergunta 50 da entrevista de front-end (Quais medidas comuns de segurança de front-end podem impedir ataques CSRF?)

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Insira a descrição da imagem aqui
Para evitar ataques de falsificação de solicitação entre sites (CSRF), as seguintes medidas de segurança comuns podem ser tomadas no desenvolvimento front-end:

1. Use token CSRF

Este é um dos mecanismos de defesa mais utilizados.

  • Gerar token: Após o login do usuário, o servidor gera um token CSRF aleatório e imprevisível e o armazena no lado do servidor. Ao mesmo tempo, ele é enviado ao cliente por meio do cabeçalho Set-Cookie e armazenado no cookie do usuário.

  • Token incorporado ao formulário: Em cada formulário HTML que precisa de proteção, adicione um campo oculto (<input type="hidden">), seu valor é definido como o token CSRF lido do cookie.

  • VerifiqueToken : Quando o formulário for enviado, o backend receberá os dados do formulário e o Token no cookie (devido à política de mesma origem, o navegador enviará automaticamente o cookie). O lado do servidor verifica se o Token no formulário é consistente com o Token armazenado no lado do servidor ou na Sessão. Se forem inconsistentes, a solicitação será rejeitada.

2. Verifique o referenciador HTTP e o cabeçalho de origem

Embora não seja totalmente confiável porque o Referer e o Origin podem estar adulterados ou ausentes, ainda pode ser usado como meio auxiliar em alguns cenários.

  • Verifique o referenciador : verifique o campo Referer no cabeçalho da solicitação HTTP para garantir que a solicitação seja iniciada a partir do nome de domínio esperado. Porém, deve-se observar que este método possui limitações. Por exemplo, em uma solicitação de downgrade de HTTPS para HTTP, o Referer não será enviado.

  • Verifique o cabeçalho de origem: semelhante ao Referer, o cabeçalho Origin fornece informações sobre a origem da solicitação, mas só é enviado ao usar XMLHttpRequest ou Fetch API.

3. Use o atributo SameSite Cookie

Para os cookies que não requerem acesso entre sites, o atributo SameSite pode ser definido para aumentar a segurança.

  • SameSite=Frouxo: O cookie é enviado apenas em solicitações no mesmo site, protegendo parcialmente contra CSRF.
  • SameSite=Rigoroso: os cookies são enviados apenas dentro do mesmo site e na mesma navegação de página, fornecendo proteção mais forte, mas podem afetar algumas funções esperadas entre subdomínios.
  • SameSite=Nenhum: precisa ser usado com o atributo Seguro para cookies que precisam ser cruzados entre sites para se adaptarem aos requisitos dos navegadores modernos.

4. Verificação do cabeçalho da solicitação personalizada

Adicione um cabeçalho HTTP personalizado à solicitação AJAX (comoX-Requested-With: XMLHttpRequest ) e, em seguida, verifique a existência e o valor desse cabeçalho no lado do servidor. Como o JavaScript pode definir livremente o cabeçalho de XMLHttpRequest, mas o envio de formulário comum não pode, isso pode distinguir solicitações iniciadas por scripts.

Código de amostra (implementação do token CSRF):

Lado do servidor (pseudocódigo):

// 生成并设置Token
function generateCsrfToken() {
    return crypto.randomBytes(32).toString('hex');
}

app.post('/login', (req, res) => {
    const token = generateCsrfToken();
    res.cookie('csrfToken', token, { httpOnly: true, secure: true, sameSite: 'strict' });
    // 存储token到session或其他存储机制
});

app.post('/submitForm', (req, res) => {
    if (req.body.csrfToken === req.cookies.csrfToken) {
        // 请求合法,处理逻辑...
    } else {
        // CSRF攻击检测,拒绝请求
        res.status(403).send('Forbidden');
    }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

HTML de front-end:

<form action="/submitForm" method="POST">
    <!-- 其他表单字段... -->
    <input type="hidden" name="csrfToken" value="{{csrfToken}}">
    <button type="submit">Submit</button>
</form>
  • 1
  • 2
  • 3
  • 4
  • 5

Observe que o código acima é apenas um exemplo e o aplicativo real precisa ser ajustado de acordo com a estrutura de back-end e a linguagem usada.