-
Notifications
You must be signed in to change notification settings - Fork 9
Catalog
Ready-to-use decoy ideas.
Idea: the application sets a cookie to remember user's preferences. An attacker may probe the cookie value to possibly escalate privileges or to trigger an injection, while non-malicious users typically ignore cookies or just delete cookies.
- Injection: a cookie is injected when visiting a page
- Detection: an alert is raised if the cookie value is modified
{
"decoy": {
"key": "theme",
"separator": "=",
"value": "light"
},
"inject": {
"store": {
"inResponse": ".*",
"as": "cookie"
}
},
"detect": {
"seek": {
"inRequest": ".*",
"in": "cookie"
},
"alert": {
"severity": "MEDIUM",
"whenModified": true
}
}
}
09-decoy-cookie.mp4
Idea: the application developers use hardcoded credentials to debug the application, and forgot to remove the credentials from the productive version. An attacker may try to login with these credentials, while non-malicious users won't typically look at the application's source code or will refrain from using the credentials.
- Injection: an HTML comment is injected in the HTTP response body of a certain page
- Detection: specified username/password are used as POST payload parameters of the /login page
{
"decoy": {
"key": "username=debug%40myapp.com",
"separator": "&",
"value": "password=ghj34g5jk34%25%24%24d",
"string": "<!-- debug with: [email protected] / ghj34g5jk34%$$d -->"
},
"inject": {
"store": {
"inResponse": "/login$",
"withVerb": "GET",
"as": "body",
"at": {
"method": "line",
"property": "1"
}
}
},
"detect": {
"seek": {
"inRequest": "/login$",
"withVerb": "POST",
"in": "payload"
},
"alert": {
"severity": "MEDIUM",
"whenComplete": true
}
}
}
10-decoy-htmlComment.mp4
Idea: a specific endpoint (/api) is only to be consumed by a certain bot. This bot is recognized as it sends a secret HTTP request header (x-analytics). Again, the developers forgot to remove this information from the productive version. An attacker may try to set this HTTP parameter to impersonate the bot, while non-malicious users will refrain or even not see the instructions in the first place.
- Injection: POST requests to /api are met with an error message saying that the header is missing
- Detection: specified HTTP request header is set prior to visiting a page
{
"decoy": {
"key": "x-analytics",
"string": "Missing header: x-analytics - denying"
},
"inject": {
"store": {
"inResponse": "^\/api(\/.*)?$",
"withVerb": "POST",
"as": "body",
"at": {
"method": "replace",
"property": "((.|\n)*)"
}
}
},
"detect": {
"seek": {
"inRequest": ".*",
"withVerb": "POST",
"in": "header"
},
"alert": {
"severity": "MEDIUM",
"whenSeen": true
}
}
},
{
"decoy": {
"key": "401"
},
"inject": {
"store": {
"inResponse": "^\/api(\/.*)?$",
"withVerb": "POST",
"as": "status"
}
}
}
11-decoy-header.mp4
Idea: different servers are deployed for different versions. The login page specifies the latest server name. When a new server is deployed, the page is updated to progressively migrate the traffic. The older version of the server, containing bugs, may still be reachable. An attacker may try to send a request to this older server, while non-malicious users won't see this server parameter or will refrain to modify it.
- Injection: a hidden FORM field in the response body of the /login page
- Detection: unexpected value in the postParam of the corresponding POST /login request.
{
"decoy": {
"key": "server",
"separator": "=",
"value": "PROD02",
"string": "<input type=\"hidden\" name=\"server\" value=\"PROD02\">\n "
},
"inject": {
"store": {
"inResponse": "/login$",
"withVerb": "GET",
"as": "body",
"at": {
"method": "line",
"property": "5"
}
}
},
"detect": {
"seek": {
"inRequest": "/login$",
"withVerb": "POST",
"in": "postParam"
},
"alert": {
"severity": "MEDIUM",
"whenModified": true
}
}
}
12-decoy-form.mp4
Idea: an API is used for sending backup requests. The code is not used anymore but the endpoint is still here and may be an entry point. An attacker may try to probe this endpoint, searching for a vulnerability, while non-malicious users won't look at the source code of the server's javascript.
- Injection: a method inside a javascript file which is never invoked, injected as a response body
- Detection: the endpoint URL is being requested
{
"decoy": {
"key": "backup-2024-sdj",
"string": "function sendBackupRequest() {\n const url = '/backup-2024-sdj';\n const payload = {\n start: 'now'\n };\n\n fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type':\n'application/json'\n },\n body: JSON.stringify(payload)\n })\n .then(response => {\n if (!response.ok) {\n throw new Error('Network response was not ok ' + response.statusText);\n }\n return response.json();\n })\n .then(data => {\n console.log('Success:', data);\n })\n .catch(error => {\n console.error('Error:', error);\n });\n}"
},
"inject": {
"store": {
"inResponse": "/script.js$",
"withVerb": "GET",
"as": "body",
"at": {
"method": "line",
"property": "0"
}
}
},
"detect": {
"seek": {
"inRequest": ".*",
"withVerb": "POST",
"in": "url"
},
"alert": {
"severity": "MEDIUM",
"whenSeen": true
}
}
}
13-decoy-javascript.mp4
Idea: the application has an endpoint that should not be crawled by bots. Attackers may try to visit that endpoint hoping to find interesting information, while non-malicious users won't try to read the content of the robots.txt file.
- Injection: a full robots.txt page generated as response body, when requesting /robots.txt
- Detection: the endpoint URL is being requested
{
"decoy": {
"key": "/administrator/login",
"string": "User-agent: *\nDisallow: /administrator/login"
},
"inject": {
"store": {
"inResponse": "/robots.txt$",
"withVerb": "GET",
"as": "body",
"at": {
"method": "replace",
"property": "((.|\n)*)"
}
}
},
"detect": {
"seek": {
"inRequest": ".*",
"withVerb": "GET",
"in": "url"
},
"alert": {
"severity": "MEDIUM",
"whenSeen": true
}
}
},
{
"decoy": {
"key": "200"
},
"inject": {
"store": {
"inResponse": "/robots.txt$",
"withVerb": "GET",
"as": "status"
}
}
},
{
"decoy": {
"key": "content-type",
"separator":"=",
"value": "text/plain"
},
"inject": {
"store": {
"inResponse": "/robots.txt$",
"withVerb": "GET",
"as": "header",
"at": {
"method": "replace",
"property": ".*"
}
}
}
}
14-decoy-robots.mp4
Idea: the login web form will refuse to be submitted if the username is not a URL. Attackers will try to bypass the client-side restriction, possibly hoping to discover an injection vulnerability, while non-malicious users will comply with the browser's request.
- Injection: nothing
- Detection: the format of the submitted username as POST payload violates the client-side rule.
{
"decoy": {
"key": "username",
"separator": "=",
"dynamicValue": "[^\\%40\\s]+\\%40[^\\%40\\s]+\\.[^\\%40\\s]+"
},
"detect": {
"seek": {
"inRequest": "/login",
"withVerb": "POST",
"in": "postParam"
},
"alert": {
"severity": "MEDIUM",
"whenModified": true
}
}
}
15-detection-clientSide.mp4
Idea: a developer using a private github repository creates an image in an insecure way. As a consquence, the local .git folder is added to the image and can be harvested to retrieve the source code of the application.
- Injection: nothing
- Detection: the url '/.git' is visited.
Please note: non-malicious users won't try to find hidden source code, but certain browsers extensions used by developers can visit .git automatically (as an offensive security tool). While unlikely, this decoy may thus trigger some false positive alerts.
{
"decoy": {
"key": "/.git"
},
"detect": {
"seek": {
"inRequest": ".*",
"withVerb": "GET",
"in": "url"
},
"alert": {
"severity": "MEDIUM",
"whenSeen": true
}
}
}