Vladimir de Turckheim, Software Engineer, Sqreen twitter, linkedin
abstract slides video
For vulnerabilities, a SQL injection example is given as well as regular expression denial of service, the latter of which can be found by vuln-regex-detector.
The most interesting, JavaScript-specific vulnerability described was object injection, which occurs when an application expects data of a certain type to be provided (e.g. a number or string), but instead a different type (e.g. a JavaScript object) is provided, significantly changing the behavior of the code.
app.post(‘/documents/find’, (req, res) => {
const query = { };
if (req.body.title) query.title = req.body.title;
if (req.body.desiredType) query.type = req.body.desiredType;
Document.find(query).exec()
.then((r) => res.json(r));
}
In this code, an endpoint is querying a NoSQL database, expecting req.body
to have a value like { desiredType: 'blog'}
, which would result in the query: { type: "blog" }
.
However, if an attacker provided an input like { desiredType: { $ne: 0 } }
, the resulting query would be { type: { $ne: 0 } }
. Since the type
field in the database is a string, all records’ type
fields will not be equal to 0 ($ne: 0
), so all records will be returned, like a NoSQL version of or 1=1
.
Ecosystem attacks: most NPM libraries have a huge number of direct and indirect dependencies, which exposes a large supply chain attack surface. Vladimir discusses when ESLint was backdoored as an example.
Recommendations:
-
Keep NodeJS up to date
-
Review any use of critical core modules – carefully sanitize any user input that reaches
fs
,child_process
, andvm
-
Data validation is not native in JavaScript, sanitize inputs using a library like joi
-
Monitor your dependencies for known issues
-
Monitor your dependency tree (anvaka) – some libraries that perform the same functionality have significantly fewer dependencies than others. Minimize your attack surface.