# Apresentação de uma falha de segurança de dados no superset
> :warning: O problema está relacionado com as tabelas antigas que não seguem a LGPD, ou seja, as tabelas desagregadas. Logo, tal problema não existe para os indicadores que utilizam fontes novas (agregadas), como por exemplo o indicador **Docentes por escola**.
## Apresentação do problema
É sabido que os dados do banco `pnad_novo` não devem ser acessados de forma bruta, sem nenhuma forma de agragação, pois seus dados ferem a LGPD.
Acreditando que não seria um problema foi criado um indicador no Apache Superset utilizando este banco, **Taxa de atendimento**. Para testar como seria o comportamento de
um usuário público visualizando o dashboard desse indicador foi criado um "usuário público", que tem acesso aos dashboards e charts sem precisar fazer login.
É mostrado que é possível esse usuário, utilizando ferramentas simples e documentação do Superset, extrair os dados brutos do dataset criado para o
indicador.
## Estrutura do dataset
O indicador é representado como um dataset dentro da ferramenta, ou seja cada indicador tem seu dataset. Esse dataset contém colunas transformadas do banco `pnad_novo`
para mapear os valores do banco para labels com sentido. Além disso o superset permite criar métricas, funções de agregação, associadas a um dataset. Essas métricas garantem que os dados apresentados nos gráficos criados pelo dataset `Taxa atendimento - pnad_novo - glc22` não ferem a LGPD.
O acordo é, todo o gráfico que for gerado utilizando `Taxa atendimento - pnad_novo - glc22` deve utilizar uma das métricas definidas para esse dataset, nesse exemplo a única métrica é[^1]:
O superset possui uma role `Public` onde são definidas as permissões do usuário público, aquele que não precisa de login. A role contém apenas permissões de leituras essenciais para a visualização exclusiva do dashboard criado para o indicador criado. Entre elas estão algumas como:
-`Can read on Dashboard`
-`Can read on Chart`
-`Can read on Dataset`
-`Can read on Datasource`
-`datasource access on [ClickHouse teste].[Taxa atendimento - pnad_novo - glc22](id:27)`
Como podemos ver é necessário ter acesso a uma diversa gama de módulos do superset para poder visualizar o dashoard. Também é necessário que o usuário público tenha acesso ao dataset.
## Explorando o problema
Foi fácil perceber que o superset não restringe a chamadas de API vindas apenas de charts já criados, ou seja é possível analisar as requisições de API e executar uma query no dataset.
### 1. Entendendo como o chart faz a requisição
Para um chart obter os dados para manipular é feita uma requisição para o endpoint `http://{host}:8088/api/v1/chart/data`, a requisição deve der do formato especificado na documentação da API. As informações relevantes da requisição são
-`body`: Deve ser um objeto json
-`credentials`
-`hearders`
-`mode`
Dentro do objeto `body` o chart envia
-`queries`
-`form_data`
Onde `queries` armazena qual a query que deve ser feita pelo chart para
retornar os dados corretos para ele utilizar.
### 2. Extraindo informações da requisição de dados
Explorando as requisições feitas por um chart no debugger do browser é possível clonar a requisição utilizando o `fetch API` no console do browser.
Por exemplo, seja as informações necessárias para a requisição
Todas as informações foram retiradas da requisição feita por algum chart no dashboard. Para achar qual foi a requisição basta analisar os logs na aba de redes do DevTools e ver qual deles faz requisição para `'http://{host}:8088/api/v1/chart/data'`.
### 3. Alterando a requisição
Agora com as informações necessárias vamos alterar a variável `body_json.queries[0]`, para alterar como vai ser a query realizada no backend.
Se retirar o campo `metrics`, deixar vazio o campo `orderby` e deixar o campo `body_json.form_data` como `null` obtendo
```js
body_json={
"datasource":{
"id":27,
"type":"table"
},
"force":true,
"queries":[
{
"filters":[],
"extras":{
"having":"",
"where":""
},
"applied_time_extras":{},
"columns":[
"ANO",
"FAIXA_ETARIA"
],
"orderby":[],
"annotation_layers":[],
"row_limit":1000,
"series_limit":0,
"order_desc":false,
"url_params":{},
"custom_params":{},
"custom_form_data":{}
}
],
"form_data":null
"result_format":"json",
"result_type":"full"
}
```
Como essa nova configuração é possível realizar um query que envolve os dados brutos do dataset, sem nenhuma função de agregação.
#### Realizando a query com fetch API
Basta utilizar o `fetch API` no DevTools e pronto, os dados estão la
1. Colete os seus próprios dados para fazer esse teste, ou seja, pode ser que não funcione copiar e colar os exemplos. É necessário que sejam obtidos os dados da aba de Rede do DevTools par seguir com o experimento.
2. Leia a documentação da API do superset sobre o endpoint `/api/v1/chart/data` para descobrir mais sobre. No exemplo alteramos apenas `orderby` e `metrics`, entretanto é possível alterar `columns` e obter dados diferentes do dataset.
3. Mudando a variável `body_json.datasource.id` é possível obter dados sobre outros datasets que o usuário público tem acesso.
## Restrições para realizar a extração
Como dito anteriormente, para o usuário público ter acesso a um certo dashboard é necessário que ele tenha acesso aos datasets que aquele dashboard utiliza. Logo, não é possível utilizar o método apresentado em datasets que o usuário público tem acesso.
[^1]:Apresentação ilustrativa da métrica, não é realmente assim que define ela no dataset.