{"id":208632,"date":"2024-02-05T15:51:35","date_gmt":"2024-02-05T15:51:35","guid":{"rendered":"https:\/\/www.ninjaone.com\/script-hub\/intentos-de-inicio-de-sesion-fallidos\/"},"modified":"2024-03-04T19:19:21","modified_gmt":"2024-03-04T19:19:21","slug":"intentos-de-inicio-de-sesion-fallidos","status":"publish","type":"script_hub","link":"https:\/\/www.ninjaone.com\/es\/script-hub\/intentos-de-inicio-de-sesion-fallidos\/","title":{"rendered":"C\u00f3mo encontrar los intentos de inicio de sesi\u00f3n fallidos en Windows usando PowerShell"},"content":{"rendered":"<p>Garantizar la seguridad de los sistemas inform\u00e1ticos es una tarea crucial. Identificar actividades sospechosas, como numerosos intentos fallidos de inicio de sesi\u00f3n, es una medida importante para reducir el riesgo de posibles amenazas. El script proporcionado escrito en PowerShell sirve como herramienta vers\u00e1til para ayudar a los profesionales de TI y MSP a encontrar <strong>informaci\u00f3n sobre los intentos de inicio de sesi\u00f3n fallidos<\/strong>.<\/p>\n<h2>Antecedentes<\/h2>\n<p>Conocer los intentos de inicio de sesi\u00f3n fallidos en un sistema puede proporcionar informaci\u00f3n important\u00edsima para los administradores de TI que permita detectar posibles fallos de seguridad, controlar los comportamientos de los usuarios y mantener la integridad del sistema. El script PowerShell proporcionado obtiene estos datos de forma eficaz, ofreciendo una soluci\u00f3n s\u00f3lida para los profesionales. Debemos insistir en la importancia de esta herramienta. Con el aumento de las amenazas a la ciberseguridad, disponer de un m\u00e9todo eficaz para detectar anomal\u00edas en los inicios de sesi\u00f3n de los usuarios se convierte en algo esencial para los MSP y los profesionales de TI.<\/p>\n<h2>El script para encontrar los intentos de inicio de sesi\u00f3n fallidos en Windows<\/h2>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\">#Requires -Version 3.0 -RunAsAdministrator\r\n\r\n&lt;#\r\n.SYNOPSIS\r\n    Returns the number of recent failed login attempts.\r\n.DESCRIPTION\r\n    Returns the number of recent failed login attempts of all users or of a specific user. If a user is specified then just a number is returned.\r\n.EXAMPLE\r\n    No parameters needed.\r\n    Returns all users, of the local machine, with a could of failed login attempts.\r\nOutput Example:\r\nUserName  FailedLoginAttempts\r\n--------  -------------------\r\nFred                        4\r\nBob                         0\r\n.EXAMPLE\r\n     -UserName \"Fred\"\r\n    Returns the number of failed login attempts of the user Fred on the local machine.\r\nOutput Example:\r\n4\r\n.EXAMPLE\r\n     -ComputerName \"FredPC\" -UserName \"Fred\"\r\n    Returns the number of failed login attempts of the user Fred on the computer named FredPC.\r\nOutput Example:\r\n4\r\n.EXAMPLE\r\n     -ComputerName \"FredPC\" -UserName \"Fred\" -Detailed\r\n    Returns the number of failed login attempts of the user Fred on the computer named FredPC, but will more details of each failed and successful logins.\r\nOutput Example:\r\n\r\nTimeGenerated   : 10\/18\/2019 7:52:43 AM\r\nEventID         : 4624\r\nCategory        : 12544\r\nADUsername      : Fred\r\nDomain          : FredPC\r\nUserSID         : S-1-0-0\r\nWorkstation     : -\r\nSourceIP        : -\r\nPort            : -\r\nFailureReason   : Interactive\r\nFailureStatus   : Incorrect password\r\nFailureSubStatus: Other\r\n.EXAMPLE\r\n    PS C:&gt; Monitor-Failed-Password-Attempts.ps1 -ComputerName \"FredPC\" -UserName \"Fred\"\r\n    Returns the number of failed login attempts of the user Fred on the computer named FredPC.\r\nOutput Example:\r\n4\r\n.OUTPUTS\r\n    System.Int32 Number of failed login attempts.\r\n.OUTPUTS\r\n    PSCustomObject List of user names and a count of failed login attempts.\r\n.NOTES\r\n    Minimum OS Architecture Supported: Windows 7, Windows Server 2012\r\n    If ComputerName is specified, then be sure that the computer that this script is running on has network and permissions to access the Event Log on the remote computer.\r\n    Release Notes:\r\n    Initial Release\r\nBy using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https:\/\/www.ninjaone.com\/terms-of-use.\r\n    Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. \r\n    Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. \r\n    Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. \r\n    Warranty Disclaimer: The script is provided \u201cas is\u201d and \u201cas available\u201d, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. \r\n    Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. \r\n    Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. \r\n    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).\r\n.COMPONENT\r\n    ManageUsers\r\n#&gt;\r\n\r\nparam (\r\n    # The name of a remote computer to get event logs for failed logins\r\n    [Parameter(Mandatory = $false)]\r\n    [String]\r\n    $ComputerName = [System.Net.Dns]::GetHostName(),\r\n    # A username\r\n    [Parameter(Mandatory = $false)]\r\n    [String]\r\n    $UserName,\r\n    # Returns all relevant events, sorted by TimeGenerated\r\n    [Switch]\r\n    $Detailed\r\n)\r\n\r\n# Support functions\r\n# Returns the matching FailureReason like Incorrect password\r\nfunction Get-FailureReason {\r\n    Param($FailureReason)\r\n    switch ($FailureReason) {\r\n        '0xC0000064' { \"Account does not exist\"; break; }\r\n        '0xC000006A' { \"Incorrect password\"; break; }\r\n        '0xC000006D' { \"Incorrect username or password\"; break; }\r\n        '0xC000006E' { \"Account restriction\"; break; }\r\n        '0xC000006F' { \"Invalid logon hours\"; break; }\r\n        '0xC000015B' { \"Logon type not granted\"; break; }\r\n        '0xc0000070' { \"Invalid Workstation\"; break; }\r\n        '0xC0000071' { \"Password expired\"; break; }\r\n        '0xC0000072' { \"Account disabled\"; break; }\r\n        '0xC0000133' { \"Time difference at DC\"; break; }\r\n        '0xC0000193' { \"Account expired\"; break; }\r\n        '0xC0000224' { \"Password must change\"; break; }\r\n        '0xC0000234' { \"Account locked out\"; break; }\r\n        '0x0' { \"0x0\"; break; }\r\n        default { \"Other\"; break; }\r\n    }\r\n}\r\nfunction Get-LogonType {\r\n    Param($LogonType)\r\n    switch ($LogonType) {\r\n        '0' { 'Interactive'; break; }\r\n        '2' { 'Interactive'; break; }\r\n        '3' { 'Network'; break; }\r\n        '4' { 'Batch'; break; }\r\n        '5' { 'Service'; break; }\r\n        '6' { 'Proxy'; break; }\r\n        '7' { 'Unlock'; break; }\r\n        '8' { 'Networkcleartext'; break; }\r\n        '9' { 'NewCredentials'; break; }\r\n        '10' { 'RemoteInteractive'; break; }\r\n        '11' { 'CachedInteractive'; break; }\r\n        '12' { 'CachedRemoteInteractive'; break; }\r\n        '13' { 'CachedUnlock'; break; }\r\n        Default {}\r\n    }\r\n}\r\n#-Newest $Records\r\n$Events = Get-EventLog -ComputerName $ComputerName -LogName 'security' -InstanceId 4625, 4624 | Sort-Object -Property TimeGenerated | ForEach-Object {\r\n    if ($_.InstanceId -eq 4625) {\r\n        $_ | Select-Object -Property @(\r\n            @{Label = 'TimeGenerated'; Expression = { $_.TimeGenerated } },\r\n            @{Label = 'EventID'; Expression = { $_.InstanceId } },\r\n            @{Label = 'Category'; Expression = { $_.CategoryNumber } },\r\n            @{Label = 'Username'; Expression = { $_.ReplacementStrings[5] } },\r\n            @{Label = 'Domain'; Expression = { $_.ReplacementStrings[6] } },\r\n            @{Label = 'UserSID'; Expression = { (($_.Message -Split 'rn' | Select-String 'Security ID')[1] -Split 's+')[3] } },\r\n            # @{Label = 'UserSID'; Expression = { $_.ReplacementStrings[0] } },\r\n            @{Label = 'Workstation'; Expression = { $_.ReplacementStrings[13] } },\r\n            @{Label = 'SourceIP'; Expression = { $_.ReplacementStrings[19] } },\r\n            @{Label = 'Port'; Expression = { $_.ReplacementStrings[20] } },\r\n            @{Label = 'LogonType'; Expression = { $_.ReplacementStrings[8] } },\r\n            @{Label = 'FailureStatus'; Expression = { Get-FailureReason($_.ReplacementStrings[7]) } },\r\n            @{Label = 'FailureSubStatus'; Expression = { Get-FailureReason($_.ReplacementStrings[9]) } }\r\n        )\r\n    }\r\n    elseif ($_.InstanceId -eq 4624 -and (Get-LogonType($_.ReplacementStrings[8])) -notlike 'Service') {\r\n        $_ | Select-Object -Property @(\r\n            @{Label = 'TimeGenerated'; Expression = { $_.TimeGenerated } },\r\n            @{Label = 'EventID'; Expression = { $_.InstanceId } },\r\n            @{Label = 'Category'; Expression = { $_.CategoryNumber } },\r\n            @{Label = 'Username'; Expression = { $_.ReplacementStrings[5] } },\r\n            @{Label = 'Domain'; Expression = { $_.ReplacementStrings[6] } },\r\n            @{Label = 'UserSID'; Expression = { $_.ReplacementStrings[0] } },\r\n            @{Label = 'Workstation'; Expression = { $_.ReplacementStrings[11] } },\r\n            @{Label = 'SourceIP'; Expression = { $_.ReplacementStrings[18] } },\r\n            @{Label = 'Port'; Expression = { $_.ReplacementStrings[19] } },\r\n            @{Label = 'LogonType'; Expression = { Get-LogonType($_.ReplacementStrings[8]) } },\r\n            @{Label = 'LogonID'; Expression = { Get-FailureReason($_.ReplacementStrings[7]) } },\r\n            @{Label = 'LogonProcess'; Expression = { Get-FailureReason($_.ReplacementStrings[9]) } }\r\n        )\r\n    }\r\n}\r\n\r\nif ($Detailed) {\r\n    if ($UserName) {\r\n        $Events | Where-Object {\r\n            $_.Username -like $UserName\r\n        }\r\n    }\r\n    else {\r\n        $Events | Where-Object {\r\n            $_.Username -notlike \"DWM*\" -and\r\n            $_.Username -notlike \"UMFD*\" -and\r\n            $_.Username -notlike \"SYSTEM\"\r\n        }\r\n    }\r\n}\r\nelse {\r\n    $UserNames = if ($UserName) {\r\n        ($Events | Select-Object -Property Username -Unique).Username | Where-Object {\r\n            $_ -like \"$UserName\"\r\n        }\r\n    }\r\n    else {\r\n        ($Events | Select-Object -Property Username -Unique).Username | Where-Object {\r\n            $_ -notlike \"DWM*\" -and\r\n            $_ -notlike \"UMFD*\" -and\r\n            $_ -notlike \"SYSTEM\"\r\n        }\r\n    }\r\n    \r\n    $UserNames | ForEach-Object {\r\n        $CurrentUserName = $_\r\n        $FailedLoginCount = 0\r\n        for ($i = 0; $i -lt $Events.Count; $i++) {\r\n            if ($Events[$i].EventID -eq 4625 -and $Events[$i].Username -like $CurrentUserName) {\r\n                # User failed to login X times\r\n                # Count the number of failed logins\r\n                $FailedLoginCount++\r\n            }\r\n            elseif ($Events[$i].EventID -eq 4624 -and $Events[$i].Username -like $CurrentUserName) {\r\n                # User logged in successfully\r\n                # Reset the number of failed logins to 0\r\n                $FailedLoginCount = 0\r\n            }\r\n        }\r\n        if ($UserName) {\r\n            # If a UserName was specified, then return only the failed login count\r\n            $FailedLoginCount\r\n        }\r\n        else {\r\n            # If no UserName was specified, then return the user name and failed login count\r\n            [PSCustomObject]@{\r\n                UserName            = $CurrentUserName\r\n                FailedLoginAttempts = $FailedLoginCount\r\n            }\r\n        }\r\n    }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n\n<div class=\"in-context-cta\"><p>Accede a m\u00e1s de 300 scripts en el Dojo de NinjaOne<\/p>\n<p><a href=\"https:\/\/www.ninjaone.com\/es\/prueba-gratuita-formulario\/\">Obt\u00e9n acceso<\/a><\/p>\n<\/div>\n<h2>Desglose detallado del script<\/h2>\n<p>En esencia, el script obtiene datos de los registros de eventos de un equipo determinado, buscando ID de eventos espec\u00edficos que representan intentos de inicio de sesi\u00f3n fallidos y finalizados con \u00e9xito.<\/p>\n<ul>\n<li><strong>Par\u00e1metros<\/strong>: el script comienza definiendo par\u00e1metros como <strong>ComputerName<\/strong>, <strong>UserName<\/strong> y <strong>Detailed<\/strong>. Esto permite al usuario especificar la m\u00e1quina, el usuario y el nivel de detalle de los intentos de inicio de sesi\u00f3n.<\/li>\n<li><strong>Funciones<\/strong>: dos funciones, <strong>Get-FailureReason<\/strong> y <strong>Get-LogonType<\/strong>, traducen la informaci\u00f3n codificada de los registros de eventos en datos legibles por humanos sobre el tipo de inicio de sesi\u00f3n y el motivo de un inicio de sesi\u00f3n fallido.<\/li>\n<li><strong>Recuperaci\u00f3n de eventos<\/strong>: entonces, el script recupera los registros de eventos y los filtra para conservar s\u00f3lo la informaci\u00f3n necesaria. Esto implica seleccionar las instancias con los ID de evento pertinentes.<\/li>\n<li><strong>Procesamiento<\/strong>: si se solicitan datos detallados, el script proporciona un desglose completo de cada uno de los intentos de inicio de sesi\u00f3n o un resumen de los intentos de inicio de sesi\u00f3n fallidos de cada usuario.<\/li>\n<\/ul>\n<h2>Posibles casos de uso<\/h2>\n<p>Imag\u00ednate un administrador de TI en una empresa mediana. Recientemente, el departamento de TI ha observado un aumento en el n\u00famero de intentos de inicio de sesi\u00f3n fallidos, especialmente en horas no laborables. Utilizando el script, el administrador puede comprobar r\u00e1pidamente qu\u00e9 usuarios han tenido intentos de inicio de sesi\u00f3n fallidos y con qu\u00e9 frecuencia. Al descubrir que una sola cuenta de usuario ha tenido varios intentos de inicio de sesi\u00f3n fallidos en un corto espacio de tiempo, el administrador puede concluir que esta cuenta puede haber sido un blanco. En este sentido, el script favorece la detecci\u00f3n precoz de un problema y una pronta correcci\u00f3n.<\/p>\n<h2>Enfoque alternativo<\/h2>\n<p>Existen varios m\u00e9todos para realizar un seguimiento de los intentos de inicio de sesi\u00f3n fallidos. La auditor\u00eda de seguridad integrada en Windows, por ejemplo, permite ver los registros de seguridad a trav\u00e9s del Visor de eventos. Aunque este enfoque es sencillo, puede llevar mucho tiempo. Nuestro script PowerShell agiliza el proceso, ofreciendo una soluci\u00f3n m\u00e1s eficaz y personalizable.<\/p>\n<h2>Preguntas frecuentes<\/h2>\n<ul>\n<li>\u00bfC\u00f3mo identifica el script un evento de inicio de sesi\u00f3n fallido?<br \/>\nEl script busca ID de eventos espec\u00edficos en el registro de eventos, por ejemplo 4625 para inicios de sesi\u00f3n fallidos.<\/li>\n<li>\u00bfPuedo obtener datos de un equipo remoto?<br \/>\nS\u00ed, proporcionando el par\u00e1metro <strong>ComputerName<\/strong>, puedes obtener datos de un ordenador remoto.<\/li>\n<\/ul>\n<h2>Implicaciones<\/h2>\n<p>Al conocer el n\u00famero de intentos de inicio de sesi\u00f3n fallidos, los administradores de TI pueden anticiparse a posibles brechas de seguridad. Las anomal\u00edas en los patrones de inicio de sesi\u00f3n suelen ser una se\u00f1al temprana de actividad maliciosa. Por tanto, actuando sobre la base de estos datos, los profesionales pueden reforzar sus sistemas frente a posibles amenazas.<\/p>\n<h2>Recomendaciones<\/h2>\n<ul>\n<li>Aseg\u00farate de que dispones de los permisos necesarios para obtener registros de eventos.<\/li>\n<li>Ejecuta el script con regularidad, especialmente en el caso de sistemas que contengan informaci\u00f3n confidencial.<\/li>\n<li>Investiga cualquier patr\u00f3n de intentos de inicio de sesi\u00f3n fallidos y notif\u00edcalo a los usuarios afectados.<\/li>\n<\/ul>\n<h2>Reflexiones finales<\/h2>\n<p>En la era de las crecientes amenazas cibern\u00e9ticas, herramientas como nuestro script PowerShell para conocer el n\u00famero de intentos de inicio de sesi\u00f3n fallidos son esenciales. Para obtener una soluci\u00f3n de seguridad completa, se pueden integrar plataformas como NinjaOne, que garantizan la <a href=\"https:\/\/www.ninjaone.com\/es\/supervision-gestion-de-endpoints\/supervision-remota-aviso-de-alertas\/\">supervisi\u00f3n y la gesti\u00f3n en tiempo real<\/a>. NinjaOne, combinado con scripts proactivos como el que hemos visto en este post, proporciona una defensa adicional contra las ciberamenazas.<\/p>\n","protected":false},"author":35,"featured_media":207207,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"_relevanssi_hide_post":"","_relevanssi_hide_content":"","_relevanssi_pin_for_all":"","_relevanssi_pin_keywords":"","_relevanssi_unpin_keywords":"","_relevanssi_related_keywords":"","_relevanssi_related_include_ids":"","_relevanssi_related_exclude_ids":"","_relevanssi_related_no_append":"","_relevanssi_related_not_related":"","_relevanssi_related_posts":"","_relevanssi_noindex_reason":"","_lmt_disableupdate":"no","_lmt_disable":""},"operating_system":[4212],"use_cases":[4267],"class_list":["post-208632","script_hub","type-script_hub","status-publish","has-post-thumbnail","hentry","script_hub_category-windows"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/script_hub\/208632","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/script_hub"}],"about":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/types\/script_hub"}],"author":[{"embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/users\/35"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/comments?post=208632"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/media\/207207"}],"wp:attachment":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/media?parent=208632"}],"wp:term":[{"taxonomy":"script_hub_category","embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/operating_system?post=208632"},{"taxonomy":"use_cases","embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/use_cases?post=208632"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}