Post

BugForge - Weekly - Mesanet Portal

BugForge - Weekly - Mesanet Portal

Weekly - Mesanet Portal


Vulnerabilities Covered:
SQL Injection (INSERT-based String Concatenation)
API Gateway Abuse via Boolean Type Confusion
Directory Enumeration

Summary:
This walkthrough demonstrates a SQL injection vulnerability in a microservice-based portal that follows the API Gateway pattern. By analysing the application’s frontend source code, a hardcoded internal service identifier was discovered. Boolean type confusion on the gateway’s application ID parameter revealed a hidden internal rail service. Fuzzing the rail endpoints uncovered a create endpoint vulnerable to INSERT-based SQL injection via string concatenation. The injection was used to extract database tables, schema, and credentials from a config table. The extracted database admin credentials provided access to a database backup portal, which was used to download a portal database containing a one-time password required to access a dev console and retrieve the flag.

Reference:
Bugforge.io

Solution

Step 1 - Application Analysis & Directory Enumeration

Start by fuzzing for directories using the Seclists/Discovery/Web-Content/common.txt wordlist.

Fuzzing Fuzzing Results

Two additional portals are discovered: a dev portal requiring a one-time password (OTP) and a database admin portal requiring credentials.

Dev Portal UI

Database Admin Portal UI


Step 2 - Authenticated Application Exploration

Log in with the provided credentials operator:operator. The application presents a dashboard with a notice board, secure email functionality, and the dev console discovered during enumeration.

Dashboard UI


Step 3 - Source Code Analysis & Gateway Discovery

Access the Nexus notice board and analyse the source code for apps/nexus. A hardcoded APP_ID is present along with a POST request to a gateway endpoint. The request payload contains a JSON object with id, endpoint, and a data object.

Notice Board UI

Nexus Source Code

The application follows the API Gateway pattern a design approach where a single entry point sits between client applications and a collection of backend microservices, acting as a reverse proxy that routes incoming requests to the appropriate internal service. Instead of the client communicating directly with multiple backend services, all requests are sent to the gateway, which determines which internal service should handle the request based on parameters like a service identifier or route path.

Gateway POST Request


Step 4 - Gateway Parameter Manipulation & Type Confusion

Manipulate the gateway payload to understand its behaviour. Removing the id parameter returns the error App ID and endpoint are required. Changing the id value to an integer (1) returns Unknown application ID. However, setting the id to a boolean value (true) returns a different error: Rail endpoint not found.

Rail Endpoint Not Found

This type confusion reveals the existence of an internal rail service. The boolean true bypasses the application ID lookup and routes directly to the rail service, exposing an entirely new attack surface.


Step 5 - Fuzzing the Rail Service Endpoints

Fuzz the rail endpoint using the Seclists/Discovery/Web-Content/common.txt wordlist to enumerate available routes.

Rail Endpoints

Several endpoints are discovered. Analyse each to understand the service functionality:

announcementsreturns a list of all announcements:

Rail Announcements

currentreturns the current announcement:

Rail Current

schedulereturns the schedule:

Rail Schedule

statusreturns the service status:

Rail Status


Step 6 - Identifying the SQL Injection Point

Send a request to the create endpoint with no data. The error message type, message, timestamp, and priority are required reveals the expected payload structure. Reference the data returned from api/rail/announcements to determine valid values for type and priority, then craft a valid creation request.

Create Announcement

Inject a single quote (') into the message field. The application returns a database error, indicating the message parameter is vulnerable to SQL injection.

SQLI Error


Step 7 - INSERT-based SQL Injection via String Concatenation

When the injection point is inside an INSERT or UPDATE statement, UNION-based extraction is not possible because there is no SELECT to append to. Instead, the || concatenation operator is used to embed a subquery result into the stored string value. The database evaluates the subquery at write time, stores the combined result, and when the application reflects it back in the response, the extracted data is visible.

Extract all tables from the database:

1
Zwarts' || (SELECT group_concat(name) FROM sqlite_master WHERE type='table') || '

Database Tables

Extract the column structure of the config table:

1
Zwarts' || (SELECT group_concat(sql) FROM sqlite_master WHERE type='table' AND name='config') || '

Config Columns

Dump the contents of the config table:

1
Zwarts' || (SELECT group_concat(key || ':' || value) FROM config) || '

Config Data

The config table reveals database admin credentials: dbadmin:Xen_Lambda_R4ilSyst3m_2024!Cr0ss1ng


Step 8 - Accessing the Database Admin Portal

Use the extracted credentials to log in to the database admin portal discovered during enumeration.

Database Portal Login

The portal allows downloading database backups when provided with a database name. Attempting a generic name reveals an error stating the database name must be suffixed with Db.

Database Name Error


Step 9 - Fuzzing the Database Name

Generate a custom wordlist themed around the challenge context (Half-Life / Black Mesa references with the Db suffix) and fuzz the database name parameter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
mesaNetDb
blackMesaDb
anomalousMaterialsDb
lambdaCoreDb
sectorCDb
xenDb
nihilanthDb
gordonFreemanDb
barneyDb
eliVanceDb
alyxVanceDb
kleinerDb
magnussonDb
headcrabDb
vortigauntDb
combineDb
apertureDb
resonanceCascadeDb
hevSuitDb
gravityGunDb
crowbarDb
teleporterDb
borealisDb
ravenholmDb
city17Db
citadelDb
surfaceTensionDb
unforeseenConsequencesDb
powerUpDb
blastPitDb
apprehensionDb
questionableEthicsDb
interloperDb
endgameDb
freemanDb
lambdaDb
nexusDb
portalDb
mesaDb
researchDb
testChamberDb
siloDb
adminDb
securityDb
personnelDb
facilityDb
containmentDb
hazardCourseDb
decayDb
opposingForceDb
blueshiftDb
sectorGDb
sectorEDb
sectorBDb
sectorADb
sectorDDb
sectorFDb
level3Db
subLevelDb
canalDb
wastelandDb
highwayDb
novaProsektDb
sandtrapsDb
antiMassDb
specimenDb
cascadeDb
xenCrystalDb
boundaryDb
crossfireDb
dataCoreDb
mainframeDb
mesaLabDb
mesaSecurityDb
mesaAdminDb
mesaPersonnelDb
mesaAccessDb
mesaPortalDb
mesaCoreDb
mesaNetAccessDb
accessPortalDb
portalAccessDb
netAccessDb
mesaNetCoreDb
mesaNetAdminDb
mesaNetSecurityDb

The fuzzing returns a hit on portalDb.


Step 10 - Extracting the OTP & Retrieving the Flag

Navigate to the dev console and trigger the OTP generation. Return to the database admin portal, download the portalDb backup, and extract the OTP from the database contents.

Read OTP

Enter the OTP in the dev console to gain access and retrieve the flag.

Flag


Impact

  • Full database schema enumeration and data extraction via SQL injection
  • Exposure of database admin credentials stored in plaintext configuration
  • Access to database backup functionality enabling offline analysis of all application data
  • Bypass of OTP-protected dev console through database credential chain
  • Discovery of hidden internal microservices via API gateway type confusion
  • Potential lateral movement to other internal services routed through the gateway

Vulnerability Classification

  • OWASP Top 10: A03:2021 - Injection
  • Vulnerability Type: INSERT-based SQL Injection via String Concatenation
  • Attack Surface: API Gateway rail service create endpoint, message parameter
  • Database: SQLite
  • CWE:
    • CWE-89 - Improper Neutralization of Special Elements used in an SQL Command (SQL Injection)
    • CWE-843 - Access of Resource Using Incompatible Type (Type Confusion)
    • CWE-256 - Plaintext Storage of a Password

Root Cause

The rail service’s create endpoint constructs an INSERT statement by directly concatenating user-supplied input from the message parameter into the SQL query without parameterization. This allows an attacker to inject arbitrary SQL subqueries that are evaluated at write time and reflected in subsequent read operations. The vulnerability chain is compounded by the API gateway’s weak type handling, which allows a boolean value to bypass application ID validation and expose the internal rail service. Additionally, storing database credentials in plaintext within a config table and exposing a database backup portal without rate limiting or additional authentication enables the full exploitation chain from SQL injection to flag retrieval.


Remediation

  • Use parameterized queries or prepared statements for all database operations, including INSERT and UPDATE statements
  • Implement strict type validation on the API gateway to reject unexpected parameter types for the application ID
  • Remove hardcoded service identifiers from client-side source code
  • Store sensitive credentials using a secrets management solution rather than in database configuration tables
  • Apply network-level access controls to restrict direct access to internal microservices
  • Implement rate limiting and additional authentication on the database backup portal
  • Conduct regular security code reviews focusing on data flow through the API gateway to backend services

This post is licensed under CC BY 4.0 by the author.