Capítulo 13 — Sistemas de dados
Mapa da aula
Aula 13 publicada. Mapa, exemplo, EX025.
flowchart TD
N0["13.1 Modelos para dados operacionais"]
N1["13.2 Transações, consistência e replicação"]
N2["13.3 Integridade: o que cada mecanismo detecta"]
N3["13.4 Tirar os dados sem deixar os ataques entrarem"]
N4["13.6 Atividade prática: Laboratório 6"]
N5["Síntese do capítulo"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5
N5 --> EX["Exemplo resolvido"]
EX --> Q["Exercício EX025"]
Desenho lógico
flowchart LR
N0["13.1 Modelos para dados operacionais"]
N1["13.2 Transações, consistência e replicação"]
N2["13.3 Integridade: o que cada mecanismo detecta"]
N3["13.4 Tirar os dados sem deixar os ataques entrarem"]
N4["13.6 Atividade prática: Laboratório 6"]
N5["Síntese do capítulo"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> Q["EX025"]
[13.1 Modelos para dados operacionais]
|
v
[13.2 Transações, consistência e replicação]
|
v
[13.3 Integridade: o que cada mecanismo detecta]
|
v
[13.4 Tirar os dados sem deixar os ataques entrarem]
|
v
[13.6 Atividade prática: Laboratório 6]
|
v
[Síntese do capítulo]
|
v
[Exemplo resolvido] --> [Exercício EX025]
Objetivos de aprendizagem e conexão
Ao fim deste capítulo você será capaz de (1) projetar modelos de dados relacionais e de séries temporais para dados operacionais; (2) explicar transações, consistência e replicação; (3) proteger a integridade dos dados com restrições, proveniência e cadeias de hashes, e dizer exatamente o que cada um detecta; e (4) planejar fluxos de dados entre os sistemas de controle e a análise de dados corporativa sem abrir um caminho para dentro do controle. Ele se apoia nos capítulos 9 e 11 e prepara os capítulos 22 (modelos de dados) e 29 (medição).
13.1 Modelos para dados operacionais
Codd (1970) introduziu o modelo relacional: dados como relações (tabelas) com chaves, manipulados por operações de conjuntos. Cadastros de ativos, ordens de serviço e contas de usuários se encaixam bem nele. Os dados de processo — milhares de tags amostradas a cada segundo — costumam ir para um historiador, um repositório de séries temporais otimizado para acréscimos e consultas por intervalo, muitas vezes com uma compressão que descarta mudanças menores do que uma banda morta. Saiba o que seu historiador descarta: a análise forense pode precisar de valores que ele nunca armazenou. O historiador da LRWA armazena o nível de Hollin Hill com compressão por banda morta, então as mudanças menores do que a banda morta nunca são guardadas.
13.2 Transações, consistência e replicação
Uma transação agrupa operações de modo que todas aconteçam ou nenhuma aconteça (atomicidade), deixando os dados válidos (consistência), sem interferência de transações concorrentes (isolamento) e sobrevivendo a quedas (durabilidade). A replicação copia os dados para a disponibilidade; quando as réplicas podem discordar, os sistemas escolhem entre consistência e disponibilidade durante uma partição da rede. Para as operações: um alarme reconhecido por um operador não pode reaparecer como não reconhecido após a troca para o servidor reserva (failover); uma mudança de setpoint não pode ser aplicada duas vezes. No par SCADA da LRWA, o failover é o momento em que essas propriedades são testadas: os testes de integração devem confirmar que os alarmes reconhecidos e os setpoints aplicados sobrevivem à troca exatamente uma vez.
13.3 Integridade: o que cada mecanismo detecta
- As restrições (tipos, faixas, chaves estrangeiras) rejeitam valores impossíveis na entrada.
- Os campos de proveniência (origem, hora da coleta, transformação) permitem rastrear um número até sua origem.
- As somas de verificação (checksums) detectam corrupção acidental.
- As cadeias de hashes ligam cada registro ao anterior, de modo que editar qualquer registro muda todos os hashes posteriores. Elas detectam modificações se você tiver uma cópia confiável de um hash posterior (uma âncora) guardada em algum lugar que o atacante não consiga alterar. Elas não detectam o truncamento do final, a menos que a âncora inclua a contagem de registros, e não provam que os dados originais eram verdadeiros.
- As assinaturas digitais ou os MACs sobre registros ou âncoras os vinculam a quem detém a chave.
13.4 Tirar os dados sem deixar os ataques entrarem
As equipes corporativas querem os dados de controle para relatórios e análises. O padrão seguro é empurrar os dados para fora — da zona de controle para uma réplica do historiador na DMZ — e deixar os usuários corporativos consultarem a réplica, nunca o historiador de controle. Onde a consequência de um comprometimento da zona de controle é grave, gateways unidirecionais (diodos de dados) impõem fisicamente o fluxo apenas para fora. A violação do Laboratório 5 — um script corporativo consultando diretamente uma RTU — é o antipadrão. Na LRWA, a réplica do historiador na DMZ atende às equipes de finanças e de ativos, e o script corporativo esquecido, encontrado na revisão de fluxos, está sendo aposentado em favor dela.
13.5 Exemplo resolvido: protegendo a linha do tempo do incidente (sintético)
Após uma queda inexplicada do nível do reservatório em 4 de março, no registro sintético, a LRWA precisa preservar o extrato do historiador para a investigação. O Laboratório 6 encadeia por hashes seis leituras diárias e guarda o hash da cabeça no chamado do incidente (a âncora). A edição do valor de 4 de março é detectada no índice 3 e em todos os registros posteriores. A exclusão do último registro não é detectada comparando apenas as cabeças se o atacante também substituir a cabeça armazenada — e é por isso que a âncora vai para um sistema fora do alcance do atacante, junto com a contagem de registros.
13.6 Atividade prática: Laboratório 6
# Lab 6 - a hash-chained historian extract detects edits, not deletions at the tail (offline)
import hashlib, json
recs = [{"t": f"2026-03-0{d} 06:00", "tag": "HOLLIN_LVL", "v": v} for d, v in zip(range(1, 7), [78.1, 77.4, 79.0, 41.2, 76.5, 77.9])]
def chain(rs):
prev, out = "0" * 64, []
for r in rs:
h = hashlib.sha256((prev + json.dumps(r, sort_keys=True)).encode()).hexdigest()
out.append(h); prev = h
return out
anchor = chain(recs)
print("head:", anchor[-1][:16])
tampered = [dict(r) for r in recs]; tampered[3]["v"] = 74.0
bad = [i for i, (a, b) in enumerate(zip(anchor, chain(tampered))) if a != b]
print("first mismatch at index:", bad[0], "mismatches:", len(bad))
print("truncated head matches stored index 4:", chain(recs[:5])[-1] == anchor[4])
Saída esperada:
head: a8407870e41914c1
first mismatch at index: 3 mismatches: 3
truncated head matches stored index 4: True
O hash da cabeça é o que a LRWA guarda no chamado do incidente. Editar a leitura de 4 de março para esconder a queda muda o hash no índice três e em todos os registros posteriores, então a edição é detectada onde quer que ocorra. A última linha mostra a fraqueza: uma cadeia construída a partir dos cinco primeiros registros coincide com o hash armazenado no índice quatro, então um atacante que exclua o registro final e substitua a cabeça armazenada passaria despercebido. O EX025 fecha essa lacuna acrescentando a contagem de registros à âncora.
13.7 Erros comuns e limites
- Tratar os dados do historiador como completos quando a compressão ou as bandas mortas descartam detalhes.
- Cadeias de hashes sem uma âncora armazenada de forma independente.
- Acreditar que os mecanismos de integridade provam a verdade; eles provam a não modificação desde a ancoragem.
- Conexões bidirecionais de "relatório" para dentro da zona de controle.
- Perder as informações de fuso horário e de fonte do relógio.
A investigação de 4 de março depende de evitar cada um desses erros, das lacunas de compressão a um fuso horário ausente. Um historiador que descarta pequenas mudanças pode ter descartado justamente os valores que mostrariam com que rapidez o nível caiu, uma âncora mantida no servidor do historiador poderia ser reescrita pelo mesmo administrador, e carimbos de tempo sem fuso tornam impossível alinhar a queda com o registro do operador.
Exercícios — capítulo 13
EX025 — Truncamento do final. Objetivo: fechar a lacuna de truncamento. Entradas: Laboratório 6. Passos: (1) mostre que chain(recs[:5]) coincide com o hash armazenado no índice 4; (2) modifique a âncora para incluir a contagem de registros e mostre que o truncamento é detectado; (3) diga onde a âncora deve ser guardada na LRWA e por quê. Evidência esperada: código e saída. Rubrica: 3 = demonstração e correção certas, âncora guardada fora do alcance dos administradores do controle e do historiador; 2 = correção incompleta; 1 = não executado; 0 = nada.
EX026 — Projeto de fluxo de dados. Objetivo: projetar com segurança o acesso para análises. Entradas: a equipe de finanças quer dados horários de energia das bombas; a equipe de ativos quer dados de pressão ao vivo para um painel. Passos: desenhe (em texto) os fluxos, as zonas e o sentido; diga qual componente impõe o sentido e o que acontece se a réplica da DMZ for comprometida. Evidência esperada: descrição dos fluxos e análise das consequências. Rubrica: 3 = empurrar para a DMZ, nada entrando no controle, consequência limitada à confidencialidade/integridade dos dados da réplica; 2 = sentido não imposto; 1 = consulta direta ao historiador de controle; 0 = nada.
Síntese do capítulo
Modele os dados operacionais deliberadamente, saiba o que seu historiador descarta e use transações e replicação com o failover em mente. Cada mecanismo de integridade detecta algo específico: as restrições rejeitam o impossível, as cadeias de hashes detectam edições em relação a uma âncora armazenada de forma independente, as assinaturas vinculam a quem detém a chave — nenhum deles prova a verdade. Mova os dados para fora, para uma DMZ, e nunca deixe que os relatórios se tornem um caminho para dentro do controle.
Continue estudando — capítulo 13 de 50
← Capítulo 12 · Índice de capítulos do curso · Capítulo 14 →
Siga para a próxima lição escrita.