Crie uma ferramenta de analista de segurança baseada em wireshark - analise os resultados da análise em suricata

A partir deste artigo, apresentarei sucessivamente através de vários artigos que, no processo de operação de segurança real, criarei uma ferramenta de análise de ameaças de tráfego para analistas de segurança baseada em wireshark, que ajudará os analistas de segurança a obter análises e análises forenses de pacotes de dados de rede. o dobro do resultado com metade do esforço. Este documento apresenta o uso do iwreshark para analisar os pacotes de dados e exibir os dados de alarme do suricata na IU.

Wireshark é a ferramenta de análise de pacotes mais comum. A vantagem do wireshark é que ele fornece os recursos de análise de protocolo mais abrangentes. A Figura 1 abaixo mostra os tipos de protocolos suportados pelo wireshark: Figura
insira a descrição da imagem aqui
1

Pode-se ver que os tipos de protocolos suportados são tão altos quanto 2000+. O Wireshark pode analisar o protocolo com precisão, mas não tem capacidade de determinar se há um problema em cada campo do protocolo e se um determinado processo de sessão é normal. Para os analistas de segurança, eles geralmente se concentram em fazer julgamentos sobre as seguintes informações:

  • Se o IP de destino e o IP de origem são normais, como ativos do invasor
  • Se há riscos em URLs em HTTP, como se há riscos como execução de comandos, injeção e travessia de diretório
  • Se o nome de domínio de acesso é normal, como se é um nome de domínio recém-registrado
  • Se o certificado TLS é normal, como se é um certificado digital aplicado por uma organização maliciosa
  • Se os arquivos transmitidos por HTTP, FTP, SMB e outros protocolos são normais, como se um arquivo de vírus está sendo transmitido
  • Existem riscos no protocolo SMB, como exploits psexec?

Talvez analistas experientes possam julgar ataques WEB comuns com base em recursos de texto em protocolos como HTTP, como ameaças como várias injeções, execução de comandos e uploads de arquivos. No entanto, se há risco no endereço IP, propriedade do nome de domínio, se o certificado é normal, se o arquivo em transmissão é malicioso, se há vulnerabilidades como o Eternal Blue no protocolo SMB, para a grande maioria das questões de segurança analistas, eles só podem confiar na detecção de dispositivos de segurança. No entanto, os recursos de cada dispositivo de segurança são desiguais e, ao mesmo tempo, falsos alarmes precisam ser levados em consideração, portanto, os recursos não podem ser muito agressivos.

Portanto, para analistas de segurança, por um lado, construir uma ferramenta de análise de segurança local para verificação secundária de pacotes de dados de alarme de dispositivos de segurança, enriquecer a identificação de diferentes pontos de detecção para pacotes de dados de alarme e aprimorar a confirmação de ameaças. Por outro lado, para alguns pacotes de dados que precisam ser investigados, é muito útil usar ferramentas de segurança local para analisar e descobrir possíveis ameaças.

Para a investigação e coleta de evidências de pacotes de dados, o mais importante é ser capaz de decodificar pacotes de dados. Os recursos avançados de análise de protocolo do Wireshark são a primeira escolha. Para detecção de ameaças, os mecanismos de detecção de ameaças de software livre no campo de pacote de dados incluem suricata, snort e zeek. Para o uso desses três mecanismos, consulte aqui . Para os analistas de segurança, o que precisa ser feito é combinar a capacidade de análise de protocolo do wireshark com a capacidade de análise de ameaças do suricata. A ideia geral é muito simples. Use o recurso de plug-in do wireshark para integrar os resultados da análise suricata dos pacotes de dados, conforme mostrado na Figura 2 abaixo:
insira a descrição da imagem aqui

Figura 2

Pode-se ver que o resultado do alarme de suricata pode ser usado como a camada superior de toda a hierarquia do pacote de dados. A essência é explicar os métodos de ataque, tipos de ameaças e níveis de ameaças existentes no pacote de dados, para que os analistas possam ser o primeiro a analisar e alterar o tráfego. Hora de entender o contexto do ataque. O código do plug-in correspondente é o seguinte ou acesse este link para fazer o download:

local ok, json = pcall(require, "cjson")
if not ok then
	json = require("dkjson")
end

--注册需要在wireshark UI上显示suricata eve文件中的信息,包括alert告警和主要协议信息
if (gui_enabled()) then 
	local suri_proto = Proto("suricata", "Suricata Analysis")
	local suri_sid = ProtoField.string("suricata.alert.sid", "SID", FT_INTEGER)
	local suri_msg = ProtoField.string("suricata.alert.msg", "Message", FT_STRING)
	local suri_category = ProtoField.string("suricata.alert.category", "Category", FT_INTEGER)
	local suri_severity = ProtoField.string("suricata.alert.severity", "Severity", FT_INTEGER)

	local suri_tls_subject = ProtoField.string("suricata.tls.subject", "TLS subject", FT_STRING)
	local suri_tls_issuerdn = ProtoField.string("suricata.tls.issuerdn", "TLS issuer DN", FT_STRING)
	local suri_tls_fingerprint = ProtoField.string("suricata.tls.fingerprint", "TLS fingerprint", FT_STRING)
	local suri_tls_version = ProtoField.string("suricata.tls.version", "TLS version", FT_STRING)

	local suri_ssh_client_version = ProtoField.string("suricata.ssh.client.version", "SSH client version", FT_STRING)
	local suri_ssh_client_proto = ProtoField.string("suricata.ssh.client.proto", "SSH client protocol", FT_STRING)
	local suri_ssh_server_version = ProtoField.string("suricata.ssh.server.version", "SSH server version", FT_STRING)
	local suri_ssh_server_proto = ProtoField.string("suricata.ssh.server.proto", "SSH server protocol", FT_STRING)

	local suri_fileinfo_filename = ProtoField.string("suricata.fileinfo.filename", "Fileinfo filename", FT_STRING)
	local suri_fileinfo_magic = ProtoField.string("suricata.fileinfo.magic", "Fileinfo magic", FT_STRING)
	local suri_fileinfo_md5 = ProtoField.string("suricata.fileinfo.md5", "Fileinfo md5", FT_STRING)
	local suri_fileinfo_sha1 = ProtoField.string("suricata.fileinfo.sha1", "Fileinfo sha1", FT_STRING)
	local suri_fileinfo_sha256 = ProtoField.string("suricata.fileinfo.sha256", "Fileinfo sha256", FT_STRING)
	local suri_fileinfo_size = ProtoField.string("suricata.fileinfo.size", "Fileinfo size", FT_INTEGER)
	local suri_fileinfo_stored = ProtoField.string("suricata.fileinfo.stored", "Fileinfo stored", FT_STRING)

	local suri_http_url = ProtoField.string("suricata.http.url", "HTTP URL", FT_STRING)
	local suri_http_hostname = ProtoField.string("suricata.http.hostname", "HTTP hostname", FT_STRING)
	local suri_http_user_agent = ProtoField.string("suricata.http.user_agent", "HTTP user agent", FT_STRING)
	local suri_http_content_type = ProtoField.string("suricata.http.content_type", "HTTP Content Type", FT_STRING)
	local suri_http_method = ProtoField.string("suricata.http.method", "HTTP Method", FT_STRING)
	local suri_http_protocol = ProtoField.string("suricata.http.protocol", "HTTP Protocol", FT_STRING)
	local suri_http_status = ProtoField.string("suricata.http.status", "HTTP Status", FT_STRING)
	local suri_http_length = ProtoField.string("suricata.http.length", "HTTP Length", FT_STRING)
	local suri_http_referer = ProtoField.string("suricata.http.referer", "HTTP Referer", FT_STRING)

	local suri_smb_command = ProtoField.string("suricata.smb.command", "SMB Command", FT_STRING)
	local suri_smb_filename = ProtoField.string("suricata.smb.filename", "SMB Filename", FT_STRING)
	local suri_smb_share = ProtoField.string("suricata.smb.share", "SMB Share", FT_STRING)
	local suri_smb_status = ProtoField.string("suricata.smb.status", "SMB Status", FT_STRING)

	local suri_prefs = suri_proto.prefs
	local suri_running = false

	local suri_alerts = {
    
    }

	local suricata_alert_expert_info = ProtoExpert.new("suricata.alert.expert","Suricata Alerts",expert.group.MALFORMED,expert.severity.WARN)
	local suricata_proto_expert_info = ProtoExpert.new("suricata.proto.expert","Suricata Proto Info",expert.group.DEBUG,expert.severity.NOTE)
	--注册分析下的专家信息
	suri_proto.experts = {
    
    suricata_alert_expert_info,suricata_proto_expert_info}

	suri_prefs.alert_file = Pref.string("EVE file", "/var/log/suricata/eve.json",
					    "EVE file containing information about pcap")
	suri_proto.fields = {
    
    suri_sid, suri_msg, suri_category, suri_severity, suri_tls_subject, suri_tls_issuerdn, suri_tls_fingerprint, suri_tls_version,
				suri_ssh_client_version, suri_ssh_client_proto, suri_ssh_server_version, suri_ssh_server_proto,
				suri_fileinfo_filename, suri_fileinfo_magic, suri_fileinfo_md5, suri_fileinfo_sha1, suri_fileinfo_sha256,
				suri_fileinfo_size, suri_fileinfo_stored, 
				suri_http_url, suri_http_hostname, suri_http_user_agent,
				suri_http_content_type, suri_http_method, suri_http_protocol, suri_http_status, suri_http_length, suri_http_referer,
				suri_smb_command, suri_smb_filename, suri_smb_share, suri_smb_status
				}

	
	--在解析每个数据包的同时,将已经解析的eve log数据按照数据包的序号为索引填充到已经注册的字段中
	function suri_proto.dissector(buffer,pinfo,tree)
		if not(suri_alerts[pinfo.number] == nil) then
			for i, val in ipairs(suri_alerts[pinfo.number]) do
				if val['sid'] then
					--print(val['sid'])
					subtree = tree:add(suri_proto,
							"Suricata alert: "..val['sid'].." ("..val['msg']..")")
					
					subtree:add(suri_sid, val['sid'])
					subtree:add(suri_msg, val['msg'])
					subtree:add(suri_category, val['category'])
					subtree:add(suri_severity, val['severity'])
					subtree:add_proto_expert_info(suricata_alert_expert_info, val['msg'])
				end
				if val['tls_subject'] then
					subtree = tree:add(suri_proto, "Suricata TLS Info")

					subtree:add(suri_tls_subject, val['tls_subject'])
					subtree:add(suri_tls_issuerdn, val['tls_issuerdn'])
					subtree:add(suri_tls_fingerprint, val['tls_fingerprint'])
					subtree:add(suri_tls_version, val['tls_version'])
					subtree:add_proto_expert_info(suricata_proto_expert_info, "TLS info")
				end
				if val['ssh_client_version'] then
					subtree = tree:add(suri_proto, "Suricata SSH Info")

					subtree:add(suri_ssh_client_version, val['ssh_client_version'])
					subtree:add(suri_ssh_client_proto, val['ssh_client_proto'])
					subtree:add(suri_ssh_server_version, val['ssh_server_version'])
					subtree:add(suri_ssh_server_proto, val['ssh_server_proto'])
					subtree:add_proto_expert_info(suricata_proto_expert_info, "SSH info")
				end
				if val['fileinfo_filename'] then
					subtree = tree:add(suri_proto, "Suricata File Info")

					subtree:add(suri_fileinfo_filename, val['fileinfo_filename'])
					if val['fileinfo_magic'] then
						subtree:add(suri_fileinfo_magic, val['fileinfo_magic'])
					end
					if val['fileinfo_md5'] then
						subtree:add(suri_fileinfo_md5, val['fileinfo_md5'])
					end
					if val['fileinfo_sha1'] then
						subtree:add(suri_fileinfo_sha1, val['fileinfo_sha1'])
					end
					if val['fileinfo_sha256'] then
						subtree:add(suri_fileinfo_sha256, val['fileinfo_sha256'])
					end
					subtree:add(suri_fileinfo_size, val['fileinfo_size'])
					if val['fileinfo_stored'] then
						subtree:add(suri_fileinfo_stored, val['fileinfo_stored'])
					end
					subtree:add_proto_expert_info(suricata_proto_expert_info, "File info")
				end
				if val['http_url'] then
					--print(val['http_url'])
					subtree = tree:add(suri_proto, "Suricata HTTP Info")
					-- add protocol fields to subtree
					subtree:add(suri_http_url, val['http_url'])
					if val['http_hostname'] then
						subtree:add(suri_http_hostname, val['http_hostname'])
					end
					if val['http_user_agent'] then
						subtree:add(suri_http_user_agent, val['http_user_agent'])
					end
					if val['http_content_type'] then
						subtree:add(suri_http_content_type, val['http_content_type'])
					end
					if val['http_method'] then
						subtree:add(suri_http_method, val['http_method'])
					end
					if val['http_protocol'] then
						subtree:add(suri_http_protocol, val['http_protocol'])
					end
					if val['http_status'] then
						subtree:add(suri_http_status, val['http_status'])
					end
					if val['http_length'] then
						subtree:add(suri_http_length, val['http_length'])
					end
					if val['http_referer'] then
						subtree:add(suri_http_referer, val['http_referer'])
					end

					subtree:add_proto_expert_info(suricata_proto_expert_info, "HTTP info")
				end
				if val['smb_command'] then
					subtree = tree:add(suri_proto, "Suricata SMB Info")
					subtree:add(suri_smb_command, val['smb_command'])
					if val['smb_filename'] then
						subtree:add(suri_smb_filename, val['smb_filename'])
					end
					if val['smb_share'] then
						subtree:add(suri_smb_share, val['smb_share'])
					end
					if val['smb_status'] then
						subtree:add(suri_smb_status, val['smb_status'])
					end
					subtree:add_proto_expert_info(suricata_proto_expert_info, "SMB info")
				end
		     end
	     end
	end

	function suri_proto.init()
	end

	-- 解析suricata eve log日志
	function ids_load_log(eve_file)
		function suricata_eve_log_parser(file)
			local event
			local id = 0
			local s_text = ""
			suri_alerts = {
    
    }
			for s_text in io.lines(file) do
				event = json.decode(s_text)
				id = event["pcap_cnt"]
				if not (id == nil) then
					if event["event_type"] == "alert" then
						if suri_alerts[id] == nil then
							suri_alerts[id] = {
    
    }
						end
						table.insert(suri_alerts[id],
							{
    
    category = event["alert"]["category"], sid = tonumber(event["alert"]["signature_id"]),
							severity = tonumber(event["alert"]["severity"]), msg = event["alert"]["signature"]})
					elseif event["event_type"] == "tls" then
						if suri_alerts[id] == nil then
							suri_alerts[id] = {
    
    }
						end
						table.insert(suri_alerts[id],
							{
    
     tls_subject = event["tls"]["subject"], tls_issuerdn = event["tls"]["issuerdn"],
							tls_fingerprint = event["tls"]["fingerprint"], tls_version = event["tls"]["version"]})
					elseif event["event_type"] == "ssh" then
						if suri_alerts[id] == nil then
							suri_alerts[id] = {
    
    }
						end
						table.insert(suri_alerts[id],
							{
    
     ssh_client_version = event["ssh"]["client"]["software_version"],
							ssh_client_proto = event["ssh"]["client"]["proto_version"],
							ssh_server_version = event["ssh"]["server"]["software_version"],
							ssh_server_proto = event["ssh"]["server"]["proto_version"],
							})
					elseif event["event_type"] == "fileinfo" then
						if suri_alerts[id] == nil then
							suri_alerts[id] = {
    
    }
						end
						table.insert(suri_alerts[id],
							{
    
     fileinfo_filename = event["fileinfo"]["filename"],
							  fileinfo_magic = event["fileinfo"]["magic"],
							  fileinfo_md5 = event["fileinfo"]["md5"],
							  fileinfo_sha1 = event["fileinfo"]["sha1"],
							  fileinfo_sha256 = event["fileinfo"]["sha256"],
							  fileinfo_size = tonumber(event["fileinfo"]["size"]),
							  fileinfo_stored = tostring(event["fileinfo"]["stored"]),
							})
					elseif event["event_type"] == "http" then
						if suri_alerts[id] == nil then
							suri_alerts[id] = {
    
    }
						end
						table.insert(suri_alerts[id],
							{
    
    
								http_url = event["http"]["url"],
								http_hostname = event["http"]["hostname"],
								http_user_agent = event["http"]["http_user_agent"],
								http_content_type = event["http"]["http_content_type"],
								http_method = event["http"]["http_method"],
								http_protocol = event["http"]["protocol"],
								http_status = event["http"]["status"],
								http_length = event["http"]["length"],
								http_referer = event["http"]["http_refer"]
							})
					elseif event["event_type"] == "smb" then
						if suri_alerts[id] == nil then
							suri_alerts[id] = {
    
    }
						end
						table.insert(suri_alerts[id],
							{
    
    
								smb_command = event["smb"]["command"],
								smb_filename = event["smb"]["filename"],
								smb_share = event["smb"]["share"],
								smb_status = event["smb"]["status"],
							})
					end
				end
			end
		end


		function suriwire_register(file)
			if file == "" then
				file = suri_prefs.alert_file
			end
			local filehandle = io.open(file, "r")

			if not (filehandle == nil) then
				filehandle:close()
				-- parse suricata log file
				suricata_eve_log_parser(file)
				-- register protocol dissector
				if suri_running == false then
					register_postdissector(suri_proto)
					suri_running = true
				end
				reload()
			else
				new_dialog("Unable to open '" .. file
					   .. "'. Choose another alert file",
					   suriwire_register,
					   "Choose file (Linux default:" .. suri_prefs.alert_file..")")
			end
		end
		-- run suricata
		-- set input file
		if eve_file then
			suriwire_register(eve_file)
		else
			new_dialog("Choose alert file",
			           suriwire_register,
			           "Choose file (Linux default:" .. suri_prefs.alert_file..")")
		end
	end

	function wireshark_page()
		browser_open_url("https://blog.csdn.net/javajiawei/category_9583097.html")
	end

	register_menu("导入入侵检测日志/导入Suricata日志", ids_load_log, MENU_TOOLS_UNSORTED)
	register_menu("Wireshark使用技巧", wireshark_page, MENU_TOOLS_UNSORTED)
	local eve_file = os.getenv("SURIWIRE_EVE_FILE")
	if eve_file then
		ids_load_log(eve_file)
	end
end

Deve-se observar que, como o script lua de dkjson é referenciado no script, o script Lua precisa ser baixado primeiro no diretório wireshark local, o endereço de download é aqui . Ou acesse o download do github correspondente, aqui .

A maneira de carregar o plug-in Lua é usar a linha de comando para abrir o wireshark, conforme a seguir:

wireshark -r test.pcap -X lua_script:suricata.lua

Ou configure o script modificado no init.lua para inicialização automática e adicione a seguinte configuração ao init.lua:

disable_lua = false--开启Lua解析
dofile(DATA_DIR.."suricata.lua")

Depois de iniciar o wireshark, você precisa carregar o arquivo de log do suricata, conforme mostrado na Figura 3 abaixo para importar o log do suricata:
insira a descrição da imagem aqui


Após o carregamento do log de véspera correspondente na Figura 3 , a análise das informações de alarme correspondentes será gerada nas informações do especialista, conforme Figura 4 abaixo:
insira a descrição da imagem aqui

Figura 4
A Figura 4 mostra todas as informações do pacote de dados que acionam um alarme, e você pode pular para o pacote de dados correspondente selecionando o alarme correspondente. Na Figura 3, você pode ver que o arquivo que precisa ser inserido é um arquivo no formato suricata eve. O exemplo é o seguinte:

{"timestamp":"2019-10-15T06:54:14.857081+0000","flow_id":1511806696075679,"pcap_cnt":351,"event_type":"alert","src_ip":"1.1.141.169","src_port":17725,"dest_ip":"1.2.61.25","dest_port":53,"proto":"TCP","alert":{"action":"allowed","gid":1,"signature_id":2030524,"rev":1,"signature":"ET INFO Possible NOP Sled Observed in Large DNS over TCP Packet M1","category":"Attempted Administrator Privilege Gain","severity":1,"metadata":{"affected_product":["Windows_DNS_server"],"created_at":["2020_07_15"],"former_category":["INFO"],"performance_impact":["Significant"],"signature_severity":["Informational"],"updated_at":["2020_07_15"]}},"flow":{"pkts_toserver":3,"pkts_toclient":1,"bytes_toserver":1638,"bytes_toclient":62,"start":"2019-10-15T06:54:14.700831+0000"}}
{"timestamp":"2019-10-15T06:54:14.872549+0000","flow_id":535741018300164,"pcap_cnt":372,"event_type":"dcerpc","src_ip":"1.1.171.176","src_port":7018,"dest_ip":"1.2.34.235","dest_port":6502,"proto":"TCP","dcerpc":{"request":"BIND","interfaces":[{"uuid":"62b93df0-8b02-11ce-876c-00805f842837","version":"1.0","ack_result":0}],"response":"BINDACK","call_id":0,"rpc_version":"5.0"}}
{"timestamp":"2019-10-15T06:54:14.902033+0000","flow_id":1632151679679309,"pcap_cnt":386,"event_type":"anomaly","src_ip":"1.2.33.242","src_port":80,"dest_ip":"1.1.30.100","dest_port":46189,"proto":"TCP","tx_id":0,"anomaly":{"app_proto":"http","type":"applayer","event":"INVALID_REQUEST_CHUNK_LEN","layer":"proto_parser"}}
{"timestamp":"2019-10-15T06:54:14.902033+0000","flow_id":1632151679679309,"pcap_cnt":386,"event_type":"http","src_ip":"1.1.30.100","src_port":46189,"dest_ip":"1.2.33.242","dest_port":80,"proto":"TCP","tx_id":0,"http":{"hostname":"pdfyoocaugsebmnhamlz","url":"/","http_method":"GET","protocol":"HTTP/1.1","length":0}}
{"timestamp":"2019-10-15T06:54:14.914528+0000","flow_id":535741018300164,"pcap_cnt":390,"event_type":"dcerpc","src_ip":"1.1.171.176","src_port":7018,"dest_ip":"1.2.34.235","dest_port":6502,"proto":"TCP","dcerpc":{"request":"REQUEST","req":{"opnum":43,"frag_cnt":1,"stub_data_size":20},"response":"RESPONSE","res":{"frag_cnt":1,"stub_data_size":8},"call_id":0,"rpc_version":"5.0"}}

Você pode ver que o script acima analisa o tipo de evento no formato de véspera para alerta, http, dns, tls, smb e outros tipos. O número de alarmes do tipo alerta depende da riqueza da base de regras. Essa área de analistas de segurança precisa ser acumulada por indivíduos e eles precisam ser definidos por eles mesmos quando necessário. Ao mesmo tempo, o script também analisa os campos-chave de HTTP, DNS, TLS, SMB e outros registros de protocolo, conforme mostrado na Figura 2 acima. Quanto a como julgar se há um problema com esses campos e quais informações mais ricas podem ser obtidas com base nesses campos, os artigos subsequentes apresentarão.

Para saber como obter o arquivo de log de véspera, você pode consultar o artigo, aqui . Deve-se observar que muitas informações não são gravadas por padrão no contêiner padrão do Dalton. Se você deseja registrar mais informações, é necessário modificar a configuração padrão em suricata.yaml. A Figura 6 abaixo mostra as informações de configuração do valor md5 do arquivo de registro, veja aqui .
insira a descrição da imagem aqui
Na Figura 6
, você pode modificar os campos do arquivo yaml de acordo com as necessidades reais.Após gerar o log de véspera, você pode modificar lua de acordo e analisar os campos correspondentes.

Deve-se notar que as regras de detecção de intrusão visam principalmente os pontos de tecnologia de ataque com determinados pontos de detecção, como injeção de SQL, execução de comandos, desserialização, etc. Para recursos de ameaças como IOC, transferência maliciosa de arquivos e certificados maliciosos, embora as regras IDS também possam ser escritas, geralmente é mais conveniente usar a forma de colisão de inteligência de ameaças para detecção. O principal motivo é que o número de recursos IOC é grande e a mudança é relativamente rápida. , que será apresentado no próximo artigo.

Este artigo é um artigo original dos jovens da vila de CSDN, e não pode ser reproduzido sem permissão. O blogger linka aqui .

Acho que você gosta

Origin blog.csdn.net/javajiawei/article/details/130176195
Recomendado
Clasificación