Cree una herramienta de analista de seguridad basada en wireshark: analice los resultados del análisis en suricata

A partir de este artículo, presentaré sucesivamente a través de varios artículos que en el proceso de la operación de seguridad real, crearé una herramienta de análisis de amenazas de tráfico para analistas de seguridad basada en wireshark, que ayudará a los analistas de seguridad a lograr análisis y análisis forense de paquetes de datos de red. el doble de resultado con la mitad del esfuerzo. Este documento presenta el uso de iwreshark para analizar los paquetes de datos y mostrar los datos de alarma de suricata en la interfaz de usuario.

Wireshark es la herramienta de análisis de paquetes más común. La ventaja de wireshark es que proporciona las capacidades de análisis de protocolo más amplias. La figura 1 a continuación muestra los tipos de protocolos admitidos por wireshark: Figura
inserte la descripción de la imagen aquí
1

Se puede ver que los tipos de protocolos admitidos son tan altos como 2000+. Wireshark puede analizar con precisión el protocolo, pero no tiene la capacidad de determinar si hay un problema en cada campo del protocolo y si un determinado proceso de sesión es normal. Para los analistas de seguridad, generalmente se enfocan en emitir juicios sobre la siguiente información:

  • Si la IP de destino y la IP de origen son normales, como los activos del atacante
  • Si existen riesgos en las URL en HTTP, por ejemplo, si existen riesgos como la ejecución de comandos, la inyección y el cruce de directorios.
  • Si el nombre de dominio de acceso es normal, por ejemplo, si es un nombre de dominio recién registrado
  • Si el certificado TLS es normal, por ejemplo, si es un certificado digital aplicado por una organización malintencionada.
  • Si los archivos transmitidos por HTTP, FTP, SMB y otros protocolos son normales, por ejemplo, si se está transmitiendo un archivo de virus.
  • ¿Existen riesgos en el protocolo SMB, como exploits psexec?

Tal vez los analistas experimentados puedan juzgar los ataques WEB comunes en función de las características de texto en protocolos como HTTP, como amenazas como varias inyecciones, ejecución de comandos y carga de archivos. Sin embargo, si existe un riesgo en la dirección IP, la propiedad del nombre de dominio, si el certificado es normal, si el archivo en transmisión es malicioso, si existen vulnerabilidades como Eternal Blue en el protocolo SMB, para la gran mayoría de seguridad. analistas, solo pueden confiar en la detección de dispositivos de seguridad. Sin embargo, las capacidades de cada dispositivo de seguridad son desiguales y, al mismo tiempo, es necesario tener en cuenta las falsas alarmas, por lo que las capacidades no pueden ser muy agresivas.

Por lo tanto, para los analistas de seguridad, por un lado, construya una herramienta de análisis de seguridad local para la verificación secundaria de paquetes de datos de alarma de dispositivos de seguridad, enriquezca la identificación de diferentes puntos de detección para paquetes de datos de alarma y mejore la confirmación de amenazas. Por otro lado, para algunos paquetes de datos que necesitan ser investigados, es muy útil usar herramientas de seguridad locales para analizar y descubrir amenazas potenciales.

Para la investigación y recopilación de pruebas de paquetes de datos, lo más importante es poder decodificar los paquetes de datos. Las ricas capacidades de análisis de protocolos de Wireshark son la primera opción. Para la detección de amenazas, los motores de detección de amenazas de código abierto en el campo de paquetes de datos incluyen suricata, snort y zeek.Para el uso de estos tres motores, consulte aquí . Para los analistas de seguridad, lo que se debe hacer es combinar la capacidad de análisis de protocolos de wireshark con la capacidad de análisis de amenazas de suricata. La idea general es muy simple: utilice la capacidad de complemento de wireshark para integrar los resultados del análisis suricata de los paquetes de datos, como se muestra en la Figura 2 a continuación:
inserte la descripción de la imagen aquí

Figura 2

Se puede ver que el resultado de la alarma de suricata se puede usar como la capa superior de toda la jerarquía del paquete de datos. La esencia es explicar los métodos de ataque, los tipos de amenazas y los niveles de amenazas existentes en el paquete de datos, para que los analistas puedan ser el primero en analizar y cambiar el tráfico Es hora de comprender el contexto del ataque. El código del complemento correspondiente es el siguiente, o vaya a este enlace para descargarlo:

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

Cabe señalar que, dado que se hace referencia al script lua de dkjson en el script, primero se debe descargar el script Lua al directorio local de wireshark, la dirección de descarga está aquí . O vaya a la descarga de github correspondiente, aquí .

La forma de cargar el complemento Lua es usar la línea de comando para abrir Wireshark, de la siguiente manera:

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

O configure el script modificado en init.lua para iniciarse automáticamente y agregue la siguiente configuración a init.lua:

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

Después de iniciar Wireshark, debe cargar el archivo de registro de Eve de Suricata, como se muestra en la Figura 3 a continuación para importar el registro de Suricata:
inserte la descripción de la imagen aquí


Después de cargar el registro de víspera correspondiente en la Figura 3 , el análisis de la información de alarma correspondiente se generará en la información experta, como se muestra en la Figura 4 a continuación:
inserte la descripción de la imagen aquí

Figura 4
La Figura 4 muestra toda la información del paquete de datos que activa una alarma, y ​​puede saltar al paquete de datos correspondiente seleccionando la alarma correspondiente. En la Figura 3, puede ver que el archivo que necesita ingresar es un archivo en formato suricata eve, el ejemplo es el siguiente:

{"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"}}

Puede ver que el script anterior analiza el tipo de evento en formato eve para alerta, http, dns, tls, smb y otros tipos. La cantidad de alarmas de tipo alerta depende de la riqueza de la base de reglas. Esta área de analistas de seguridad debe ser acumulada por individuos y deben definirse por sí mismos cuando sea necesario. Al mismo tiempo, el script también analiza los campos clave de HTTP, DNS, TLS, SMB y otros registros de protocolo, como se muestra en la Figura 2 anterior. En cuanto a cómo juzgar si hay un problema con estos campos y qué información más rica se puede obtener en base a estos campos, se presentarán artículos posteriores.

Para obtener información sobre cómo obtener el archivo de registro de Eve, puede consultar el artículo aquí . Cabe señalar que mucha información no se registra de forma predeterminada en el contenedor predeterminado de Dalton. Si desea registrar más información, debe modificar la configuración predeterminada en suricata.yaml. La Figura 6 a continuación muestra la información de configuración del valor md5 del archivo de registro, ver aquí .
inserte la descripción de la imagen aquí
En la Figura 6
, puede modificar los campos del archivo yaml de acuerdo con las necesidades reales.Después de generar el registro eve, puede modificar lua en consecuencia y analizar los campos correspondientes.

Cabe señalar que las reglas de detección de intrusiones están dirigidas principalmente a los puntos de tecnología de ataque con ciertos puntos de detección, como inyección SQL, ejecución de comandos y deserialización. Para funciones de amenazas como IOC, transferencia de archivos maliciosos y certificados maliciosos, aunque también se pueden escribir reglas de IDS, generalmente es más conveniente usar la forma de colisión de inteligencia de amenazas para la detección. grande y el cambio es relativamente rápido. , que se presentará en el próximo artículo.

Este artículo es un artículo original de los jóvenes del pueblo de CSDN, y no puede ser reproducido sin permiso. El blogger enlaza aquí .

Supongo que te gusta

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