Visão geral
Um Credentials Feed entrega as credenciais expostas (logins vazados de colaboradores ou clientes) que a Plataforma Axur detecta. Um pequeno script no ServiceNow transforma cada credencial em um registro de Incidente, para que sua equipe possa redefinir a senha e acompanhar a resposta.
Figura 1: Os dois modos de entrega. Ambos usam o mesmo JSON e o mesmo script de mapeamento.
Push (Webhook 2.0): quase em tempo real
A Plataforma Axur envia as credenciais para um endpoint que você cria no ServiceNow. Sua instância precisa aceitar chamadas de entrada.
Pull (polling): mais fácil de aprovar
O ServiceNow consulta o feed a cada X minutos. O tráfego é somente de saída, e a latência é igual ao intervalo do agendamento.
Já usa o guia do Tickets Feed?
Este guia segue a mesma estrutura, com nomes de script próprios (AxurCredentialFeedMapper, axur.credentials_feed.url). As duas integrações podem funcionar lado a lado na mesma instância e podem compartilhar a mesma propriedade de API Key.
Pré-requisitos
Uma instância do ServiceNow e um usuário admin (ou
web_service_adminpara Push). Para testar antes, use uma Personal Developer Instance (PDI) gratuita em developer.servicenow.com. A URL dela tem o formatohttps://dev123456.service-now.com.Um usuário com perfil manager na Plataforma Axur para criar o feed.
Uma API Key da Plataforma Axur (somente Pull). Veja o "Get the API Key (Pull only)".
UI clássica vs. Next Experience
Os menus do ServiceNow são diferentes na interface clássica (UI16) e no Next Experience (menu All). Alguns atalhos, como digitar sys_properties.list no filtro, não funcionam em todas as versões. Cada passo abaixo também traz uma URL direta que funciona nas duas interfaces. Substitua <instance> pelo nome da sua instância, por exemplo dev123456.
URLs diretas usadas neste guia
O quê | URL direta |
Nova propriedade de sistema |
|
Lista de propriedades de sistema |
|
Novo Script Include |
|
Nova Scheduled Script Execution |
|
Nova Scripted REST API |
|
Incidentes criados pelo feed |
|
Logs do sistema |
|
Obter o feed e a API Key na Plataforma Axur
Faça este passo primeiro. O Pull precisa da URL do feed e da API Key antes de você criar qualquer coisa no ServiceNow.
Criar o feed
Acesse one.axur.com/api-integrations → seção Feeds → Add feed. Você pode escolher o template Employee credentials ou User credentials, ou clicar em Skip templates.
Escolha o tipo Credentials.
Escolha o modo de entrega: Pull ou Push. Para Push, informe a URL do endpoint que você vai criar no passo 6.
O campo Event date já vem preenchido com a data de criação (
created). Cada credencial chega uma única vez, quando a Plataforma Axur a detecta pela primeira vez.Em Feed parameters, escolha quais credenciais receber. Combine filtros com
&:Recomendado: adicione também o parâmetro
fieldsmostrado abaixo. Assim o feed retorna apenas o que o script usa, e as senhas nunca saem da Plataforma Axur:fields=id,created,detectionDate,customer,assets,status,credential.types,user,user.type,access.url,source.name
Exemplo combinado com um filtro:
credential.types=employee&fields=id,created,…Defina um título, por exemplo “ServiceNow – Credenciais expostas”, e salve.
Copie a URL do feed exibida para o feed na lista. Ela tem o formato
https://api.axur.com/gateway/1.0/api/integration-feed/feeds/feed/<ID>.
Figura 2: Configuração sugerida do feed (ilustração; a tela real pode ser diferente).
Obter a API Key (somente Pull)
Na Plataforma Axur, abra My Preferences → aba API KEY.
Crie uma nova chave e copie-a imediatamente. Guarde-a em um gerenciador de senhas até criar a propriedade no ServiceNow no passo "Armazenar a URL e a API Key".
A chave pertence ao usuário que a criou
A chave só enxerga o que esse usuário pode ver na Plataforma Axur. Se o usuário for desativado, bloqueado ou removido, a chave é revogada e o job começa a falhar com 401 Unauthorized. Crie a chave com um usuário que tenha acesso às credenciais e que não será desativado, como um usuário de integração dedicado. Nunca compartilhe a chave nem a escreva em scripts.
Mapeamento de campos
Cada item em collectionData.detections[] vira um registro na tabela Incident. As cores mostram de onde vem cada informação:
Tabela de mapeamento
Campo do ServiceNow | Origem no JSON | Observações |
|
| Definido somente na criação. Atualizações não reabrem o incidente. |
|
| Usado para evitar duplicatas. |
|
|
|
| Data Leakage - Tipo - | Limitado a 160 caracteres: somente a parte de usuário/URL é encurtada (com |
| Modelo da Figura 3b | Link: |
Rótulos de tipo de credencial
| Rótulo no Incidente |
| Employee credential exposed |
| User credential exposed |
ambos | Employee and User credential exposed |
A senha nunca é gravada no ServiceNow
O script não copia a senha para o Incidente, mesmo que o feed a envie. Incidentes ficam visíveis para muitas pessoas e são mantidos por muito tempo, então armazenar senhas expostas neles criaria um novo vazamento. Sua equipe pode ver a detecção completa na Plataforma Axur pelo link na descrição.
Atenção às chaves com ponto
Campos como access.url e credential.types têm um ponto no nome. Em JavaScript, use colchetes: d['access.url'], e não d.access.url.
Script Include: o mapeador
Este script monta os campos e cria ou atualiza o incidente. Você o cria uma única vez, e tanto o Push quanto o Pull o utilizam.
Abra
https://<instance>.service-now.com/sys_script_include.do?sys_id=-1. Pelo menu, o caminho é System Definition › Script Includes → New.Name:
AxurCredentialFeedMapper(precisa ser exatamente este nome).Cole o código abaixo no campo Script e salve.
var AxurCredentialFeedMapper = {
TABLE: 'incident',
CREDENTIALS_URL: 'https://one.axur.com/data-leakage/credentials',
SHORT_DESCRIPTION_LIMIT: 160,
WORKSPACE: 'Data Leakage',
TYPE_LABELS: {
'employee': 'Employee',
'user': 'User'
},
buildFields: function (item) {
var id = item.id;
var customer = item.customer || '';
var user = item.user || '';
var accessUrl = item['access.url'] || '';
var typeLabel = this.typeLabel(item['credential.types'] || []);
var prefix = this.WORKSPACE + ' - ' + typeLabel + ' credential exposed - ' + customer + ' - ';
var target = accessUrl ? user + ' @ ' + accessUrl : user;
var shortDescription = prefix + this.fit(target, prefix.length);
var link = this.CREDENTIALS_URL + '?customerId=' + encodeURIComponent(customer)
+ '&text=' + encodeURIComponent(id);
var description = [
'Axur - one.axur.com',
'',
'New credential exposure detected (' + link + ')',
'',
'Detection ID: ' + id,
this.assetsLine(item.assets || []),
'Credential Type: ' + typeLabel,
'User: ' + user + (item['user.type'] ? ' (' + item['user.type'] + ')' : ''),
'Access URL: ' + accessUrl,
'Source: ' + (item['source.name'] || ''),
'Status: ' + (item.status || ''),
'Detection Date: ' + this.formatDate(item.detectionDate || item.created)
].join('\n');
return { id: id, shortDescription: shortDescription, description: description };
},
typeLabel: function (types) {
var labels = [];
for (var i = 0; i < types.length; i++) {
labels.push(this.TYPE_LABELS[types[i]] || types[i]);
}
return labels.length ? labels.join(' and ') : 'Unknown';
},
fit: function (text, usedLength) {
var available = this.SHORT_DESCRIPTION_LIMIT - usedLength;
if (text.length <= available) return text;
return text.substring(0, Math.max(available - 3, 0)) + '...';
},
assetsLine: function (assets) {
if (assets.length === 0) return 'Asset: -';
return assets.length === 1 ? 'Asset: ' + assets[0] : 'Assets: (' + assets.join(', ') + ')';
},
formatDate: function (iso) {
if (!iso) return '';
return iso.substring(8, 10) + '/' + iso.substring(5, 7) + '/' + iso.substring(0, 4);
},
upsert: function (item) {
var f = this.buildFields(item);
if (!f.id) return;
var gr = new GlideRecord(this.TABLE);
gr.addQuery('correlation_id', f.id);
gr.query();
var exists = gr.next();
if (!exists) {
gr.initialize();
gr.state = 1;
}
gr.correlation_id = f.id;
gr.correlation_display = f.id;
gr.short_description = f.shortDescription;
gr.description = f.description;
if (exists) { gr.update(); } else { gr.insert(); }
},
processPayload: function (payload) {
var detections = (payload && payload.collectionData && payload.collectionData.detections) || [];
for (var i = 0; i < detections.length; i++) {
this.upsert(detections[i]);
}
return detections.length;
}
};Opção A: Pull com um Scheduled Job
Escolha esta opção se a sua instância não pode receber chamadas externas.
Armazenar a URL e a API Key
Antes de começar: tenha em mãos a URL do feed e a API Key.
Abra diretamente o formulário de nova propriedade:
https://<instance>.service-now.com/sys_properties.do?sys_id=-1. Você também pode abrirsys_properties_list.doe clicar em New.Crie a propriedade da URL do feed:
Se
axur.feed.api_keyainda não existir (ela é compartilhada com a integração do Tickets Feed), abra o formulário novamente e crie-a:
Segurança
Nunca escreva a API Key diretamente no script. Se a sua equipe de segurança preferir, use Connection & Credential Aliases em vez da propriedade de sistema.
Criar o agendamento
Abra
https://<instance>.service-now.com/sysauto_script.do?sys_id=-1. Pelo menu, o caminho é System Definition › Scheduled Jobs → New → Automatically run a script of your choosing.Name:
Axur Credentials Feed → Incident. Run: Periodically. Repeat interval:00:05:00(5 min).Cole o script abaixo e salve.
Figura 4: Scheduled Job executado a cada 5 minutos (ilustração).
var FEED_URL = gs.getProperty('axur.credentials_feed.url');
var API_KEY = gs.getProperty('axur.feed.api_key');
var MAX_PAGES = 20;
for (var page = 0; page < MAX_PAGES; page++) {
var request = new sn_ws.RESTMessageV2();
request.setEndpoint(FEED_URL);
request.setHttpMethod('GET');
request.setRequestHeader('Authorization', 'Bearer ' + API_KEY);
request.setRequestHeader('Accept', 'application/json');
var response = request.execute();
if (response.getStatusCode() != 200) {
gs.error('Axur credentials feed: HTTP ' + response.getStatusCode() + ' - ' + response.getBody());
break;
}
var processed = AxurCredentialFeedMapper.processPayload(JSON.parse(response.getBody()));
if (processed === 0 || FEED_URL.indexOf('dry-run=true') > -1) break;
}
Cada chamada ao feed avança o ponteiro e retorna o próximo lote. O loop continua até que um lote volte vazio, com limite de 20 chamadas por execução para que o job nunca trave. No modo dry-run o ponteiro não avança, então o job faz uma única chamada por execução.
Opção B: Push com uma Scripted REST API
Escolha esta opção para receber credenciais quase em tempo real. Sua instância precisa aceitar chamadas de entrada da Plataforma Axur.
Abra
https://<instance>.service-now.com/sys_ws_definition.do?sys_id=-1. Pelo menu, o caminho é System Web Services › Scripted Web Services › Scripted REST APIs → New.Name:
Axur Credentials Feed, API ID:axur_credentials_feed. Salve.Na aba Resources → New: Name
credentials, HTTP methodPOST, Relative path/credentials.Cole o script abaixo no resource e salve.
Copie o Resource path (por exemplo
https://<instance>.service-now.com/api/<scope>/axur_credentials_feed/credentials) e informe-o como endpoint do feed Push na Plataforma Axur.
(function process(request, response) {
var processed = AxurCredentialFeedMapper.processPayload(request.body.data);
response.setStatus(200);
response.setBody({ processed: processed });
})(request, response);
Autenticação do endpoint
Por padrão, o resource exige autenticação do ServiceNow (Requires authentication). Não a desative. Em vez disso, faça a Plataforma Axur se autenticar em cada chamada:
No ServiceNow, crie um usuário de integração dedicado (por exemplo
axur.integration) apenas com as roles necessárias para criar e atualizar incidentes.Ao configurar o feed Push na Plataforma Axur, adicione um header personalizado com as credenciais desse usuário:
Authorization: Basic <base64 de usuário:senha>. A Plataforma Axur envia seus headers personalizados em todas as requisições.
Opcional: verificar a assinaturaToda requisição Push também traz um header X-Push-Signature: um HMAC-SHA256 do corpo bruto da requisição, codificado em hexadecimal e calculado com a chave secreta do feed Push. Valide-o no resource se a sua equipe de segurança exigir prova de que a chamada veio da Plataforma Axur.
Teste de conexão
Quando você salva ou testa o feed Push, a Plataforma Axur envia um corpo vazio ({}). O script responde 200 com processed: 0 e não cria nada.
Testar e validar
Ative o dry-run temporariamente: abra a propriedade
axur.credentials_feed.url(sys_properties_list.do, busque pelo nome) e adicione?dry-run=trueao final do Value, por exemplohttps://api.axur.com/gateway/1.0/api/integration-feed/feeds/feed/<ID>?dry-run=true. Salve. Agora o feed retorna as mesmas credenciais em todas as chamadas e o ponteiro não avança, então nada se perde durante o teste.Execute o job manualmente: abra o Scheduled Job → Execute Now.
Confira os incidentes em
incident_list.do?sysparm_query=correlation_idISNOTEMPTY. Confirme que nenhuma senha aparece no Incidente.Execute novamente. Graças ao upsert, o número de incidentes não deve aumentar.
Verifique erros em
syslog_list.doou em System Logs › Errors (mensagens que começam comAxur credentials feed:).Tudo certo? Edite
axur.credentials_feed.urlnovamente e remova?dry-run=truedo valor, para que o ponteiro comece a avançar.
Dica
Valide em uma instância de subprodução ou de desenvolvimento antes de ativar em produção. Um feed sem filtros pode trazer muitas credenciais na primeira execução; comece com um filtro (por exemplo credential.types=employee) se você espera um volume grande.
Notas de segurança e checklist
Tema | Recomendação |
Senhas | Nunca são armazenadas no ServiceNow. Use o parâmetro |
Quem vê os incidentes | Credenciais expostas são dados pessoais. Atribua os incidentes a um grupo restrito (por exemplo, com uma regra de Assignment group) em vez da fila geral. |
API Key | Armazenada como |
Checklist para entrar em produção
Credentials Feed criado na Plataforma Axur com os filtros corretos e o parâmetro
fieldsScript Include
AxurCredentialFeedMappercriadoPull: propriedades
axur.credentials_feed.urleaxur.feed.api_keycriadasPull: Scheduled Job ativo · Push: endpoint registrado no feed
Testado com
?dry-run=trueemaxur.credentials_feed.url, sem duplicatas e sem senhas no Incidente?dry-run=trueremovido deaxur.credentials_feed.url







