"Debbie Nuttall" firstname.lastname@example.org
Cromulence LLC (CROMU)
This is a payroll system that allows registration of users, logging of hours worked, and querying the system for payroll information.
The system works for up to 50 employees over one calendar year. It will allow registration of both exempt and non exempt employees who make up to $75/hour. The system will log both standard time and overtime based on a standard 40 hour work week. The system will calculate a weekly paycheck per employee including removal of required payroll taxes. Various reports can be generated. This is a simulation only, do not use this to pay your employees.
Employees can be registered as exempt or non-exempt. Exempt employees are paid at the same hourly rate for overtime and standardtime. Non-exempt employees are paid time-and-a-half for overtime. For all employees anything over 8 hours on a weekday and all weekend time is treated as overtime. By default, employees are treated as non-exempt
The following reports can be generated by the system: "all" - Show all payroll information for everyone. "one" - Show all payroll information for one employee. "week" - Show payroll information for one employee for a specific week. "week_all" - Show payroll information for all employees for a specific week.
Input to the program is in the form of key-value pairs using the syntax: key-value` Some key-value pairs are required for certain commands and the rest can be included in an arbitrary order. Input will be processed as a single command when a newline is received.
The program will continue to operate in a loop processing input and generating output until a blank line is entered to terminate the session.
User registration can contain the following key-value pairs: Key Value employee_id A number from 0 to 49 employee-name An ascii string wage The hourly wage of an employee (capped at 75.00) exempt Indicates an exempt employee. Values are 'yes' or 'no'
Logging hours can contain the following key-value pairs: Key Value employee_id A number from 0 to 49 week A number from 0 to 51 monday Hours worked in the form #h#m ... hours are capped at 24 sunday minutes are capped at 59
A report query can contain the following key-value pairs: Key Value query Type of query [all|one|week|week_all] employee_id A number from 0 to 49 week A number from 0 to 51
For example, registering a non-exempt employee, logging one 40 hour work week, and generating a weekly payroll report would look like this: employee_id-1
There are two vulnerabilities in this program. The first vulnerability is in the process_query function in timecard.c. It allows an out of bounds read by using unverified user input as the index to an array when reading employee data.
The second vulnerability is due to improper use of the payroll structure as defined in timecard.h and used incorrectly in the calculate_totalpay function in timecard.c. User input goes through a floating point calculation to affect the value of an integer which is then converted to an ascii decimal representation and written to a fixed length buffer. If the integer value becomes sufficiently large, the buffer will overflow into a nearby function pointer. Subsequent access to the function pointer results in limited EIP control.
Information for all employees is stored in an array of employee structures located on the stack. Each structure contains an array of 52 payroll structures which store hours worked and paycheck information for each week of the year.
When program input logs hours for an employee the hours are added to this payroll structure for the given week. Each time hours are logged, a payroll calculation occurs using floating point math to generate regular pay and overtime pay for that week. A structure containing integer values for dollars and cents is used to store the pay values after they are calculated. Because the payroll calculation must differ between exempt and non-exempt employees, there is a function pointer inside the payroll structure which points to the correct overtime calculation for that employee. This function pointer will be overwritten later on.
When a report is generated via the query command, it calls the function calculate_totalpay. In order to display the pay amount, calculate_totalpay calls the function mtoa (short for money to ascii) to convert from integer values (for dollars and cents) to an ascii string. mtoa can write up to 19 characters total given the largest value for dollars. The vulnerability occurs because calculate_totalpay calls mtoa with an output buffer of only 12 bytes. The output buffer is located in an employee's payroll structure.
If the pay amount is large enough (over 1,000,000 for one week), the buffer will overflow and a nearby function pointer is overwritten. The overwritten function pointer is calculate_overtime and as we previously discussed is used to calculate overtime for the employee. It will be called the next time hours are logged for that week for that employee.
Hours for a single day are restricted to 24 or less and the pay rate is restricted to $75.00 or less, so a significant number of log entries are required to generate a pay amount large enough to overflow the buffer. In addition, for non-exempt employees the function pointer is re-initialized before it is called each time so the overflow will only lead to EIP control in cases where the employee was registered as exempt.
In order to crash the program, the input must: 1. Register an employee as exempt. 2. Log sufficient hours to generate a one week pay amount of $1,000,000.00 or greater. 3. Generate a report for that employee's paycheck that week to cause the overflow. 4. Log additional hours for that employee that week to call the overwritten function pointer.
Improper bounds check on an array dereference. Improper bounds check on an integer to ascii conversion allows overwrite of a function pointer.
CWE-118: Improper Access of Indexable Resource CWE-121: Stack-based Buffer Overflow
The first vulnerability allows a simple user input to affect the location of a memory read. It was detected during internal testing using a fuzzer.
The second vulnerability is not as straightforward. This CB allows input of many different key-value pairs in an arbitrary fashion. This will lead to a state explosion issue for symbolic program analysis. The large integer value needed for the overflow requires a significant number of key-value pairs in a particular order that is not informed by the structure of the CB. The vulnerable code lies after a floating point calculation potentially confusing systems which do not handle floating point.
The code path needed to access the overwritten function pointer requires an additional key-value pair that is not present in the sample traffic given to the CRS. A successful fuzzing approach will require informing the fuzzer of the additional key-value pair and placing it in the correct location in input.
Curated by Lunge Technology, LLC. Questions or comments? Send us email