Assine para receber notificações de novos posts:

Apresentamos o API Shield

01/10/2020

11 min. de leitura

As APIs são a força vital dos aplicativos modernos conectados à internet. A cada milissegundo elas carregam solicitações de aplicativos móveis "Faça este pedido de entrega de comida"; "'Curta' esta foto", e instruções para dispositivos de IoT "Destranque a porta do carro", "Inicie o ciclo de lavagem", "Meu humano acabou de correr 5k", entre inúmeras outras chamadas.

Elas também são alvo de ataques generalizados, projetados para executar ações não autorizadas ou exfiltrar dados, como os dados do Gartner mostram cada vez mais: “até 2021, 90% dos aplicativos habilitados para web terão mais área de superfície para ataques na forma de APIs expostas do que a interface de usuários, acima dos 40% de 2019" e “a Gartner previu que, até 2022, os abusos de API passarão de um vetor de ataque pouco frequente para o mais frequente, resultando em violações de dados para aplicativos web corporativos”[1][2]. Dos 18 milhões de solicitações por segundo que atravessam a rede da Cloudflare, 50% são direcionados a APIs e a maioria dessas solicitações é bloqueada como sendo maliciosas.

Para combater essas ameaças, a Cloudflare está simplificando a segurança de APIs por meio do uso de uma forte identidade de cliente baseada em certificado e validação rigorosa baseada em esquema. A partir de hoje, esses recursos estão disponíveis gratuitamente para todos os planos da nossa nova oferta “API Shield”. E, a partir de hoje, os benefícios de segurança também se estendem às APIs baseadas em gRPC, que usam formatos binários, como buffers de protocolo em vez de JSON, e têm crescido em popularidade junto à nossa base de clientes.

Continue lendo para saber mais sobre os novos recursos ou vá direto para o parágrafo "Demonstração" para obter exemplos de como começar a configurar sua primeira regra do API Shield.

Modelos de segurança positiva e certificados de clientes

Um modelo de “segurança positiva” é aquele que permite apenas comportamentos e identidades conhecidos, rejeitando todo o resto. É o oposto do modelo tradicional de “segurança negativa” imposto por um firewall de aplicativos web (WAF) que permite tudo, exceto solicitações provenientes de IPs, ASNs e países problemáticos ou solicitações com assinaturas problemáticas (tentativas de injeção de SQL, etc.).

A implementação de um modelo de segurança positivo para APIs é a maneira mais objetiva de eliminar o ruído de ataques de preenchimento de credenciais e outras ferramentas de verificação automatizadas. E o primeiro passo para um modelo positivo é a implantação de autenticação forte, como a autenticação de TLS mútuo, que não é vulnerável à reutilização ou compartilhamento de senhas.

Assim como simplificamos a emissão de certificados de servidor em 2014 com o Universal SSL, o API Shield reduz o processo de emissão de certificados de cliente ao clique em alguns botões no Painel de controle da Cloudflare. Ao fornecer uma infraestrutura de chave pública privada (PKI) totalmente hospedada, você pode se concentrar em seus aplicativos e recursos, em vez de em operar e proteger sua própria autoridade de certificação (CA).

Impor solicitações válidas com validação de esquema

Quando os desenvolvedores podem ter certeza de que apenas clientes legítimos (com certificados SSL em mãos) estão se conectando às suas APIs, a próxima etapa na implementação de um modelo de segurança positivo é garantir que esses clientes estejam fazendo solicitações válidas. Extrair um certificado de cliente de um dispositivo e reutilizá-lo em outro lugar é difícil, mas não impossível, por isso também é importante garantir que a API esteja sendo chamada conforme o esperado.

Solicitações contendo entradas estranhas podem não ter sido antecipadas pelo desenvolvedor da API e podem causar problemas se processadas diretamente pelo aplicativo, portanto, devem ser descartadas na borda, se possível. A validação do esquema de API funciona comparando o conteúdo das solicitações de API, os parâmetros de consulta que vêm após o URL e o conteúdo do corpo do POST, com um contrato ou “esquema” que contém as regras para o que é esperado. Se a validação falhar, a chamada da API é bloqueada, protegendo a origem de uma solicitação inválida ou de uma carga maliciosa.

A validação do esquema está atualmente em versão beta fechada para cargas JSON, e a compatibilidade com gRPC/buffer de protocolo está no roteiro. Se você quiser participar da versão beta, abra um ticket de suporte com o assunto "Validação de esquema de API beta". Após o término da versão beta, planejamos disponibilizar a validação de esquema como parte da interface de usuário do API Shield.

Demonstração

Para demonstrar como as APIs que alimentam dispositivos de IoT e aplicativos móveis podem ser protegidas, criamos uma demonstração do API Shield usando certificados de cliente e validação de esquema.

As temperaturas são capturadas por um dispositivo de IoT, representado na demonstração por um Raspberry Pi 3 Modelo B+ com um sensor de temperatura infravermelho externo e, em seguida, transmitidas por meio de uma solicitação POST para uma API protegida pela Cloudflare. As temperaturas são posteriormente recuperadas por solicitações GET e, em seguida, exibidas em um aplicativo móvel criado em Swift para iOS.

Em ambos os casos, a API foi criada, na verdade, usando o Cloudflare Workers® e o Workers KV, mas pode ser substituída por qualquer endpoint acessível pela internet.

1. Configuração da API

Antes de configurar o dispositivo de IoT e o aplicativo móvel para se comunicarem com segurança com a API, precisamos inicializar os endpoints da API. Para manter o exemplo simples, além de permitir personalização adicional, implementamos a API como um Cloudflare Worker (pegando emprestado o código do tutorial To-Do List).

Neste exemplo específico, as temperaturas são armazenadas no Workers KV usando o endereço de IP de origem como uma chave, mas isso pode ser facilmente substituído por um valor do certificado do cliente, por exemplo, a impressão digital. O código abaixo salva uma temperatura e o timestamp em KV quando um POST é realizado e retorna as 5 temperaturas mais recentes quando uma solicitação GET é feita.

const defaultData = { temperatures: [] }

const getCache = key => TEMPERATURES.get(key)
const setCache = (key, data) => TEMPERATURES.put(key, data)

async function addTemperature(request) {

    // pull previously recorded temperatures for this client
    const ip = request.headers.get('CF-Connecting-IP')
    const cacheKey = `data-${ip}`
    let data
    const cache = await getCache(cacheKey)
    if (!cache) {
        await setCache(cacheKey, JSON.stringify(defaultData))
        data = defaultData
    } else {
        data = JSON.parse(cache)
    }

    // append the recorded temperatures with the submitted reading (assuming it has both temperature and a timestamp)
    try {
        const body = await request.text()
        const val = JSON.parse(body)

        if (val.temperature && val.time) {
            data.temperatures.push(val)
            await setCache(cacheKey, JSON.stringify(data))
            return new Response("", { status: 201 })
        } else {
            return new Response("Unable to parse temperature and/or timestamp from JSON POST body", { status: 400 })
        }
    } catch (err) {
        return new Response(err, { status: 500 })
    }
}

function compareTimestamps(a,b) {
    return -1 * (Date.parse(a.time) - Date.parse(b.time))
}

// return the 5 most recent temperature measurements
async function getTemperatures(request) {
    const ip = request.headers.get('CF-Connecting-IP')
    const cacheKey = `data-${ip}`

    const cache = await getCache(cacheKey)
    if (!cache) {
        return new Response(JSON.stringify(defaultData), { status: 200, headers: { 'content-type': 'application/json' } })
    } else {
        data = JSON.parse(cache)
        const retval = JSON.stringify(data.temperatures.sort(compareTimestamps).splice(0,5))
        return new Response(retval, { status: 200, headers: { 'content-type': 'application/json' } })
    }
}

async function handleRequest(request) {

    if (request.method === 'POST') {
        return addTemperature(request)
    } else {
        return getTemperatures(request)
    }

}

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

Antes de adicionar a autenticação de TLS mútuo, testaremos o POST de uma leitura de temperatura aleatória:

$ TEMPERATURE=$(echo $((361 + RANDOM %11)) | awk '{printf("%.2f",$1/10.0)}')
$ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")

$ echo -e "$TEMPERATURE\n$TIMESTAMP"
36.30
2020-09-28T02:57:49Z

$ curl -v -H "Content-Type: application/json" -d '{"temperature":'''$TEMPERATURE''', "time": "'''$TIMESTAMP'''"}' https://shield.upinatoms.com/temps 2>&1 | grep "< HTTP/2"
< HTTP/2 201 

E aqui está uma leitura subsequente dessa temperatura, junto com as 4 anteriores que foram enviadas:

$ curl -s https://shield.upinatoms.com/temps | jq .
[
  {
    "temperature": 36.3,
    "time": "2020-09-28T02:57:49Z"
  },
  {
    "temperature": 36.7,
    "time": "2020-09-28T02:54:56Z"
  },
  {
    "temperature": 36.2,
    "time": "2020-09-28T02:33:08Z"
  },
    {
    "temperature": 36.5,
    "time": "2020-09-28T02:29:22Z"
  },
  {
    "temperature": 36.9,
    "time": "2020-09-28T02:27:19Z"
  } 
]

2. Emissão de certificado de cliente

Com nossa API em mãos, é hora de bloqueá-la para exigir um certificado de cliente válido. Antes de fazer isso, vamos gerar esses certificados. Para fazer isso, você pode ir para a guia SSL/TLS → Certificados de cliente do Painel de controle da Cloudflare e clicar em “Criar Certificado” ou pode automatizar o processo por meio de chamadas de API.

Como a maioria dos desenvolvedores em escala gera suas próprias chaves privadas e CSRs e solicita que sejam assinados via API, mostramos este processo aqui. Usando o kit de ferramentas de PKI CFSSL da Cloudflare. Primeiro criaremos um certificado de bootstrap para o aplicativo iOS e, em seguida, criaremos um certificado para o dispositivo de IoT:

$ cat <<'EOF' | tee -a csr.json
{
    "hosts": [
        "ios-bootstrap.devices.upinatoms.com"
    ],
    "CN": "ios-bootstrap.devices.upinatoms.com",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [{
        "C": "US",
        "L": "Austin",
        "O": "Temperature Testers, Inc.",
        "OU": "Tech Operations",
        "ST": "Texas"
    }]
}
EOF

$ cfssl genkey csr.json | cfssljson -bare certificate
2020/09/27 21:28:46 [INFO] generate received request
2020/09/27 21:28:46 [INFO] received CSR
2020/09/27 21:28:46 [INFO] generating key: rsa-2048
2020/09/27 21:28:47 [INFO] encoded CSR

$ mv certificate-key.pem ios-key.pem
$ mv certificate.csr ios.csr

// and do the same for the IoT sensor
$ sed -i.bak 's/ios-bootstrap/sensor-001/g' csr.json
$ cfssl genkey csr.json | cfssljson -bare certificate
...
$ mv certificate-key.pem sensor-key.pem
$ mv certificate.csr sensor.csr
Gere uma chave privada e CSR para o dispositivo de IoT e aplicativo iOS
// we need to replace actual newlines in the CSR with ‘\n’ before POST’ing
$ CSR=$(cat ios.csr | perl -pe 's/\n/\\n/g')
$ request_body=$(< <(cat <<EOF
{
  "validity_days": 3650,
  "csr":"$CSR"
}
EOF
))

// save the response so we can view it and then extract the certificate
$ curl -H 'X-Auth-Email: YOUR_EMAIL' -H 'X-Auth-Key: YOUR_API_KEY' -H 'Content-Type: application/json' -d “$request_body” https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/client_certificates > response.json

$ cat response.json | jq .
{
  "success": true,
  "errors": [],
  "messages": [],
  "result": {
    "id": "7bf7f70c-7600-42e1-81c4-e4c0da9aa515",
    "certificate_authority": {
      "id": "8f5606d9-5133-4e53-b062-a2e5da51be5e",
      "name": "Cloudflare Managed CA for account 11cbe197c050c9e422aaa103cfe30ed8"
    },
    "certificate": "-----BEGIN CERTIFICATE-----\nMIIEkzCCA...\n-----END CERTIFICATE-----\n",
    "csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIIDITCCA...\n-----END CERTIFICATE REQUEST-----\n",
    "ski": "eb2a48a19802a705c0e8a39489a71bd586638fdf",
    "serial_number": "133270673305904147240315902291726509220894288063",
    "signature": "SHA256WithRSA",
    "common_name": "ios-bootstrap.devices.upinatoms.com",
    "organization": "Temperature Testers, Inc.",
    "organizational_unit": "Tech Operations",
    "country": "US",
    "state": "Texas",
    "location": "Austin",
    "expires_on": "2030-09-26T02:41:00Z",
    "issued_on": "2020-09-28T02:41:00Z",
    "fingerprint_sha256": "84b045d498f53a59bef53358441a3957de81261211fc9b6d46b0bf5880bdaf25",
    "validity_days": 3650
  }
}

$ cat response.json | jq .result.certificate | perl -npe 's/\\n/\n/g; s/"//g' > ios.pem

// now ask that the second client certificate signing request be signed
$ CSR=$(cat sensor.csr | perl -pe 's/\n/\\n/g')
$ request_body=$(< <(cat <<EOF
{
  "validity_days": 3650,
  "csr":"$CSR"
}
EOF
))

$ curl -H 'X-Auth-Email: YOUR_EMAIL' -H 'X-Auth-Key: YOUR_API_KEY' -H 'Content-Type: application/json' -d "$request_body" https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/client_certificates | perl -npe 's/\\n/\n/g; s/"//g' > sensor.pem
Peça à Cloudflare para assinar os CSRs com a CA privada emitida para sua zona

3. Criação de regras do API Shield

Com os certificados em mãos, agora podemos configurar o endpoint de API para exigir seu uso. Abaixo está uma demonstração de como criar tal regra.

As etapas incluem especificar quais hostnames solicitam certificados, por exemplo, shield.upinatoms.com e, em seguida, criar a regra do API Shield.

4. Comunicação com o dispositivo de IoT

Para preparar o dispositivo de IoT para comunicação segura com nosso endpoint de API, precisamos incorporar o certificado no dispositivo e, em seguida, apontar nosso aplicativo para ele para que possa ser usado ao fazer a solicitação POST para o endpoint de API.

Copiamos com segurança a chave privada e o certificado em /etc/ssl/private/sensor-key.pem e /etc/ssl/certs/sensor.pem e, em seguida, modificamos nosso script de amostra para apontar para estes arquivos:

import requests
import json
from datetime import datetime

def readSensor():

    # Takes a reading from a temperature sensor and store it to temp_measurement 

    dateTimeObj = datetime.now()
    timestampStr = dateTimeObj.strftime(‘%Y-%m-%dT%H:%M:%SZ’)

    measurement = {'temperature':str(36.5),'time':timestampStr}
    return measurement

def main():

    print("Cloudflare API Shield [IoT device demonstration]")

    temperature = readSensor()
    payload = json.dumps(temperature)
    
    url = 'https://shield.upinatoms.com/temps'
    json_headers = {'Content-Type': 'application/json'}
    cert_file = ('/etc/ssl/certs/sensor.pem', '/etc/ssl/private/sensor-key.pem')
    
    r = requests.post(url, headers = json_headers, data = payload, cert = cert_file)
    
    print("Request body: ", r.request.body)
    print("Response status code: %d" % r.status_code)

Quando o script tenta se conectar a https://shield.upinatoms.com/temps, a Cloudflare solicita que um Certificado de cliente seja enviado e nosso script envia o conteúdo de sensor.pem antes de demonstrar que possui sensor-key.pem conforme necessário para concluir o handshake SSL/TLS.

Se não enviarmos o certificado de cliente ou tentarmos incluir campos estranhos na solicitação da API, a validação do esquema (configuração não mostrada) falha e a solicitação é rejeitada:

Cloudflare API Shield [IoT device demonstration]
Request body:  {"temperature": "36.5", "time": "2020-09-28T15:52:19Z"}
Response status code: 403

Se, em vez disso, um certificado válido for apresentado e a carga seguir o esquema carregado anteriormente, nosso script POSTa a última leitura de temperatura para a API.

Cloudflare API Shield [IoT device demonstration]
Request body:  {"temperature": "36.5", "time": "2020-09-28T15:56:45Z"}
Response status code: 201

5. Comunicação com o aplicativo móvel (iOS)

Agora que as solicitações de temperatura foram enviadas para nosso endpoint de API, é hora de lê-las com segurança em nosso aplicativo móvel usando um dos certificados de cliente.

Resumidamente, vamos incorporar um certificado e uma chave “bootstrap” como um arquivo PKCS#12 no pacote de aplicativos. Em uma implantação no mundo real, esse certificado bootstrap só deve ser usado junto com as credenciais do usuário para ser autenticado em um endpoint de API que pode retornar um certificado de usuário exclusivo. Os usuários corporativos preferem usar o MDM para distribuir certificados para controle adicional e opções de persistência.

Crie o pacote do certificado e da chave privada

Antes de adicionar o certificado bootstrap e a chave privada, precisamos combiná-los em um arquivo binário PKCS#12. Este arquivo binário será adicionado ao nosso pacote de aplicativos iOS.

$ openssl pkcs12 -export -out bootstrap-cert.pfx -inkey ios-key.pem -in ios.pem
Enter Export Password:
Verifying - Enter Export Password:

Adicione o pacote de certificados ao seu aplicativo iOS

No XCode, clique em Arquivo → Adicionar arquivos a "[Nome do projeto]" e selecione seu arquivo .pfx. Certifique-se de marcar "Adicionar ao alvo" antes de confirmar.

Modifique seu código URLSession para usar o certificado do cliente

Este artigo fornece uma boa explicação sobre o uso de uma classe PKCS#11 e URLSessionDelegate para modificar seu aplicativo a fim de concluir a autenticação de TLS mútuo ao se conectar a uma API que a exija.

Pensando no futuro

Nos próximos meses, planejamos expandir o API Shield com vários recursos adicionais projetados para proteger o tráfego de APIs. Para clientes que desejam usar sua própria PKI, forneceremos a capacidade de importar suas próprias CAs, algo disponível hoje como parte do Cloudflare Access.

À medida que recebermos feedback sobre nossa versão beta de validação de esquema, pensamos em colocar o recurso em disponibilidade geral para todos os clientes. Se você está experimentando a versão beta e tem ideias para compartilhar, adoraríamos ouvir seus comentários.

Além de certificados e validação de esquema, estamos entusiasmados em oferecer recursos adicionais de segurança de API, bem como análises aprofundadas para ajudá-lo a entender melhor suas APIs. Se houver recursos que você gostaria de ver, informe-nos nos comentários abaixo.

1: “Até 2021, 90% dos aplicativos habilitados para web terão mais área de superfície para ataques na forma de APIs expostas do que a interface de usuários, acima dos 40% de 2019." Fonte: Gartner “Gartner's API Strategy Maturity Model”, Saniye Alaybeyi, Mark O'Neill, 21 de outubro de 2019. (É necessária uma assinatura da Gartner)

2: “A Gartner previu que até 2022 os abusos de API passarão de um vetor de ataque pouco frequente para o mais frequente, resultando em violações de dados para aplicativos web corporativos." Fonte: Gartner “Cool Vendors in API Strategy”, Shameen Pillai, Paolo Malinverno, Mark O'Neill, Jeremy D'Hoinne, 18 de maio de 2020 (É necessária uma assinatura da Gartner)

Nós protegemos redes corporativas inteiras, ajudamos nossos clientes a construírem aplicativos em escala de internet com eficiência, aceleramos qualquer site ou aplicativo de internet, evitamos ataques DDoS, mantemos os invasores afastados, e podemos ajudá-lo em sua jornada para a Zero Trust.

Acesse 1.1.1.1 de qualquer dispositivo para começar a usar nosso aplicativo gratuito que tornará sua internet mais rápida e mais segura.

Para saber mais sobre nossa missão de ajudar a construir uma internet melhor, comece aqui. Se estiver procurando uma nova carreira para trilhar, confira nossas vagas disponíveis.
Birthday Week (PT)Product News (PT)API Shield (PT)Security (PT)Português

Seguir no X

Patrick R. Donahue|@prdonahue
Cloudflare|@cloudflare

Posts relacionados

28 de setembro de 2022 às 13:01

Anunciamos o Turnstile, uma alternativa ao CAPTCHA fácil de usar e que preserva a privacidade

Hoje, estamos anunciando o beta aberto do Turnstile, uma alternativa invisível aos CAPTCHAs. Qualquer pessoa, em qualquer lugar da internet, que queira substituir os CAPTCHAs em seu site poderá chamar uma API simples...

28 de setembro de 2022 às 13:00

Monitore sua rede com análises de fluxo de rede gratuitas da Cloudflare

O Magic Network Monitoring agora apresenta um poderoso painel de análise de dados, configuração de autoatendimento e um assistente de integração passo a passo. Você terá acesso a uma ferramenta que ajuda a visualizar seu tráfego e filtrar por características de pacotes, incluindo protocolos...