class
Analyzer::Cfml::Pure
- Analyzer::Cfml::Pure
- Analyzer::Cfml::CfmlEngine
- Analyzer
- Reference
- Object
Overview
Plain CFML (ColdFusion / Lucee / BoxLang) attack surface.
CFML has two directly-reachable shapes and no route table:
.cfmpages are file-path routed — the path under the web root is the URL, exactly like plain PHP or JSP..cfccomponents are not reachable on their own, but any method declaredaccess="remote"is callable over HTTP as/path/To/Component.cfc?method=<name>, with the declared arguments arriving as URL or FORM keys.
Framework route tables (Taffy taffy:uri, ColdBox Router.cfc,
Wheels config/routes.cfm, FW/1 variables.framework.routes) are
deliberately out of scope here — they warrant their own techs so the
generic analyzer isn't the thing that decides framework semantics.
Defined in:
analyzer/analyzers/cfml/pure.crConstant Summary
-
CFPARAM_ASSIGN_RE =
/(?<![.\w])param\s+(url|form|cookie)\.(\w+)\s*=/i -
CFPARAM_SCRIPT_RE =
/(?<![.\w])param\b[^;\n]*?\bname\s*=\s*["'](url|form|cookie)\.(\w+)["']/i -
CFPARAM_TAG_RE =
/<cfparam\b[^>]*?\bname\s*=\s*["'](url|form|cookie)\.(\w+)["']/i -
CGI_HEADER_RE =
/(?<![.\w])cgi\.(http_[a-z_]+)/i -
cgi.http_x_forwarded_foris the CFML spelling of an inbound header. The othercgi.*keys (request_method, script_name, ...) are server metadata, not request params. -
INTERPOLATION_RE =
/#[^#\n]+#/ -
IS_DEFINED_RE =
/\bisDefined\s*\(\s*["'](url|form|cookie)\.(\w+)["']\s*\)/i -
LIFECYCLE_PAGES =
Set {"application.cfm", "onrequestend.cfm"} -
Auto-run lifecycle includes, not requestable pages — the CFML analogue of
global.asa. -
REMOTE_HINT_RE =
/remote/i -
CFML is case-insensitive, so
access="ReMote"is as valid asaccess="remote"; gate on one case-insensitive pass rather than a handful of literal spellings. -
SCOPE_BRACKET_RE =
/#{SCOPE_PREFIX}\s*\[\s*["']([^"'\]]+)["']\s*\]/i -
SCOPE_DOT_RE =
/#{SCOPE_PREFIX}\.([A-Za-z_]\w*)/i -
SCOPE_PATTERNS =
[CFPARAM_TAG_RE, CFPARAM_SCRIPT_RE, CFPARAM_ASSIGN_RE, SCOPE_DOT_RE, SCOPE_BRACKET_RE, STRUCT_KEY_EXISTS_RE, IS_DEFINED_RE] -
SCOPE_PREFIX =
"(?<![.\\w])(url|form|cookie)" -
Request-scope reads on
.cfmpages. The negative lookbehind keepsdocument.form.x/application.form.xfrom registering as aformscope read. -
SCRIPT_ACCESS_REMOTE_RE =
/\baccess\s*=\s*["']remote["']/i -
SCRIPT_BLOCK_RE =
/(<script\b[^>]*>)([\s\S]*?)(<\/script>)/i -
Client-side JavaScript routinely names a local
form(form.submit(),form.action), which the scope patterns above would otherwise read as CFML form-scope access — inventing params and flipping the page to POST. Script bodies are blanked, except#...#spans, because CFML genuinely interpolates server values into JS (var id = #url.id#;). -
SCRIPT_REMOTE_PREFIX_RE =
/(?<![\w.])remote\s+(?:\w+\s+)?function\s+(\w+)\s*\(/i -
Script syntax has two spellings of the same thing. The prefix form is matched loosely and its argument list is delimited by real paren matching; the suffix form is driven off the
accessattribute so a component with hundreds of private methods costs one scan, not one paren walk per declaration. -
SCRIPT_REMOTE_SUFFIX_RE =
/(?<![\w.])function\s+(\w+)\s*\(([^)]*)\)([^{;]*?)access\s*=\s*["']remote["']/i -
STRUCT_KEY_EXISTS_RE =
/\bstructKeyExists\s*\(\s*(url|form|cookie)\s*,\s*["']([^"']+)["']\s*\)/i -
WEBROOT_MARKERS =
["webroot/", "wwwroot/", "htdocs/"] -
Only unambiguous web-root directory names. Bare
public/andwww/were tried and dropped: they collide with build output such asdocs/public/, the same false positiveFileHelperdocuments.Locating the root from
Application.cfcwas also tried and is worse — every CFML sub-application, module and test harness ships one (7-25 per repo across the validation corpus), so anchoring collapsed Taffy's 20 example apps onto a single/index.cfm. Leaving the path repo-relative keeps colliding pages distinct and locatable.