Conducting primary account number scan with Wazuh
![Post icon](https://wazuh.com/uploads/2023/05/conducting-pan-circle.png)
Primary account number (PAN) is a unique identifier for payment card account numbers. It consists of a string of numbers ranging from 14 to 19 digits, used to identify the card issuer and account.
Safeguarding cardholder data such as primary account number is of importance for organizations that process card payments. Regulatory bodies require these organizations to comply with the Payment Card Industry Data Security Standard (PCI DSS). The Payment Card Industry Security Standards Council (PCI SSC) developed PCI DSS to ensure the protection of sensitive payment card data. One of the critical mandates of PCI DSS is to perform regular scans that detect the storage of plaintext Primary Account Number (PAN) information.
PCI DSS V4.0 requirement 3.5.1 states that PAN is rendered unreadable anywhere it is stored by using any of the following approaches:
In summary, this requires that PAN is not stored in plaintext. To meet this condition, organizations can conduct a scan to detect the presence of PAN data stored in plaintext, satisfying the criteria outlined in requirement 3.5.1.
In this blog post, we demonstrate how to use Wazuh to conduct a PAN scan of major card brands like Mastercard, Visa, AMEX, Discover, and JCB to meet PCI DSS compliance.
We set up the following infrastructure to demonstrate the capability of Wazuh in detecting the presence of plaintext PAN:
1. A pre-built ready-to-use Wazuh OVA 4.4.1. The OVA contains the Wazuh central components (Wazuh server, Wazuh indexer, and Wazuh dashboard). Follow this guide to download the virtual machine.
2. A CentOS 7 server with Wazuh agent 4.4.1 installed and enrolled to the Wazuh server.
3. A Windows Server 2019 with Wazuh agent 4.4.1 installed and enrolled to the Wazuh server.
In this section, we show the steps required to configure the Wazuh server and the monitored endpoints. Using the Wazuh command monitoring module, we set up commands which search for plaintext PANs and generate logs to be monitored by the Wazuh agent. These commands search for 16-digit PAN data for VISA, MasterCard, Discover, JCB, and 15-digit PAN for AMEX. We also write a custom rule to analyze the logs and generate alerts on the Wazuh dashboard.
Warning
The following configuration is sensitive and contains important information that should only be accessed by authorized personnel. It is important to take proper precautions and ensure that only personnel with training and proper clearance have access to this configuration and the information it contains. Please exercise caution and follow all applicable guidelines when accessing this configuration.
1. Append the configuration below to the Wazuh agent C:\Program Files (x86)\ossec-agent\ossec.conf
configuration file. This configuration checks files on the monitored endpoint to detect PANs stored in plaintext:
<ossec_config> <!-- Check for MasterCard PAN --> <localfile> <log_format>full_command</log_format> <command>powershell -c "Get-ChildItem -Path 'C:\Users\*' -Recurse -Exclude *.dll,*.exe,*.jpg,*.png,*jpeg,*.sys,*.msi,*.dat | Select-String '(\D|^)5[1-5][0-9]{2}(\ |\-|)[0-9]{4}(\ |\-|)[0-9]{4}(\ |\-|)[0-9]{4}(\D|$)' | Select-Object -Unique path -EV Err -EA SilentlyContinue"</command> <alias>PAN scan</alias> <frequency>86400</frequency> </localfile> <!-- Check for Visa PAN --> <localfile> <log_format>full_command</log_format> <command>powershell -c "Get-ChildItem -Path 'C:\Users\*' -Recurse -Exclude *.dll,*.exe,*.jpg,*.png,*jpeg,*.sys,*.msi,*.dat | Select-String '(\D|^)4[0-9]{3}(\ |\-|)[0-9]{4}(\ |\-|)[0-9]{4}(\ |\-|)[0-9]{4}(\D|$)' | Select-Object -Unique path -EV Err -EA SilentlyContinue"</command> <alias>PAN scan</alias> <frequency>86400</frequency> </localfile> <!-- Check for AMEX PAN --> <localfile> <log_format>full_command</log_format> <command>powershell -c "Get-ChildItem -Path 'C:\Users\*' -Recurse -Exclude *.dll,*.exe,*.jpg,*.png,*jpeg,*.sys,*.msi,*.dat | Select-String '(\D|^)(34|37)[0-9]{2}(\ |\-|)[0-9]{6}(\ |\-|)[0-9]{5}(\D|$)' | Select-Object -Unique path -EV Err -EA SilentlyContinue"</command> <alias>PAN scan</alias> <frequency>86400</frequency> </localfile> <!-- Check for Discover PAN --> <localfile> <log_format>full_command</log_format> <command>powershell -c "Get-ChildItem -Path 'C:\Users\*' -Recurse -Exclude *.dll,*.exe,*.jpg,*.png,*jpeg,*.sys,*.msi,*.dat | Select-String '(\D|^)6011(\ |\-|)[0-9]{4}(\ |\-|)[0-9]{4}(\ |\-|)[0-9]{4}(\D|$)' | Select-Object -Unique path -EV Err -EA SilentlyContinue"</command> <alias>PAN scan</alias> <frequency>86400</frequency> </localfile> <!-- Check for JCB PAN --> <localfile> <log_format>full_command</log_format> <command>powershell -c "Get-ChildItem -Path 'C:\Users\*' -Recurse -Exclude *.dll,*.exe,*.jpg,*.png,*jpeg,*.sys,*.msi,*.dat | Select-String '(\D|^)3[0-9]{3}(\ |\-|)[0-9]{4}(\ |\-|)[0-9]{4}(\ |\-|)[0-9]{4}(\D|$)' | Select-Object -Unique path -EV Err -EA SilentlyContinue"</command> <alias>PAN scan</alias> <frequency>86400</frequency> </localfile> </ossec_config>
Where:
<log_format>
specifies how the output of the command is read. full_command
allows the entire output of the command to be treated as a single log item.<command>
specifies the command that the command monitoring module would execute.<alias>
gives the command output an alternative name in the log message.<frequency>
specifies how often the command will be executed, in seconds.The configuration above checks the C:\Users
folder recursively and excludes non-text files. You can adjust the folder to meet your individual needs.
2. Launch PowerShell with administrative privileges and restart the Wazuh agent for the changes to take effect:
> Restart-Service -Name wazuh
1. Append the configuration below to the Wazuh agent /var/ossec/etc/ossec.conf
configuration file. This configuration checks files on the monitored endpoint to detect PAN stored in plain text:
<ossec_config> <!-- Check for MasterCard PAN --> <localfile> <log_format>full_command</log_format> <command>grep -rilE --exclude-dir={bin,boot,mnt,proc,dev,usr,lib64,sbin,lib,run,sys} --exclude={*.bin,*.deb,*.iso,*.lock,*.jpg,*.png,*jpeg,*.gif,*.sys,*.dat} '(\D|^)5[1-5][0-9]{2}(\ |\-|)[0-9]{4}(\ |\-|)[0-9]{4}(\ |\-|)[0-9]{4}(\D|$)' /home</command> <alias>PAN scan</alias> <frequency>86400</frequency> </localfile> <!-- Check for Visa PAN --> <localfile> <log_format>full_command</log_format> <command>grep -rilE --exclude-dir={bin,boot,mnt,proc,dev,usr,lib64,sbin,lib,run,sys} --exclude={*.bin,*.deb,*.iso,*.lock,*.jpg,*.png,*jpeg,*.gif,*.sys,*.dat} '(\D|^)4[0-9]{3}(\ |\-|)[0-9]{4}(\ |\-|)[0-9]{4}(\ |\-|)[0-9]{4}(\D|$)' /home</command> <alias>PAN scan</alias> <frequency>86400</frequency> </localfile> <!-- Check for AMEX PAN --> <localfile> <log_format>full_command</log_format> <command>grep -rilE --exclude-dir={bin,boot,mnt,proc,dev,usr,lib64,sbin,lib,run,sys} --exclude={*.bin,*.deb,*.iso,*.lock,*.jpg,*.png,*jpeg,*.gif,*.sys,*.dat} '(\D|^)(34|37)[0-9]{2}(\ |\-|)[0-9]{6}(\ |\-|)[0-9]{5}(\D|$)' /home</command> <alias>PAN scan</alias> <frequency>86400</frequency> </localfile> <!-- Check for JCB PAN --> <localfile> <log_format>full_command</log_format> <command>grep -rilE --exclude-dir={bin,boot,mnt,proc,dev,usr,lib64,sbin,lib,run,sys} --exclude={*.bin,*.deb,*.iso,*.lock,*.jpg,*.png,*jpeg,*.gif,*.sys,*.dat} '(\D|^)3[0-9]{3}(\ |\-|)[0-9]{4}(\ |\-|)[0-9]{4}(\ |\-|)[0-9]{4}(\D|$)' /home</command> <alias>PAN scan</alias> <frequency>86400</frequency> </localfile> <!-- Check for Discover PAN --> <localfile> <log_format>full_command</log_format> <command>grep -rilE --exclude-dir={bin,boot,mnt,proc,dev,usr,lib64,sbin,lib,run,sys} --exclude={*.bin,*.deb,*.iso,*.lock,*.jpg,*.png,*jpeg,*.gif,*.sys,*.dat} '(\D|^)6011(\ |\-|)[0-9]{4}(\ |\-|)[0-9]{4}(\ |\-|)[0-9]{4}(\D|$)' /home</command> <alias>PAN scan</alias> <frequency>86400</frequency> </localfile> </ossec_config>
Where:
<log_format>
specifies how the output of the command is read. full_command
allows the entire output of the command to be treated as a single log item.<command>
specifies the command that the command monitoring module would execute.<alias>
gives the command output an alternative name in the log message.<frequency>
specifies how often the command will be executed, in seconds.The configuration above recursively checks the home (/home
) directory and excludes directories and file extensions that commonly store system and non-text files. You can adjust the path to meet your individual needs.
2. Restart the Wazuh agent service to apply the configuration changes:
$ sudo systemctl restart wazuh-agent
Note
1. Add the following rule to the Wazuh server /var/ossec/etc/rules/local_rules.xml
file to generate an alert when a file contains plaintext PAN:
<group name="PCIDSS"> <!-- This rule generates an alert when a file is found to contain unmasked card PAN data. --> <rule id="100010" level="6"> <if_sid>530</if_sid> <match>^ossec: output: 'PAN scan'</match> <description>Unmasked Card PAN discovered.</description> <group>pci_dss_3.5.1,</group> </rule> </group>
2. Restart the Wazuh manager to apply the changes:
$ sudo systemctl restart wazuh-manager
In this section, we test the configuration by creating files containing sample plaintext PAN data. An alert is triggered on the Wazuh dashboard when unmasked PANs are detected.
1. Create a file sensitive.txt
in the Documents
folder and add the following sample plaintext PANs:
5411111111111115 371111111111114
2. Create a file secured_PAN.txt
in the Documents
folder and add the following sample truncated PANs:
541111******1115 371111*****1114
The scan runs once every 86400 seconds (24 hours). To get an instantaneous result, trigger the scan by restarting the Wazuh agent service as the command runs on start:
> Restart-Service -Name wazuh
1. Create account_info.txt
and secured_PAN.txt
files in the /home
directory:
$ touch /home/account_info.txt $ touch /home/secured_PAN.txt
2. Add the following sample plaintext PAN to the account_info.txt
file:
$ echo "4532 1111 1111 1112" >> /home/account_info.txt
3. Add the following sample truncated PAN to the secured_PAN.txt
file:
$ echo "4532 11** **** 1112" >> /home/secured_PAN.txt
The scan runs once every 86400 seconds (24 hours). To get an instantaneous result, trigger the scan by restarting the Wazuh agent service as the command runs on start:
$ sudo systemctl restart wazuh-agent
Perform the following steps on the Wazuh dashboard to visualize the alerts:
1. Navigate to Modules > Security events and apply a filter for rule.id:100010
.
2. Expand the alert. The path to the files containing plaintext card PANs can be seen in the full_log
field.
In this blog post, we demonstrated how you can use Wazuh to conduct a PAN scan to meet the PCI DSS requirement 3.5.1. The PCI DSS requirement 3.5.1 requires organizations to ensure Primary Account Number (PAN) information is not stored in an insecure manner. We used the Wazuh command monitoring module to detect the presence of plaintext PAN and generated alerts on the Wazuh dashboard for easy monitoring.
To meet the PCI DSS requirement on securing stored PAN, administrators should scan their storage to detect PAN data stored in plaintext. Stored PAN data should be secured by applying any of the methods prescribed in PCI DSS requirement 3.5.1.
Wazuh is a free and open source SIEM and XDR solution. Wazuh is deployed and managed on-premises, or on our Wazuh cloud. Check our community for support and updates.