Strategies for CyberPatriot
A look inside how the high school cybersecurity competition CyberPatriot calculates score and the lessons learned from such analysis
CyberPatriot is a secondary school-level cybersecurity competition based around hardening instances of desktop and server machines. Sponsored by the Air Force Association and Northrop Grumman, the program is an initiative to inspire a new generation of engineers for the adapting government landscape. It presents a unique experience, especially to those without any prior introduction to the subject matter.
Unfortunately, much of the competition is hazed with an air of mystery; if not for the upperclassmen who had first introduced me I would have had no idea what CyberPatriot entailed before diving straight in competition day. Even after two years I realized I wasn’t much more aware of what was really going on beyond the Mario coin sound playing every time I got lucky with installing anti-virus software. This expository piece is my effort to alleviate this void in understanding, if not only for myself but for any other CyberPatriot stuck in the same rut.
Vulnerability Scoring
Behind every competition image is the CyberPatriot Scoring Engine, a local daemon responsible for tabulating all of your points and relaying that to the official server. Discussion of this protocol is neither here nor there but it can be insightful to know how exactly this scoring engine evaluates the state of your image.
Behind every security issue that points are awarded for, or in the case of
penalties, confiscated for, are a series of tests and conditionals. Tests are
rather straightforward – they specify a certain type of test and any
parameters. The conditionals then evaluate the results of the tests and
determine if the so-called check and its associated point value should be
applied. Some checks involve several tests and conditionals while others are
only responsible for evaluating one factor. Here’s an example of a simple check
that will award 5 points when the user branw
has been removed from the
system:
checks:
- name: "branw"
description: "User branw has been removed"
value: 5
tests:
- name: "test_a"
test: "user"
user_name: "branw"
conditions:
- if:
- test: "test_a"
value: "exists"
equals: "false"
Every 5 minutes or so, the engine will iterate over the list of checks,
evaluate every test, and finally award points if at least one set of
conditionals is true. You can imagine penalties working very similarly, only
with value
existing on the other side of zero. To get an idea of what the
engine is capable of, here are a few different kinds of tests it implements:
-
Account lockout policy:
-
Obtained from
NetUserModalsGet
withlevel = 3
, returningtypedef struct _USER_MODALS_INFO_3 { DWORD usrmod3_lockout_duration; DWORD usrmod3_lockout_observation_window; DWORD usrmod3_lockout_threshold; } USER_MODALS_INFO_3, *PUSER_MODALS_INFO_3, *LPUSER_MODALS_INFO_3;
-
Checks that a lockout threshold exists and is between a certain value
-
-
Registered antivirus:
- Obtained by polling the WMI providers
ROOT\\SecurityCenter
andROOT\\SecurityCenter2
with the querySELECT * FROM AntiVirusProduct
- Checks that an anti-virus solution has been installed and registered with the security center
- Obtained by polling the WMI providers
-
Audit policies:
-
Obtained from
LsaQueryInformationPolicy
withInformationClass = PolicyAuditEventsInformation
, capable of auditing the following categories:typedef enum _POLICY_AUDIT_EVENT_TYPE { AuditCategorySystem, AuditCategoryLogon, AuditCategoryObjectAccess, AuditCategoryPrivilegeUse, AuditCategoryDetailedTracking, AuditCategoryPolicyChange, AuditCategoryAccountManagement, AuditCategoryDirectoryServiceAccess, AuditCategoryAccountLogon } POLICY_AUDIT_EVENT_TYPE, *PPOLICY_AUDIT_EVENT_TYPE;
-
Checks a variety of details including when policies are changed
-
-
Files:
- Checks existence of files as well as their contents against regular expressions
-
Firewall:
- Obtained by polling the WMI providers
ROOT\\SecurityCenter
andROOT\\SecurityCenter2
with the querySELECT * FROM FirewallProduct
- Checks if a firewall is enabled and if so, which one
- Obtained by polling the WMI providers
-
Resultant Set of Policy security settings (group policies):
- Obtained by polling the WMI providers
ROOT\\RSOP\\Computer
with the querySELECT * FROM RSOP_SecuritySettingboolean
- Checks any kind of group policy setting
- Obtained by polling the WMI providers
-
Password policies:
-
Obtained from
NetUserModalsGet
withlevels = 0
, returningtypedef struct _USER_MODALS_INFO_0 { DWORD usrmod0_min_passwd_len; DWORD usrmod0_max_passwd_age; DWORD usrmod0_min_passwd_age; DWORD usrmod0_force_logoff; DWORD usrmod0_password_hist_len; } USER_MODALS_INFO_0, *PUSER_MODALS_INFO_0, *LPUSER_MODALS_INFO_0;
-
Checks password requirements, including password length, history length, and age limits
-
-
Processes:
- Obtained through
EnumProcesses
- Checks state of running processes
- Obtained through
-
Registry:
- Obtained through the Win32 registry API
- Checks values for a variety of keys, mostly in
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet
andHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\
-
Services:
- Obtained from
QueryServiceStatus
- Checks state of services
- Obtained from
-
Users:
-
Obtained from
NetUserGetInfo
withlevel = 2
, returningtypedef struct _USER_INFO_2 { LPWSTR usri2_name; LPWSTR usri2_password; DWORD usri2_password_age; DWORD usri2_priv; LPWSTR usri2_home_dir; LPWSTR usri2_comment; DWORD usri2_flags; LPWSTR usri2_script_path; DWORD usri2_auth_flags; LPWSTR usri2_full_name; LPWSTR usri2_usr_comment; LPWSTR usri2_parms; LPWSTR usri2_workstations; DWORD usri2_last_logon; DWORD usri2_last_logoff; DWORD usri2_acct_expires; DWORD usri2_max_storage; DWORD usri2_units_per_week; PBYTE usri2_logon_hours; DWORD usri2_bad_pw_count; DWORD usri2_num_logons; LPWSTR usri2_logon_server; DWORD usri2_country_code; DWORD usri2_code_page; } USER_INFO_2, *PUSER_INFO_2, *LPUSER_INFO_2;
-
Checks if a user has been deleted or if they’re in a certain group, etc.
-
-
Volume:
- Obtained from
GetVolumeInformation
- Checks volume metadata including serial number; the scoring engine also uses this to verify that the primary hard drive serial number matches, i.e. that it is not running outside of the competition
- Obtained from
-
Windows version:
- Obtained from
GetNativeSystemInfo
andGetProductInfo
- Checks if an operating system is installed (just in case, you never know) including the build version and service packs
- Obtained from
Keep in mind, the Ubuntu scoring engine is or at least has been a fairly crippled version of that seen on Windows images; generally only the file, user, and process tests are implemented. By the policy of “everything is a file,” this is not all too limiting
Conclusions
When taking a step back and seeing the competition by how it is scored, one is able to gain a bit of a deeper understanding of how to tackle the competition. While each round generally brings something new to the table, there are a few essential patterns behind every competition.