☕ Um Café no Bellacosa Mainframe
Gostou do conteúdo? Ajude a manter o café quente, o COBOL compilando e o mainframe acordado. 😄
☕ Pague um café ao Bellacosa

Translate

Mostrar mensagens com a etiqueta Privilege Path. Mostrar todas as mensagens
Mostrar mensagens com a etiqueta Privilege Path. Mostrar todas as mensagens

quarta-feira, 12 de fevereiro de 2020

👑 KAZUYA SOUMA ASSUME O RACF — QUANDO O PROGRAMADOR COBOL DESCOBRIU QUE GOVERNAR PRIVILÉGIOS ERA MAIS DIFÍCIL QUE CONCEDÊ-LOS

 
Bellacosa Mainframe e o perigo dos privilégios


☕ UM CAFÉ NO BELLACOSA MAINFRAME

👑 KAZUYA SOUMA ASSUME O RACF — QUANDO O PROGRAMADOR COBOL DESCOBRIU QUE GOVERNAR PRIVILÉGIOS ERA MAIS DIFÍCIL QUE CONCEDÊ-LOS

RACF, COBOL, privilege paths, grafos, grupos, JCL, SURROGAT, started tasks, CICS, Db2, MQ, least privilege, confused deputy, blast radius, graph analytics, segurança — e o dia em que Kazuya Souma descobriu que o problema não era saber quem tinha a chave do castelo, mas descobrir todas as estradas que chegavam ao tesouro.



🎬 PRÓLOGO — SUA MAJESTADE, O USUÁRIO NÃO TEM ACESSO

A reunião começara havia poucos minutos.

Na enorme tela verde estava escrito:

USER: BELL01
RESOURCE: PROD.PAYROLL.MASTER
ACCESS: NONE

O administrador RACF cruzou os braços.

— Resolvido.

Kazuya Souma permaneceu olhando para a tela.

— O que está resolvido?

— O usuário não possui acesso ao arquivo.

— Eu consigo ver isso.

Souma apontou para ACCESS: NONE.

— Minha pergunta é outra.

A sala ficou silenciosa.

— Ele consegue chegar ao arquivo?

O administrador RACF olhou novamente para a tela.

— Acabei de dizer. Não possui acesso.

Souma suspirou.

Chamou o programador COBOL.

Chamou o administrador CICS.

Chamou o DBA Db2.

Chamou a equipe MQ.

Chamou o responsável pelo batch.

Chamou o pessoal de segurança.

Depois desenhou no quadro:

BELL01
   |
   v
APPDEV
   |
   v
JCL
   |
   v
SURROGAT
   |
   v
STARTED TASK
   |
   v
CICS
   |
   v
COBOL
   |
   +------> DB2
   |
   +------> MQ

— Agora — perguntou Souma — alguém consegue me garantir que não existe nenhum caminho daqui até o dado?

Ninguém respondeu.

Souma sorriu.

— Excelente.

O programador COBOL iniciante quase caiu da cadeira.

Excelente?

Foi naquele momento que ele descobriu a primeira regra do novo rei do CPD:

Não confunda ausência de permissão direta com ausência de capacidade.

E nossa história começa exatamente aí.



🏰 CAPÍTULO 1 — PRIMEIRO: O QUE DIABOS É RACF?

Antes de falar sobre grafos, privilege paths, CICS ou Db2, precisamos construir nosso reino.

No IBM z/OS, o RACF — Resource Access Control Facility participa do controle de acesso a recursos.

Simplificando bastante para quem está começando, podemos imaginar três perguntas fundamentais:

QUEM É VOCÊ?

Depois:

VOCÊ CONSEGUE PROVAR QUE É VOCÊ?

E finalmente:

VOCÊ PODE FAZER ISSO?

Imagine um userid:

BELL01

e um dataset:

PROD.CLIENTES.MASTER

Dependendo das regras configuradas, a identidade pode possuir níveis de acesso apropriados ao recurso.

Conceitualmente:

BELL01 ---- READ ----> PROD.CLIENTES.MASTER

Ou talvez:

BELL01 ----- X ------> PROD.CLIENTES.MASTER

Nada de acesso.

Para quem acabou de chegar ao mainframe, isso parece suficiente.

Usuário de um lado.

Recurso do outro.

Permissão no meio.

Souma escreveu:

USER ---- ACCESS ----> RESOURCE

— Esse — explicou — é o mapa mais simples do reino.

O COBOLzeiro perguntou:

— E está errado?

— Não.

Souma completou:

— Está incompleto.



🗺️ CAPÍTULO 2 — O MAPA NÃO É O TERRITÓRIO

Imagine uma cidade medieval.

O tesouro real está dentro do castelo.

Você não possui a chave da porta principal.

Portanto:

VOCÊ ---- X ----> TESOURO

Seguro?

Talvez.

Mas existe uma cozinha?

Existe entrada de funcionários?

Existe túnel?

Existe esgoto?

Existe alguém autorizado que recebe ordens suas?

Existe uma carroça que entra diariamente?

Existe uma porta interna ligando outro prédio ao castelo?

A segurança muda quando percebemos que chegar a alguma coisa não exige necessariamente acesso direto a ela.

No mainframe ocorre algo conceitualmente semelhante.

Um usuário talvez não tenha:

READ PROD.PAYROLL.MASTER

mas possa executar uma transação CICS.

A transação executa um programa COBOL.

O programa acessa Db2.

Ou coloca uma mensagem em MQ.

Outro programa consome a mensagem.

Esse consumidor executa sob uma identidade técnica.

E essa identidade possui acesso aos dados.

Nosso desenho deixa de ser:

USER → DATA

e passa a ser:

USER
 ↓
TRANSACTION
 ↓
PROGRAM
 ↓
SERVICE
 ↓
DATABASE
 ↓
DATA

Nenhuma dessas relações é automaticamente uma vulnerabilidade.

Muito pelo contrário.

É assim que sistemas corporativos são construídos.

O desafio está em descobrir se a composição dessas relações produz capacidades que não deveriam existir.



🕸️ CAPÍTULO 3 — SOUMA DESCOBRE A TEORIA DOS GRAFOS

Souma apagou o quadro.

Desenhou vários círculos:

(USER)

(GROUP)

(JCL)

(STC)

(CICS)

(PROGRAM)

(DB2)

(MQ)

— Cada círculo será um nó.

Depois começou a ligá-los.

USER ──member_of──> GROUP
USER ──execute──> TRANSACTION
TRANSACTION ──invokes──> PROGRAM
PROGRAM ──uses──> DB2
PROGRAM ──puts──> MQ QUEUE

Isso é a base de um grafo.

Temos:

nós, representando entidades;

e:

arestas, representando relacionamentos.

Nosso ambiente pode ser transformado conceitualmente em:

USER:BELL01
     |
     | MEMBER_OF
     v
GROUP:APPDEV
     |
     | EXECUTE
     v
CICS:PAYR
     |
     | INVOKES
     v
PROGRAM:PAY001
     |
     | USES
     v
DB2:PAYROLL

Agora temos algo novo.

Um caminho.

Em nosso contexto, um privilege path.

A pergunta deixa de ser somente:

BELL01 tem acesso a PAYROLL?

e passa a incluir:

Existe um caminho entre BELL01 e PAYROLL?

Parece uma diferença pequena.

Não é.

É uma mudança brutal na forma de pensar segurança.



👥 CAPÍTULO 4 — O PODER DOS GRUPOS

Souma chamou seu Ministro dos Grupos.

— Quantos usuários existem?

— Milhares.

— E vocês concedem autorização individualmente para todos?

O homem empalideceu.

Felizmente, não.

Grupos existem justamente porque administrar milhares de usuários individualmente seria uma insanidade.

Podemos ter:

APPDEV
OPERATIONS
DBA
SUPPORT
PAYROLL

e relacionar usuários a eles.

Por exemplo:

BELL01
   ↓
APPDEV

Se APPDEV possuir determinadas capacidades, Bell pode obtê-las através da associação.

Isso introduz o primeiro conceito importante:

Uma capacidade nem sempre aparece diretamente ligada ao usuário.

Ela pode ser transitiva.

Imagine:

BELL01
   ↓
APPDEV
   ↓
RESOURCE

Mas a história pode atravessar subsistemas.

No universo Db2, grupos RACF podem participar da construção dos chamados secondary authorization IDs, dependendo da configuração.

Portanto, conceitualmente:

RACF USER
   ↓
RACF GROUP
   ↓
DB2 SECONDARY AUTHID
   ↓
DB2 PRIVILEGE

Agora perceba a armadilha mental.

Você pergunta:

Existe GRANT diretamente para BELL01?

Não.

E conclui:

BELL01 não possui capacidade.

Conclusão potencialmente precipitada.

Souma escreveu:

DIRECT != TRANSITIVE

Primeiro easter egg do reino.

Quem conhece banco de dados já começou a desconfiar que esse rei pensa em WITH RECURSIVE.


📜 CAPÍTULO 5 — JCL: O PERGAMINHO QUE MANDA O EXÉRCITO TRABALHAR

Para o iniciante COBOL, JCL pode parecer uma linguagem criada por um mago particularmente mal-humorado:

//PAYJOB   JOB ...
//STEP01   EXEC PGM=PAY001
//INPUT    DD DSN=PROD.PAY.INPUT,DISP=SHR
//OUTPUT   DD DSN=PROD.PAY.OUTPUT,DISP=OLD

Mas existe uma separação importante.

O programa COBOL contém lógica.

Algo como:

READ ARQUIVO-CLIENTES

Mas em ambiente batch, o JCL ajuda a definir como aquele trabalho será executado e quais recursos serão associados à execução.

Pense nisso como logística militar.

COBOL diz:

ataque o objetivo.

JCL ajuda a dizer:

use este batalhão, esta estrada, estes suprimentos e este destino.

Agora surge uma pergunta de segurança:

Quem consegue alterar o JCL?

E outra:

Quem consegue alterar uma procedure utilizada por uma execução privilegiada?

Imagine:

USER
 ↓
UPDATE JCL
 ↓
JOB
 ↓
PRIVILEGED EXECUTION
 ↓
RESOURCE

O usuário talvez não possa tocar diretamente no recurso final.

Mas controlar uma parte da execução pode ser extremamente relevante.

Aqui aparece outra lição:

Controlar código, configuração ou fluxo de execução também pode constituir uma forma de poder.


🎭 CAPÍTULO 6 — SURROGAT: O MINISTRO QUE ASSINA EM NOME DE OUTRO

Souma encontrou um mecanismo interessante no reino:

SURROGAT

Em determinados cenários, RACF permite que um usuário devidamente autorizado submeta trabalho para execução sob outra identidade sem precisar conhecer a senha dessa identidade.

Imagine:

BELL01

não possui acesso a:

PAYROLL

Mas existe:

PAYBATCH

que precisa acessar payroll para executar seu trabalho.

Temos:

PAYBATCH
   ↓
PAYROLL

Se Bell possuir legitimamente a capacidade necessária para submeter trabalho como PAYBATCH, nosso grafo pode conter:

BELL01
   ↓
SURROGAT
   ↓
PAYBATCH
   ↓
PAYROLL

Pergunta 1:

BELL01 possui READ diretamente?

Resposta:

NO

Pergunta 2:

Existe um caminho de execução autorizado
que termina em uma identidade com capacidade?

Talvez:

YES

São perguntas diferentes.

Essa distinção precisa entrar na cabeça de quem trabalha com segurança.


🚂 CAPÍTULO 7 — STARTED TASK: O REI NÃO PRECISA EMPURRAR TODA CARROÇA

Agora entramos no universo das started tasks.

No z/OS existem workloads e serviços que precisam executar continuamente ou ser iniciados pelo sistema ou por operadores.

CICS, MQ e muitos outros componentes podem envolver started tasks.

Conceitualmente podemos ter:

PAYSTC
   ↓
STARTED PROFILE
   ↓
PAYUSER

Aqui aparece uma distinção essencial:

Quem solicitou alguma coisa não é necessariamente a mesma identidade sob a qual o trabalho subsequente será executado.

Imagine:

HUMAN USER
   ↓
REQUEST
   ↓
SERVICE
   ↓
SERVICE USER

O service user pode possuir capacidades diferentes das do usuário humano.

Isso é proposital.

Serviços precisam trabalhar.

O problema aparece quando esquecemos de incluir essa transformação de identidade em nosso mapa.

Souma mandou escrever na parede do CPD:

ALWAYS ASK:

WHO REQUESTED?

WHO EXECUTED?

UNDER WHICH AUTHORITY?

🏦 CAPÍTULO 8 — CICS: A CAPITAL DO REINO

Chegamos ao CICS.

Para quem está começando, pense no CICS — Customer Information Control System como uma plataforma fundamental para processamento transacional no universo mainframe.

Imagine uma transação:

SALO

que chama:

SALDO01

Então:

USER
 ↓
CICS:SALO
 ↓
COBOL:SALDO01

O programa pode consultar Db2:

EXEC SQL
    SELECT SALDO
      INTO :WS-SALDO
      FROM CONTA
     WHERE CONTA_ID = :WS-CONTA
END-EXEC.

O usuário não precisa necessariamente possuir acesso direto à tabela CONTA.

Na verdade, isso frequentemente seria indesejável.

Queremos:

USER
 ↓
APPLICATION
 ↓
CONTROLLED OPERATION
 ↓
DATABASE

e não:

USER
 ↓
EVERYTHING IN DATABASE

A aplicação atua como uma barreira.

Ou deveria.


🧙 CAPÍTULO 9 — O COBOLZEIRO DESCOBRE QUE TAMBÉM É GUARDA

Souma chamou o programador.

— Quem preenche WS-CONTA?

— A transação.

— E de onde vem o valor?

Silêncio.

Souma continuou:

— O usuário consegue alterá-lo?

Mais silêncio.

— E vocês verificam se a conta solicitada pertence ao usuário autenticado?

Agora o COBOLzeiro entendeu.

Segurança não termina no RACF.

Imagine que o programa deveria permitir:

CONSULTAR MINHA CONTA

mas aceite sem validação adequada:

CONSULTAR CONTA 8472

e depois:

CONSULTAR CONTA 8473

e:

CONSULTAR CONTA 8474

A infraestrutura pode estar funcionando exatamente como projetada.

RACF funcionando.

CICS funcionando.

Db2 funcionando.

O defeito está na autorização de negócio dentro da aplicação.

Isso significa que o programador COBOL também participa do modelo de segurança.

Não precisa ser administrador RACF.

Mas precisa entender:

IDENTITY
AUTHENTICATION
AUTHORIZATION
INPUT
BUSINESS RULE
EXECUTION CONTEXT

Seu IF também pode ser uma muralha.


🤵 CAPÍTULO 10 — O CONFUSED DEPUTY DO REINO

Souma contou uma história.

Um ministro possuía autorização para entrar no tesouro.

Os cidadãos não.

Então os cidadãos entregavam solicitações ao ministro.

O ministro verificava a solicitação e buscava o item correspondente.

Perfeito.

Até aparecer uma solicitação:

TRAGA TUDO.

E o ministro respondeu:

— Certamente.

Temos aí a essência do clássico confused deputy problem.

O intermediário possui autoridade legítima.

Uma entidade menos privilegiada consegue induzi-lo a usar essa autoridade de maneira que não deveria.

No nosso mainframe:

USER
 ↓
CICS
 ↓
COBOL PROGRAM
 ↓
SERVICE AUTHORITY
 ↓
DB2

O programa pode legitimamente possuir capacidade para consultar milhares de clientes.

Mas determinado usuário talvez devesse consultar apenas:

CLIENTE 8472

Se a aplicação não limitar corretamente essa operação, temos um problema.

Observe a sutileza.

O usuário não ganhou:

SYSADM

Não recebeu:

SELECT *

Não alterou RACF.

Ele simplesmente conseguiu fazer uma entidade mais poderosa trabalhar inadequadamente em seu benefício.

Essa é uma classe de problema que uma simples análise:

WHO HAS READ?

pode não revelar.


📦 CAPÍTULO 11 — MQ: O MENSAGEIRO DO REINO

Então chegou um mensageiro.

Chamava-se IBM MQ.

Imagine:

CICS
 ↓
PUT
 ↓
PAY.REQUEST

A aplicação não processa imediatamente o trabalho.

Coloca uma mensagem numa queue.

Outro serviço consome:

PAY.REQUEST
 ↓
PAYCONSUMER

O consumidor pode executar como uma started task:

PAYCONSUMER
 ↓
PAYSTC
 ↓
PAYUSER

e acessar Db2:

PAYUSER
 ↓
DB2
 ↓
PAYROLL

Agora conecte tudo:

BELL01
   ↓
CICS TRANSACTION
   ↓
COBOL PROGRAM
   ↓
MQ PUT
   ↓
PAY.REQUEST
   ↓
CONSUMER
   ↓
STARTED TASK
   ↓
SERVICE USER
   ↓
DB2
   ↓
PAYROLL

Souma perguntou:

— Bell possui acesso direto ao payroll?

Todos responderam:

— Não.

— Bell consegue provocar uma cadeia de processamento que termina no payroll?

Silêncio novamente.

Essa é exatamente a diferença entre:

PERMISSION

e:

REACHABILITY

💥 CAPÍTULO 12 — BLAST RADIUS: QUANTO DO REINO CAI SE UMA IDENTIDADE FOR COMPROMETIDA?

Agora Souma fez uma pergunta diferente.

— Se BELL01 fosse comprometido, até onde alguém conseguiria chegar?

Não queremos somente:

LISTUSER BELL01

Queremos conceitualmente descobrir:

REACHABLE(BELL01)

Talvez apareça:

BELL01
├── APPDEV
│   ├── DEV.DATA
│   └── DB2 privileges
│
├── CICS
│   ├── SALO
│   ├── EXTR
│   └── PAYR
│
├── MQ
│   └── APP.REQUEST
│
└── SURROGAT
    └── APPBATCH

Cada ramo pode abrir novos ramos.

Temos então uma maneira interessante de pensar no blast radius de uma identidade.

Não apenas:

O que ela possui diretamente?

Mas:

Que capacidades podem ser alcançadas a partir dela?

Isso muda a priorização defensiva.

Dois usuários podem possuir dez permissões cada.

Mas um deles alcança apenas desenvolvimento.

O outro consegue atravessar cinco relações e atingir serviços críticos.

Contar permissões não revela necessariamente essa diferença.

O grafo revela.


⚖️ CAPÍTULO 13 — LEAST PRIVILEGE NÃO É APENAS REMOVER ACL

Souma reuniu o conselho.

— Precisamos implementar least privilege.

Alguém imediatamente sugeriu:

— Vamos remover permissões!

Souma respondeu:

— Quais?

Silêncio.

O Principle of Least Privilege diz, em essência, que identidades devem possuir somente as capacidades necessárias para desempenhar suas funções.

Mas nosso grafo permite aprofundar isso.

Não basta minimizar:

DIRECT PERMISSIONS

Também queremos minimizar:

UNNECESSARY PRIVILEGE PATHS

Imagine remover:

BELL01 → PAYROLL

Excelente.

Mas continuar com:

BELL01
 ↓
APPDEV
 ↓
PAYR
 ↓
PAY001
 ↓
PAYDB2
 ↓
PAYROLL

Talvez isso seja necessário para a aplicação.

Talvez não.

A questão é saber que o caminho existe e verificar se cada etapa possui justificativa.

Least privilege deixa de ser somente uma propriedade de ACL.

Passa a ser uma propriedade da arquitetura.


🕷️ CAPÍTULO 14 — O NÓ QUE TODO MUNDO IGNORAVA

Souma então pediu:

— Mostrem todos os caminhos críticos.

Centenas apareceram.

Mas havia algo curioso.

Muitos passavam por:

PROD.CICS.LOADLIB

Outros convergiam para:

PROD.APP.PROCLIB

E muitos dependiam do grupo:

PROD_SUPPORT

Em teoria dos grafos existem medidas de centralidade.

Uma delas, chamada betweenness centrality, ajuda a identificar nós que aparecem em muitos caminhos entre outros nós.

Traduzindo para nosso reino:

Existe alguma ponte pela qual metade do exército precisa passar?

Se existe, proteja muito bem aquela ponte.

Em segurança, esses pontos podem funcionar como choke points.

Talvez um recurso aparentemente banal seja estruturalmente crítico porque centenas de privilege paths passam por ele.

Essa é uma descoberta que listas tradicionais dificilmente tornam intuitiva.


🧮 CAPÍTULO 15 — ALGORITMOS ENTRAM NO CPD

O programador COBOL olhou para o desenho.

— Precisamos verificar isso manualmente?

Souma quase derrubou o café.

Claro que não.

Grafos possuem décadas de algoritmos.

Temos conceitos como:

Breadth-First Search
Depth-First Search
Shortest Path
Dijkstra
Connected Components
Centrality
Community Detection

Imagine uma consulta:

SOURCE = USER:BELL01
TARGET = DB2:PAYROLL

Queremos:

FIND PATH

Resultado:

BELL01
 ↓
APPDEV
 ↓
CICS:PAYR
 ↓
PAY001
 ↓
PAYDB2
 ↓
PAYROLL

Podemos ainda atribuir pesos às relações.

Exemplo puramente conceitual:

GROUP MEMBERSHIP        COST 1
EXECUTE TRANSACTION     COST 1
MQ PUT                  COST 2
SURROGATE               COST 3
MODIFY JCL              COST 4
MODIFY LOADLIB          COST 5

Agora podemos procurar não apenas o caminho com menos saltos, mas caminhos segundo critérios de risco ou relevância definidos pela organização.

A matemática começou a governar o reino.

Souma parecia satisfeito.


🔎 CAPÍTULO 16 — O GOOGLE MAPS DOS PRIVILÉGIOS

Souma teve uma ideia.

— Quero um mapa.

— Já temos relatórios RACF.

— Não quero relatório.

Ele escreveu:

FROM USER:BELL01
TO RESOURCE:PAYROLL

E queria receber:

DIRECT ACCESS: NO

INDIRECT PATHS: 3

ROTA 1

BELL01
 ↓
APPDEV
 ↓
CICS PAYR
 ↓
PAY001
 ↓
PAYDB2
 ↓
PAYROLL

ROTA 2

BELL01
 ↓
MQ
 ↓
PAY.REQUEST
 ↓
PAYSTC
 ↓
PAYUSER
 ↓
PAYROLL

ROTA 3

BELL01
 ↓
SURROGAT
 ↓
PAYBATCH
 ↓
PAYROLL

E então:

REMOVE EDGE:
BELL01 → PAY.REQUEST

RESULT:
ROUTE 2 ELIMINATED

Isso seria praticamente um:

GOOGLE MAPS DOS PRIVILÉGIOS

Você pergunta:

BELL01 → PAYROLL

e recebe:

3 rotas encontradas.

Rota mais curta:
5 saltos.

Existe uma rota alternativa via MQ.

SURROGAT apresenta tráfego intenso.

O administrador RACF não achou graça.

O programador COBOL achou maravilhoso.

Souma aprovou o orçamento.


🤖 CAPÍTULO 17 — ONDE ENTRA INTELIGÊNCIA ARTIFICIAL?

Aqui existe uma tentação perigosa:

jogar todos os logs num LLM e perguntar:

Quem é o vilão?

Não precisamos fazer isso.

Primeiro podemos construir deterministicamente um:

ENTERPRISE PRIVILEGE GRAPH

usando informações de:

RACF
JES
JCL
SURROGAT
STARTED
CICS
DB2
MQ
USS
SMF
APPLICATIONS

Algoritmos de grafos encontram relações e caminhos.

Depois uma IA pode ajudar a transformar:

NODE 481
EDGE 92
NODE 773
EDGE 144
NODE 112

em algo compreensível:

BELL01 não possui acesso direto ao recurso. Entretanto, pertence ao grupo APPDEV, que permite utilizar determinada transação CICS. Essa transação executa PAY001, que utiliza um contexto Db2 autorizado a executar PAYPKG, que acessa PAYROLL.

O algoritmo encontra.

A IA explica.

O humano decide.

Essa divisão de responsabilidades é muito mais interessante que transformar IA em oráculo.


⏰ CAPÍTULO 18 — SOUMA DESCOBRE QUE O MAPA SE MOVE

Na manhã seguinte:

08:00

BELL01 → APPDEV

Às 10:12 alguém realizou uma mudança:

APPDEV → PROD_SUPPORT

Às 10:12:01 nasceram dezenas de novas rotas.

O administrador disse:

— Mas foi apenas uma alteração.

Souma respondeu:

— Uma aresta.

E uma única aresta pode conectar dois enormes conjuntos do grafo.

Imagine dois continentes separados.

Adicione uma ponte.

A ponte é apenas uma estrutura.

Mas milhões de novas rotas passam a existir.

No nosso ambiente:

GRAPH(t0)

antes da mudança.

Depois:

GRAPH(t1)

Calculamos:

DIFF GRAPH(t0,t1)

Resultado hipotético:

DIRECT PERMISSIONS ADDED: 1

NEW TRANSITIVE PATHS: 317

NEW PATHS TO CRITICAL RESOURCES: 12

Agora temos uma aplicação extraordinária para Change Management.

Antes de aprovar uma alteração, poderíamos perguntar:

Qual será o impacto desta mudança no grafo de privilégios?

Não apenas:

WHAT ARE WE ADDING?

Mas:

WHAT WILL BECOME REACHABLE?

Isso é muito mais poderoso.


🧪 CAPÍTULO 19 — LABORATÓRIO DO COBOLZEIRO

Você não precisa construir um Neo4j corporativo amanhã.

Comece com papel.

Escolha uma transação CICS conhecida.

Por exemplo:

SALO

Faça o seguinte.

PASSO 1 — IDENTIDADE

Pergunte:

Quem pode iniciar SALO?

PASSO 2 — TRANSAÇÃO

Descubra:

SALO
 ↓
qual programa?

Talvez:

SALDO01

PASSO 3 — PROGRAMA COBOL

Descubra os recursos usados:

SALDO01
 ├── DB2
 ├── VSAM
 └── MQ

PASSO 4 — DB2

Pergunte:

Qual contexto de autorização?
Qual package?
Quais objetos?

PASSO 5 — MQ

Se existir:

PUT PAY.REQUEST

não pare.

Pergunte:

Quem consome PAY.REQUEST?

PASSO 6 — CONSUMIDOR

Descubra:

QUEUE
 ↓
CONSUMER
 ↓
STC
 ↓
USERID

PASSO 7 — CONTINUE

Pergunte quais recursos esse userid consegue utilizar.

Ao terminar, talvez você tenha:

USER
 ↓
CICS
 ↓
COBOL
 ↓
MQ
 ↓
STC
 ↓
COBOL
 ↓
DB2

Você acabou de construir manualmente um pequeno privilege graph.


🧰 CAPÍTULO 20 — DEZ DICAS DE SOUMA PARA O COBOLZEIRO

1. Não pergunte apenas “quem tem acesso?”

Pergunte:

quem consegue chegar?

2. Aprenda RACF mesmo sem querer ser administrador RACF.

Entenda pelo menos:

USER
GROUP
PROFILE
ACCESS
SURROGAT
STARTED

3. Aprenda JCL.

Seu COBOL não vive sozinho.

4. Quando encontrar CICS, siga a transação.

TRANSACTION → PROGRAM → RESOURCE

5. Quando encontrar MQ, siga a mensagem.

A fila não é necessariamente o destino.

Pode ser apenas uma estrada.

6. Quando encontrar Db2, pense além da tabela.

Considere contextos de autorização, packages, roles e outros mecanismos envolvidos.

7. Pergunte sempre sob qual identidade algo executa.

Essa pergunta vale ouro.

8. Diferencie autenticação de autorização.

Saber quem alguém é não responde automaticamente o que essa pessoa pode fazer.

9. Desenhe.

Cinco caixas e quatro setas podem revelar algo que cinquenta páginas de relatório esconderam.

10. Procure composição.

O problema mais interessante talvez não esteja em nenhum componente isoladamente.

Pode estar na combinação:

RACF + CICS + COBOL + MQ + STC + DB2

🥚 CAPÍTULO 21 — PROJECT REALIST HERO

Às 03:17 da madrugada, o console mostrou:

ICH408I ...

O operador acordou Souma.

— Sua Majestade! Temos um problema!

Souma olhou para a mensagem.

— Qual o impacto?

— Ainda não sabemos.

— Qual identidade?

— BELL01.

— Quais caminhos ela possui?

Silêncio.

— Quais serviços ela consegue acionar?

Silêncio.

— Quais recursos críticos são alcançáveis?

Silêncio.

Souma voltou para a cama.

— Então vocês não têm um incidente.

O operador ficou aliviado.

Souma terminou:

— Vocês têm três perguntas sem resposta. Descubram primeiro.

Na saída havia uma placa:

HOW A REALIST HERO REBUILT THE KINGDOM

SEASON 3:
RACF EDITION

Nenhum produtor confirmou essa temporada.

Principalmente porque provavelmente teríamos três episódios inteiros discutindo LISTGRP.

Eu assistiria.


👑 EPÍLOGO — GOVERNAR NÃO É POSSUIR TODAS AS CHAVES

Meses depois, o reino possuía um enorme mapa.

Nele estavam:

USERS
GROUPS
JCL
PROCEDURES
STARTED TASKS
CICS REGIONS
TRANSACTIONS
COBOL PROGRAMS
DB2 AUTHORIZATION
PACKAGES
TABLES
MQ QUEUES
CONSUMERS
SERVICE IDs

Milhares de nós.

Milhões de relações possíveis.

Souma voltou à pergunta que iniciou tudo.

Na tela:

USER: BELL01

RESOURCE: PROD.PAYROLL.MASTER

DIRECT ACCESS: NONE

O antigo administrador sorriu.

— Então eu estava certo.

Souma concordou.

— Estava.

O homem pareceu surpreso.

Souma continuou:

— Só estava respondendo à pergunta errada.

Na tela apareceu:

INDIRECT PATHS FOUND: 3

Agora todos entenderam.

Segurança não é somente descobrir:

WHO HAS THE KEY?

É descobrir:

WHO CAN REACH THE CASTLE?

Depois:

BY WHICH ROAD?

Depois:

WHO CONTROLS THE ROAD?

E finalmente:

WHAT HAPPENS
IF THAT ROAD CHANGES?

Essa é a transformação fundamental.

RACF continua sendo fundamental.

CICS continua fazendo seu trabalho.

Db2 continua protegendo seus objetos.

MQ continua transportando mensagens.

JES continua executando jobs.

COBOL continua processando negócios.

Cada componente pode estar funcionando perfeitamente.

Mas sistemas empresariais não são componentes isolados.

São relações.

Uma identidade chama uma transação.

A transação chama COBOL.

COBOL chama Db2.

Outro programa publica em MQ.

Uma started task consome a mensagem.

Outra identidade entra em cena.

Um package acessa dados.

E o caminho termina num recurso que estava seis saltos distante do usuário original.

Por isso o próximo nível de segurança não consiste simplesmente em produzir listas maiores de ACLs.

Consiste em compreender a topologia do poder.

Quem possui autoridade?

Quem pode delegá-la?

Quem consegue provocar sua utilização?

Quem controla programas executados por identidades privilegiadas?

Quais caminhos são necessários?

Quais são acidentais?

Quais recursos funcionam como pontes?

Quais alterações criam novas rotas?

E qual é o blast radius se um único nó for comprometido?

Souma levantou-se.

O jovem COBOLzeiro perguntou:

— Então qual é a diferença entre administrar permissões e governar privilégios?

O rei escreveu duas linhas no quadro:

PERMISSION = CAN I OPEN THIS DOOR?

e:

REACHABILITY = IS THERE ANY ROUTE
               THAT TAKES ME INSIDE?

Guardou o marcador.

— Administrar permissões é cuidar das portas.

Apontou para o gigantesco grafo.

— Governar privilégios é conhecer o reino.

No fundo do CPD, JES2 imprimiu a última mensagem da madrugada:

$HASP395 SOUMAJOB ENDED

******************************** TOP OF DATA ********************************

DIRECT ACCESS........ NONE
INDIRECT PATHS....... 0003
CRITICAL PATHS....... 0001

SECURITY RESULT:

DO NOT PANIC.
INVESTIGATE THE GRAPH.

******************************** BOTTOM OF DATA *****************************

O programador COBOL sorriu.

Finalmente tinha entendido por que Kazuya Souma fora convocado.

Ele não derrotava monstros ficando mais poderoso.

Ele olhava para sistemas complicados, descobria como as coisas estavam conectadas e reorganizava o reino.

O que, pensando bem, talvez seja uma descrição surpreendentemente boa do trabalho de um programador mainframe.

E também explica por que, quarenta anos depois, alguém ainda encontra um JCL em produção e pergunta:

QUEM DIABOS DEPENDE DISSO?

A resposta, naturalmente, é:

MUITO MAIS GENTE
DO QUE VOCÊ IMAGINA.

☕ Bellacosa Mainframe

Porque no mainframe a porta pode estar perfeitamente trancada — e ainda assim o verdadeiro trabalho do segurança é descobrir todas as estradas que chegam do outro lado.

sexta-feira, 10 de janeiro de 2020

🕸️ BELL CRANEL ENTRA NA DUNGEON DO RACF — QUANDO O PROGRAMADOR COBOL DESCOBRIU QUE NÃO PRECISAVA TER ACESSO AO DADO PARA CHEGAR ATÉ ELE

Bellacosa Mainframe atalhas na segurança que podem comprometer um sistema

☕ UM CAFÉ NO BELLACOSA MAINFRAME

🕸️ BELL CRANEL ENTRA NA DUNGEON DO RACF — QUANDO O PROGRAMADOR COBOL DESCOBRIU QUE NÃO PRECISAVA TER ACESSO AO DADO PARA CHEGAR ATÉ ELE

RACF, privilege paths, grafos, grupos, JCL, SURROGAT, started tasks, CICS, Db2, MQ, COBOL, confused deputy, least privilege, blast radius, graph analytics — e o dia em que Bell Cranel descobriu que derrotar o monstro não exigia atravessar a porta da frente.



🎬 PRÓLOGO — BELL, VOCÊ NÃO TEM ACESSO

Bell Cranel estava parado diante de uma enorme porta de ferro.

No centro dela havia uma pequena placa:

PROD.PAYROLL.MASTER

Bell aproximou seu cartão de identificação.

Uma luz vermelha apareceu.

ICH408I USER(BELL)
DATASET(PROD.PAYROLL.MASTER)
ACCESS INTENT(READ)
ACCESS ALLOWED(NONE)

— Negado — disse Bell.

O veterano COBOLzeiro sentado alguns metros atrás tomou tranquilamente seu café.

— Excelente.

Bell olhou desconfiado.

— Excelente? Eu não consigo entrar.

— Você tentou a porta.

— Claro. Como mais eu entraria?

O velho apontou para a gigantesca construção atrás da porta.

Havia corredores, escadas, elevadores, passagens de manutenção, túneis, portas laterais, filas MQ, regiões CICS, jobs batch, started tasks e conexões Db2.

— Bell... isso aqui é um mainframe.

Ele tomou outro gole.

— Nunca presuma que existe apenas uma entrada.

Foi naquele momento que Bell Cranel descobriu que estava prestes a entrar em uma nova Dungeon.

Não uma Dungeon de monstros.

Uma Dungeon de privilégios.



🦖 CAPÍTULO 1 — PRIMEIRO: O QUE DIABOS É RACF?

Se você começou agora em COBOL e mainframe, precisamos começar do começo.

Em sistemas IBM z/OS existe um componente fundamental chamado RACF — Resource Access Control Facility.

Simplificando bastante, RACF ajuda a responder perguntas como:

Quem é você?
Você conseguiu provar que é você?

e:

Você pode fazer isso?

Imagine um usuário:

BELL01

e um dataset:

PROD.CLIENTES.MASTER

RACF pode determinar que Bell possui:

READ

ou:

UPDATE

ou:

ALTER

ou simplesmente:

NONE

Para quem está começando, é tentador imaginar segurança assim:

USER
 |
 |
 v
RESOURCE

Perguntamos:

BELL01 pode acessar PROD.CLIENTES.MASTER?

Se a resposta for:

NO

parece que terminamos.

Bell não pode acessar o arquivo.

Caso encerrado.

Mas não.

Na verdade, acabamos de começar.



🚪 CAPÍTULO 2 — NÃO TER A CHAVE NÃO SIGNIFICA NÃO CONSEGUIR ENTRAR

Bell voltou até a porta.

Tentou novamente.

ACCESS DENIED

— Eu definitivamente não tenho acesso.

O COBOLzeiro perguntou:

— Você consegue chamar alguém que tenha?

Bell parou.

Essa pequena pergunta muda completamente nosso modelo de segurança.

Considere:

BELL
  |
  X
  |
PAYROLL

Bell não consegue acessar PAYROLL.

Mas imagine agora:

BELL
  |
  v
PROGRAMA
  |
  v
PAYROLL

O programa possui autoridade para consultar os dados.

Bell possui autoridade para executar o programa.

Então temos uma situação perfeitamente normal:

BELL
   ↓
PROGRAMA
   ↓
PAYROLL

Isso não significa automaticamente que existe uma vulnerabilidade.

Na verdade, é exatamente assim que aplicações empresariais devem funcionar.

Um caixa eletrônico não deveria entregar ao cliente acesso direto ao banco de dados.

Você solicita:

CONSULTAR SALDO

A aplicação verifica quem você é, executa uma operação autorizada e devolve somente aquilo que deveria.

A aplicação funciona como intermediária.

E é aqui que aparece nossa primeira grande lição:

Acesso direto e capacidade de provocar uma operação são coisas diferentes.



🕸️ CAPÍTULO 3 — BEM-VINDO À DUNGEON DOS GRAFOS

Bell abriu o mapa.

Havia dezenas de salas.

USER
GROUP
DATASET
JCL
SURROGATE
STARTED TASK
CICS
PROGRAM
DB2
MQ

O veterano explicou:

— Pare de pensar nisso como uma lista.

— Como devo pensar?

— Como um grafo.

Um grafo é uma estrutura matemática formada basicamente por:

NÓS

e:

ARESTAS

Os nós representam coisas.

Por exemplo:

USER:BELL
GROUP:APPDEV
CICS:PAYR
PROGRAM:PAY001
DB2:PAYROLL

As arestas representam relações entre essas coisas:

BELL ──member_of──> APPDEV
BELL ──execute──> PAYR
PAYR ──invokes──> PAY001
PAY001 ──reads──> PAYROLL

Quando conectamos tudo:

BELL
  ↓
APPDEV
  ↓
PAYR
  ↓
PAY001
  ↓
PAYROLL

acabamos de encontrar um caminho.

Em segurança, podemos chamar esse tipo de relacionamento de privilege path.



🧙 CAPÍTULO 4 — O GRUPO QUE PARECIA INOCENTE

Bell encontrou a primeira bifurcação da Dungeon.

Na parede estava escrito:

GROUP APPDEV

Usuários RACF podem pertencer a grupos.

Isso facilita tremendamente a administração.

Imagine 300 programadores.

Em vez de concedermos individualmente:

PERMIT ...

para cada pessoa, podemos criar:

APPDEV

e conceder determinados acessos ao grupo.

Então:

BELL
 ↓
APPDEV
 ↓
RESOURCE

Mas grupos também podem participar de contextos de autorização em outros componentes.

No Db2 for z/OS, por exemplo, dependendo da configuração, grupos RACF podem aparecer como secondary authorization IDs.

Agora temos:

BELL
 ↓
RACF GROUP
 ↓
SECONDARY AUTHID
 ↓
DB2 PRIVILEGE

Talvez Bell nunca tenha recebido diretamente:

GRANT SELECT

Mas isso não significa necessariamente que seu contexto de execução não possa possuir determinada capacidade.

Esse detalhe ensina algo importante:

Permissões podem ser herdadas ou adquiridas através de relacionamentos.

Bell encontrou sua primeira passagem secreta.


📜 CAPÍTULO 5 — JCL NÃO É APENAS AQUELA COISA ESTRANHA COM DUAS BARRAS

Para o iniciante COBOL, JCL inicialmente parece uma coleção de encantamentos ancestrais:

//BELLJOB JOB ...
//STEP01  EXEC PGM=PAY001
//INFILE  DD DSN=PROD.INPUT,DISP=SHR
//OUTFILE DD DSN=PROD.OUTPUT,DISP=OLD

Mas JCL não é COBOL.

COBOL descreve a lógica do programa.

JCL descreve, entre outras coisas, como determinado trabalho será executado no ambiente batch.

Um programa COBOL pode dizer:

READ CLIENTES

Mas alguma coisa precisa dizer qual dataset corresponde a CLIENTES.

No ambiente batch, JCL frequentemente participa dessa associação.

Agora pense em segurança.

Se alguém pode modificar JCL usado por uma execução poderosa, talvez essa pessoa consiga alterar:

programas
datasets
parâmetros
procedures
fluxo de execução

Por isso bibliotecas de JCL e procedures precisam ser cuidadosamente protegidas.

Surge outra regra importante:

Quem controla aquilo que será executado pode adquirir influência sobre o contexto que executará aquilo.

No grafo:

USER
 ↓
MODIFY JCL
 ↓
EXECUTION
 ↓
SERVICE ID
 ↓
RESOURCE

Bell olhou para o mapa.

A Dungeon acabara de ganhar outro andar.


🎭 CAPÍTULO 6 — SURROGATE: “EU NÃO SOU ELE, MAS POSSO PEDIR QUE ELE EXECUTE”

Agora Bell encontrou uma habilidade peculiar.

Chamava-se:

SURROGAT

Em determinados cenários controlados pelo RACF, um usuário autorizado pode submeter trabalho para execução sob outro userid sem precisar conhecer a senha desse userid.

Imagine:

BELL

não possui acesso ao payroll.

Mas existe um userid técnico:

PAYBATCH

que precisa processar folha de pagamento.

Naturalmente:

PAYBATCH
 ↓
PAYROLL

Se houver uma relação surrogate devidamente autorizada:

BELL
 ↓
SURROGATE
 ↓
PAYBATCH

temos:

BELL
 ↓
SURROGATE
 ↓
PAYBATCH
 ↓
PAYROLL

Observe a diferença.

Pergunta:

BELL possui READ diretamente em PAYROLL?

Resposta:

NO

Pergunta:

Existe um caminho autorizado entre BELL e alguma execução capaz de alcançar PAYROLL?

Possível resposta:

YES

São perguntas completamente diferentes.


🚂 CAPÍTULO 7 — STARTED TASK: QUANDO OUTRA IDENTIDADE ASSUME O TRABALHO

Bell continuou descendo.

Encontrou:

PAYSTC

Uma started task é um workload iniciado no z/OS, frequentemente utilizado para serviços de longa duração e componentes do sistema ou middleware.

CICS pode executar como started task.

MQ pode executar como started task.

Diversos produtos e serviços utilizam esse mecanismo.

O RACF permite associar started procedures a identidades específicas.

Conceitualmente:

PAYSTC
 ↓
STARTED
 ↓
PAYUSER

Portanto, não basta perguntar:

Quem iniciou a operação?

Precisamos perguntar:

Sob qual identidade a operação efetivamente executará?

Essa distinção é fundamental.

Além disso, existem conceitos poderosos associados a started procedures, incluindo atributos como:

TRUSTED

e:

PRIVILEGED

São configurações que exigem enorme cuidado porque ampliam significativamente as capacidades daquele contexto de execução.

Bell encontrou uma sala onde estava escrito:

COM GRANDES PRIVILÉGIOS
VÊM GRANDES AUDITORIAS.

Ele jurava já ter ouvido algo parecido em outro universo.

Easter egg número 1 encontrado.


💳 CAPÍTULO 8 — CICS: BELL ENTRA NA CIDADE

Depois do mundo batch, Bell chegou ao CICS.

Para um iniciante:

CICS — Customer Information Control System é uma plataforma de processamento transacional extremamente importante no universo mainframe.

Imagine um sistema bancário.

Quando alguém consulta uma conta, talvez exista uma transação:

SALO

que executa:

SALDO01

Podemos representar:

USER
 ↓
TRANSACTION
 ↓
COBOL PROGRAM

O programa COBOL então acessa Db2, VSAM, MQ ou outros recursos.

Algo conceitualmente assim:

EXEC SQL
   SELECT SALDO
     INTO :WS-SALDO
     FROM CONTA
    WHERE CONTA_ID = :WS-CONTA
END-EXEC.

A questão de segurança agora fica interessantíssima.

Bell talvez não possua:

SELECT ON CONTA

Mas pode possuir:

EXECUTE TRANSACTION SALO

Então:

BELL
 ↓
CICS:SALO
 ↓
SALDO01
 ↓
DB2
 ↓
CONTA

Novamente, isso é normal.

Na verdade, desejável.

Bell não deveria receber acesso irrestrito à tabela inteira só porque precisa consultar uma conta.


🪪 CAPÍTULO 9 — QUEM CHEGA AO DB2?

Aqui encontramos outra transformação importante.

Uma aplicação CICS acessando Db2 possui regras específicas de conexão e autorização.

Dependendo da configuração, elementos como:

DB2CONN
DB2ENTRY
AUTHID
AUTHTYPE

participam da determinação do contexto utilizado.

Portanto, podemos chegar a algo conceitualmente semelhante a:

BELL
 ↓
CICS
 ↓
TRANSACTION
 ↓
COBOL PROGRAM
 ↓
DB2ENTRY
 ↓
APPDB2
 ↓
PACKAGE
 ↓
TABLE

Perceba quantos saltos apareceram.

A pergunta inicial era:

Bell pode ler a tabela?

Agora percebemos que a pergunta deveria ser:

Bell consegue iniciar alguma cadeia de execução
que termine em uma operação sobre a tabela?

E, principalmente:

QUAL operação?

Porque talvez Bell possa solicitar:

SELECT saldo da própria conta

mas não:

SELECT * FROM TODAS_AS_CONTAS

A diferença entre essas duas coisas não está necessariamente numa ACL.

Pode estar na lógica COBOL.


👮 CAPÍTULO 10 — O PROGRAMA COBOL TAMBÉM É UMA BARREIRA DE SEGURANÇA

Essa conclusão é importantíssima para quem está começando.

Você pode pensar:

Segurança é trabalho do RACF.

Não.

RACF é uma camada fundamental.

Mas segurança também pode depender da aplicação.

Imagine:

EXEC SQL
   SELECT NOME, SALDO
   FROM CONTA
   WHERE CLIENTE = :WS-CLIENTE
END-EXEC.

Quem controla WS-CLIENTE?

De onde veio esse valor?

Foi validado?

O usuário pode substituir o identificador?

Existe verificação de propriedade?

O programa garante que:

CLIENTE SOLICITADO = CLIENTE AUTENTICADO

?

Essas perguntas pertencem à segurança da aplicação.

O RACF pode estar perfeitamente configurado enquanto a lógica da aplicação permite operações indevidas.


🤵 CAPÍTULO 11 — O CONFUSED DEPUTY

Bell encontrou um NPC poderoso.

Ele possuía autorização para entrar na sala do tesouro.

Bell não.

Mas Bell podia entregar ordens ao NPC.

O veterano perguntou:

— O que acontece se o NPC não verificar corretamente o pedido?

Temos o clássico problema conhecido como confused deputy.

O intermediário possui privilégios legítimos.

O problema surge quando uma entidade menos privilegiada consegue induzi-lo a usar esses privilégios de forma não pretendida.

Imagine:

USER
 ↓
APPLICATION
 ↓
SERVICE ID
 ↓
DB2

O service ID precisa acessar:

CUSTOMERS
ACCOUNTS
TRANSACTIONS

Isso é legítimo.

Mas o usuário deveria enxergar somente:

CUSTOMER 8472

Se uma falha permitir solicitar:

CUSTOMER *

o usuário não ganhou:

DBADM
SYSADM
SELECT *

Ele conseguiu controlar uma aplicação que já possuía autoridade.

Essa diferença é crucial.


📬 CAPÍTULO 12 — E ENTÃO APARECE MQ

Bell ouviu um barulho.

Não era um Minotauro.

Era uma mensagem chegando.

PAY.REQUEST

IBM MQ introduz comunicação assíncrona e mensageria no cenário.

Imagine:

CICS
 ↓
PUT
 ↓
PAY.REQUEST

Uma aplicação consumidora recebe a mensagem:

PAY.REQUEST
 ↓
PAYCONSUMER

Ela executa sob uma started task:

PAYCONSUMER
 ↓
PAYSTC
 ↓
PAYUSER

e acessa Db2:

PAYUSER
 ↓
DB2
 ↓
PAYROLL

Junte tudo:

BELL
 ↓
CICS
 ↓
COBOL PROGRAM
 ↓
MQ PUT
 ↓
QUEUE
 ↓
CONSUMER
 ↓
STARTED TASK
 ↓
SERVICE ID
 ↓
DB2
 ↓
PAYROLL

Agora volte à primeira pergunta:

Bell possui READ em PAYROLL?

Não.

E isso praticamente deixou de ser a pergunta mais interessante.


💥 CAPÍTULO 13 — BLAST RADIUS

Bell agora recebeu outra missão:

Descubra tudo aquilo que BELL consegue alcançar.

Isso é muito mais interessante.

Podemos pensar no blast radius de uma identidade.

Imagine:

BELL
├── GROUP APPDEV
│   ├── DEV datasets
│   └── DB2 secondary authorization
│
├── CICS
│   ├── SALO
│   ├── EXTR
│   └── TRNF
│
├── MQ
│   └── APP.REQUEST
│
└── SURROGATE
    └── APPBATCH

Cada um desses nós abre outros caminhos.

Então o blast radius não é somente aquilo que aparece diretamente no userid.

É o conjunto de capacidades alcançáveis através das relações existentes.


🧠 CAPÍTULO 14 — LEAST PRIVILEGE GANHA OUTRO SIGNIFICADO

Você provavelmente já ouviu:

Principle of Least Privilege.

Ou:

conceda somente os privilégios necessários.

Perfeito.

Mas nosso grafo permite uma interpretação mais profunda.

Least privilege não deveria significar somente:

minimizar permissões diretas

Também precisamos pensar em:

minimizar caminhos desnecessários

Você pode remover:

BELL → PAYROLL

e continuar possuindo:

BELL
 ↓
APPDEV
 ↓
CICS
 ↓
PROGRAM
 ↓
SERVICE
 ↓
PAYROLL

A ACL ficou menor.

A capacidade talvez continue existindo.


🕷️ CAPÍTULO 15 — SECURITY CHOKE POINTS

Bell percebeu algo estranho no mapa.

Centenas de caminhos diferentes passavam pela mesma sala:

PROD.CICS.LOADLIB

Isso é interessante.

Em teoria dos grafos existe uma medida chamada betweenness centrality.

Simplificando brutalmente:

Quantos caminhos importantes passam por determinado nó?

Imagine:

400 USERS
   ↓
CICS
   ↓
PROD.CICS.LOADLIB
   ↓
72 PROGRAMS
   ↓
DB2 / MQ / VSAM

Talvez essa load library seja muito mais importante para segurança do que sua aparência sugere.

O mesmo poderia acontecer com:

PROD.JCL.PROCLIB

ou:

APP_SUPPORT

ou:

REQUEST.QUEUE

Esses elementos tornam-se choke points.

Se forem comprometidos ou excessivamente permissivos, muitos caminhos podem ser afetados.


🧮 CAPÍTULO 16 — Dijkstra ENTRA NO CPD

Agora Bell precisava encontrar a rota mais curta.

Quem já estudou estruturas de dados talvez reconheça nomes como:

Breadth-First Search
Depth-First Search
Dijkstra
Shortest Path
Connected Components

Esses algoritmos podem ser aplicados conceitualmente ao problema.

Queremos descobrir:

SHORTEST PATH
FROM USER:BELL
TO DB2:PAYROLL

Talvez o resultado seja:

BELL
 ↓
APPDEV
 ↓
CICS:PAYR
 ↓
PROGRAM:PAY001
 ↓
AUTHID:PAYDB2
 ↓
PAYROLL

Cinco saltos.

Mas podemos melhorar.

Nem toda aresta possui o mesmo significado.

Podemos atribuir pesos hipotéticos:

GROUP MEMBERSHIP       1
EXECUTE TRANSACTION    1
MQ PUT                 2
SURROGATE              3
MODIFY JCL             4
MODIFY LOADLIB         5

Agora não procuramos apenas:

shortest path

Podemos procurar:

lowest-cost privilege path

ou caminhos que atravessem relações consideradas particularmente sensíveis.


🤖 CAPÍTULO 17 — IA NÃO PRECISA SER O ORÁCULO

E aqui aparece uma aplicação muito interessante de inteligência artificial.

Não precisamos entregar os dados para um LLM e perguntar:

“Quem é perigoso?”

Isso seria uma péssima abstração.

Podemos primeiro usar mecanismos determinísticos para construir:

ENTERPRISE PRIVILEGE GRAPH

alimentado por informações de:

RACF
JES
JCL
STARTED
SURROGAT
CICS
Db2
MQ
USS
SMF

Algoritmos tradicionais encontram os caminhos.

Depois uma IA pode ajudar a explicar o resultado.

Por exemplo:

USER BELL não possui acesso direto a PAYROLL.

Entretanto:

BELL pertence a APPDEV.
APPDEV permite executar CICS transaction PAYR.
PAYR chama PAY001.
PAY001 utiliza determinado contexto Db2.
Esse contexto executa PAYPKG.
PAYPKG acessa PAYROLL.

Agora temos:

WHAT

mais:

HOW

mais:

WHY

Essa combinação é muito mais útil para um analista.


⏰ CAPÍTULO 18 — O GRAFO TEM TEMPO

Bell finalmente achou que havia entendido a Dungeon.

Então o mapa mudou.

Às:

08:00

tínhamos:

BELL → APPDEV

Às:

10:12

um administrador adicionou uma relação.

Agora:

APPDEV → PROD_SUPPORT

Instantaneamente apareceram novos caminhos.

Esse é um detalhe fantástico.

O grafo de privilégios não é estático.

Podemos pensar:

GRAPH(t0)

e:

GRAPH(t1)

Então perguntar:

DIFF GRAPH(t0,t1)

Talvez uma única mudança tenha criado:

1 nova permissão direta

mas, transitivamente:

37 novos caminhos

ou:

317 novos caminhos

incluindo:

12 caminhos até recursos críticos.

Agora imagine isso integrado ao Change Management.

Antes de aprovar:

PERMIT ...

o sistema calcula:

DIRECT CHANGE:

1 permission

TRANSITIVE EFFECT:

317 new reachable paths

CRITICAL RESOURCES AFFECTED:

12

Nesse momento alguém no Security Operations Center olha para a tela e pergunta:

— Quem diabos pediu essa mudança?

Bell discretamente esconde o formulário.


🔬 CAPÍTULO 19 — PASSO A PASSO PARA PENSAR COMO ANALISTA

Você é um programador COBOL iniciante.

Como aplicar tudo isso sem virar especialista RACF amanhã?

Comece simples.

Pegue uma transação qualquer.

Por exemplo:

CICS transaction: SALO

Pergunte:

1. Quem pode executá-la?

Depois:

2. Qual programa ela chama?

SALO
 ↓
SALDO01

3. Esse programa acessa o quê?

SALDO01
 ├── DB2
 ├── VSAM
 └── MQ

4. Sob qual contexto de autorização?

5. Existem packages Db2 envolvidos?

6. Existem filas MQ?

7. Quem consome essas filas?

8. O consumidor executa sob qual userid?

9. Existe uma started task?

10. Quais recursos essa identidade alcança?

De repente você construiu manualmente:

USER
 ↓
CICS
 ↓
COBOL
 ↓
MQ
 ↓
STC
 ↓
COBOL
 ↓
DB2

Parabéns.

Você acabou de fazer sua primeira análise de privilege path.


🧰 CAPÍTULO 20 — DICAS PARA O COBOLZEIRO

Primeira dica:

não olhe somente para o programa.

Descubra como ele é executado.

Segunda:

aprenda JCL.

O COBOL pode ser o motor, mas JCL frequentemente explica como aquele motor entra na estrada no mundo batch.

Terceira:

aprenda o básico de RACF.

Mesmo que você nunca seja administrador RACF.

Entenda pelo menos:

USER
GROUP
PROFILE
ACCESS
PERMIT
SURROGAT
STARTED

Quarta:

quando encontrar CICS, pergunte pelo contexto de segurança.

Quinta:

quando encontrar MQ, siga a mensagem.

Não pare na fila.

Pergunte:

Quem consome?

Depois:

Sob qual identidade?

Depois:

O consumidor faz o quê?

Sexta:

quando encontrar Db2, não pense somente em tabela.

Lembre-se de:

AUTHID
secondary IDs
roles
packages
plans
privileges

Sétima:

aprenda a desenhar.

Uma folha de papel com:

USER
 ↓
CICS
 ↓
PGM
 ↓
MQ
 ↓
STC
 ↓
DB2

às vezes explica mais que cinquenta páginas de relatório.


🥚 CAPÍTULO 21 — O EASTER EGG DO NÍVEL 37

Bell finalmente chegou ao nível 37 da Dungeon.

Encontrou uma porta.

Na placa estava escrito:

PF3 = EXIT

Bell apertou PF3.

Nada aconteceu.

Apareceu:

IKJ56700A ENTER USERID -

Bell olhou para o veterano.

— Isso não faz sentido.

O COBOLzeiro terminou seu café.

— Bem-vindo ao mainframe.

Bell tentou PF12.

Funcionou.

Ninguém jamais descobriu por quê.

Os arqueólogos de sistemas ainda investigam o incidente.


🗺️ CAPÍTULO 22 — O GOOGLE MAPS DOS PRIVILÉGIOS

Agora podemos imaginar uma ferramenta fascinante.

Você informa:

SOURCE:

USER:BELL

e:

TARGET:

DB2:PAYROLL

A ferramenta responde:

DIRECT ACCESS:

NO

Mas não termina aí.

Ela mostra:

3 INDIRECT PATHS FOUND

PATH 01

BELL
 ↓
APPDEV
 ↓
CICS PAYR
 ↓
PAY001
 ↓
PAYDB2
 ↓
PAYROLL

PATH 02

BELL
 ↓
MQ PUT
 ↓
PAY.REQUEST
 ↓
PAYSTC
 ↓
PAYUSER
 ↓
PAYROLL

PATH 03

BELL
 ↓
SURROGATE
 ↓
PAYBATCH
 ↓
PAYROLL

E ainda poderia dizer:

REMOVE EDGE:

BELL → PAY.REQUEST

RESULT:

PATH 02 eliminated.

Ou:

REMOVE EDGE:

APPDEV → PAYR

RESULT:

PATH 01 eliminated.

Isso transforma segurança em algo visual e explicável.

Quase um:

Google Maps do RACF

Só que, em vez de:

São Paulo → Campinas

perguntamos:

USER01 → PAYROLL

E o sistema responde:

Você chegará ao destino em 5 privilégios.

Existe uma rota alternativa via MQ.

Evite SURROGAT:
tráfego intenso.

Bell riu.

O auditor RACF não.


🏁 EPÍLOGO — A PORTA CONTINUAVA TRANCADA

Bell retornou ao começo da Dungeon.

A velha porta continuava lá:

PROD.PAYROLL.MASTER

Passou seu userid novamente.

ACCESS DENIED

Bell sorriu.

Agora entendia.

A mensagem estava correta.

Ele realmente não possuía acesso direto.

Mas essa informação, sozinha, não descrevia todo o sistema.

Atrás dela existiam:

GROUPS
JCL
SURROGATES
STARTED TASKS
CICS
COBOL
DB2
MQ
SERVICE IDs
PACKAGES
QUEUES
APPLICATION LOGIC

Todos conectados.

A segurança tradicional havia perguntado:

WHO HAS ACCESS?

Bell aprendera a fazer outra pergunta:

WHO CAN REACH IT?

E depois uma ainda melhor:

HOW?

Essa talvez seja uma das mudanças de perspectiva mais importantes para quem começa a estudar segurança em ambientes corporativos complexos.

Um privilégio não precisa ser uma linha dizendo:

USER01 READ PAYROLL

Ele pode estar espalhado por cinco sistemas diferentes.

Pode começar em um grupo RACF.

Passar por JCL.

Trocar de identidade numa started task.

Entrar em CICS.

Executar um programa COBOL.

Publicar uma mensagem MQ.

Ser consumido por outro serviço.

Terminar em um package Db2.

E somente então alcançar o dado.

Nenhum componente isolado necessariamente está errado.

O risco pode existir na composição.

Essa é a beleza — e também a dificuldade — dos sistemas grandes.

Bell guardou a adaga.

O COBOLzeiro fechou o SDSF.

E na última tela verde da Dungeon apareceu:

******************************** TOP OF DATA ********************************

USER BELL01
DIRECT ACCESS TO PAYROLL: NONE

INDIRECT PRIVILEGE PATHS: 3

******************************** BOTTOM OF DATA *****************************

Bell ficou alguns segundos olhando.

Então perguntou:

— Então segurança não é descobrir quem tem a chave?

O velho levantou a xícara.

— Não, Bell.

Na tela apareceu o último ensinamento:

       PERMISSION != REACHABILITY

— Segurança também é descobrir quem conhece o caminho.

E, em algum lugar profundamente enterrado dentro do z/OS, um job terminou:

IEF404I BELLJOB - ENDED - TIME=03.17.42

MAXCC=0000

Porque algumas tradições são sagradas.

☕

Vagner Renato Bellacosa, IBM Champion e especialista em IBM Mainframe
IBM Z17 SYSTEM ONLINE
Sobre o autor

Vagner Renato Bellacosa

IBM Champion 2026 • Especialista em IBM Mainframe

Vagner Renato Bellacosa trabalha com IBM Mainframe desde 1988 , é IBM Champion e especialista em COBOL, CICS, Db2, z/OS e IBM Z. Compartilha experiências profissionais, conhecimento técnico, história da computação e práticas do universo mainframe para aproximar novas gerações das tecnologias que sustentam empresas, bancos e governos ao redor do mundo.

IBM Champion IBM Z COBOL CICS Db2 z/OS Mainframe desde 1988
GitHub LinkedIn
Inicializando conteúdo...