-
Notifications
You must be signed in to change notification settings - Fork 211
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Prototype Pollution (Server Side) + Email Injection (#307)
A client side endpoint that is vulnerable to prototype pollution --------- Co-authored-by: Tamir Gershberg <[email protected]>
- Loading branch information
1 parent
f6fe49e
commit 7b546bc
Showing
19 changed files
with
668 additions
and
100 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,7 @@ The full API documentation is available via swagger or GraphQL: | |
npm ci && npm run build | ||
|
||
# build client | ||
npm ci --prefix public && npm run build --prefix public | ||
npm ci --prefix client && npm run build --prefix client | ||
|
||
#build and start dockers with Postgres DB, nginx and server | ||
docker-compose --file=docker-compose.local.yml up -d | ||
|
@@ -177,4 +177,19 @@ Additionally, the endpoint PUT /api/users/one/{email}/photo accepts SVG images, | |
3. The endpoint GET `/api/partners/query` is a raw XPATH injection endpoint. You can put whatever you like there. It is not referenced in the frontend, but it is an exposed API endpoint. | ||
4. Note: All endpoints are vulnerable to error based payloads. | ||
|
||
* **Prototype Pollution** - The `/marketplace` endpoint is vulnerable to prototype pollution using the following methods: | ||
1. The EP GET `/marketplace?__proto__[Test]=Test` represents the client side vulnerabillity, by parsing the URI (for portfolio filtering) and converting | ||
it's parmeters into an object. This means that a requests like `/marketplace?__proto__[TestKey]=TestValue` will lead to a creation of `Object.TestKey`. | ||
One can test if an attack was successful by viewing the new property created in the console. | ||
This EP also supports prototyp pollution based DOM XSS using a payload such as `__proto__[prototypePollutionDomXss]=data:,alert(1);`. | ||
The "legitimate" code tries to use the `prototypePollutionDomXss` parameter as a source for a script tag, so if the exploit is not used via this key it won't work. | ||
2. The EP GET `/api/email/sendSupportEmail` represents the server side vulnerabillity, by having a rookie URI parsing mistake (similiar to the client side). | ||
This means that a request such as `/api/email/sendSupportEmail?name=Bob%20Dylan&__proto__[status]=222&to=username%40email.com&subject=Help%20Request&content=Help%20me..` | ||
will lead to a creation of `uriParams.status`, which is a parameter used in the final JSON response. | ||
|
||
* **Date Manipulation** - The `/api/products?date_from={df}&date_to={dt}` endpoint fetches all products that were created between the selected dates. There is no limit on the range of dates and when a user tries to query a range larger than 2 years querying takes a significant amount of time. This EP is used by the frontend in the `/marketplace` page. | ||
|
||
* **Email Injection** - The `/api/email/sendSupportEmail` is vulnerable to email injection by supplying tempred recipients. | ||
To exploit the EP you can dispatch a request as such `/api/email/sendSupportEmail?name=Bob&to=username%40email.com%0aCc:%[email protected]&subject=Help%20Request&content=I%20would%20like%20to%20request%20help%20regarding`. | ||
This will lead to the sending of a mail to both `[email protected]` and `[email protected]` (as the Cc). | ||
Note: This EP is also vulnerable to `Server side prototype pollution`, as mentioned in this README. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// Taken from PortSwigger's prototype pollution labs | ||
// VULNERABLE TO PROTOTYPE POLLUTION! | ||
var splitUriIntoParamsPPVulnerable = (params, coerce) => { | ||
if (params.charAt(0) === '?') { | ||
params = params.substring(1); | ||
} | ||
|
||
var obj = {}, | ||
coerce_types = { true: !0, false: !1, null: null }; | ||
|
||
if (!params) { | ||
return obj; | ||
} | ||
|
||
params | ||
.replace(/\+/g, ' ') | ||
.split('&') | ||
.forEach(function (v) { | ||
var param = v.split('='), | ||
key = decodeURIComponent(param[0]), | ||
val, | ||
cur = obj, | ||
i = 0, | ||
keys = key.split(']['), | ||
keys_last = keys.length - 1; | ||
|
||
if (/\[/.test(keys[0]) && /\]$/.test(keys[keys_last])) { | ||
keys[keys_last] = keys[keys_last].replace(/\]$/, ''); | ||
keys = keys.shift().split('[').concat(keys); | ||
keys_last = keys.length - 1; | ||
} else { | ||
keys_last = 0; | ||
} | ||
|
||
if (param.length === 2) { | ||
val = decodeURIComponent(param[1]); | ||
|
||
if (coerce) { | ||
val = | ||
val && !isNaN(val) && +val + '' === val | ||
? +val // number | ||
: val === 'undefined' | ||
? undefined // undefined | ||
: coerce_types[val] !== undefined | ||
? coerce_types[val] // true, false, null | ||
: val; // string | ||
} | ||
|
||
if (keys_last) { | ||
for (; i <= keys_last; i++) { | ||
key = keys[i] === '' ? cur.length : keys[i]; | ||
cur = cur[key] = | ||
i < keys_last | ||
? cur[key] || (keys[i + 1] && isNaN(keys[i + 1]) ? {} : []) | ||
: val; | ||
} | ||
} else { | ||
if (Object.prototype.toString.call(obj[key]) === '[object Array]') { | ||
obj[key].push(val); | ||
} else if ({}.hasOwnProperty.call(obj, key)) { | ||
obj[key] = [obj[key], val]; | ||
} else { | ||
obj[key] = val; | ||
} | ||
} | ||
} else if (key) { | ||
obj[key] = coerce ? undefined : ''; | ||
} | ||
}); | ||
|
||
return obj; | ||
}; | ||
|
||
export default splitUriIntoParamsPPVulnerable; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.