Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JS: support hana db client #19118

Merged
merged 14 commits into from
Mar 31, 2025
Merged

JS: support hana db client #19118

merged 14 commits into from
Mar 31, 2025

Conversation

Napalys
Copy link
Contributor

@Napalys Napalys commented Mar 25, 2025

Modeled @sap/hana-client, @sap/hdbext and hdb packages sql-injection sinks.

@github-actions github-actions bot added the JS label Mar 25, 2025
@Napalys Napalys marked this pull request as ready for review March 26, 2025 08:37
@Copilot Copilot bot review requested due to automatic review settings March 26, 2025 08:37
@Napalys Napalys requested a review from a team as a code owner March 26, 2025 08:37
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for the SAP HANA database client by modeling SQL injection sinks for the @sap/hana-client, @sap/hdbext, and hdb packages.

  • Added new test cases in the hana.js file to simulate SQL injection scenarios.
  • Introduced a YAML extension model file to map SQL injection sinks for the supported packages.
  • Updated the change notes to reflect the new enhancements.

Reviewed Changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated no comments.

File Description
javascript/ql/test/query-tests/Security/CWE-089/untyped/hana.js New test cases demonstrating various SQL injection sink flows.
javascript/ql/lib/ext/hana-db-client.model.yml YAML file mapping methods to SQL injection sinks for the packages.
javascript/ql/lib/change-notes/2025-03-26-hana-db-client.md Added change notes documenting the support for the new clients.
Files not reviewed (1)
  • javascript/ql/test/query-tests/Security/CWE-089/untyped/SqlInjection.expected: Language not supported
Comments suppressed due to low confidence (1)

javascript/ql/test/query-tests/Security/CWE-089/untyped/hana.js:38

  • [nitpick] The 'express' module is imported twice with different variable declarations; consider using 'const' consistently for clarity and maintainability.
var express = require('express');

Tip: If you use Visual Studio Code, you can request a review from Copilot before you push from the "Source Control" tab. Learn more

let maliciousInput = req.body.data; // $ MISSING: Source
client.exec('SELECT * FROM DUMMY' + maliciousInput, function (err, rs) {}); // $ MISSING: Alert

dbStream.createProcStatement(client, 'CALL PROC_DUMMY (?, ?, ?, ?, ?)' + maliciousInput, function (err, stmt) { // $ MISSING: Alert
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is technically SQL injection. It's loading a stored procedure, and calling that with some arguments.

An attacker can definitely not do the usual SQL-injection attacks (e.g. inserting " OR 1=1 ").
But it still seems wrong to allow a user to control that string, so I suppose it's fine.
Did you have any thoughts on this kind of sink?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The concern I had was that, while typical SQL injection might not be possible, there's still a risk that users could invoke procedures they shouldn’t have access to or perform other unauthorized actions. 🤔

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine to err on the side of generating more alerts rather than fewer alerts for this case.

Comment on lines 46 to 48
var client = req.db;
let maliciousInput = req.body.data; // $ Source
client.exec('SELECT * FROM DUMMY' + maliciousInput, function (err, rs) {}); // $ MISSING: Alert
client.exec('SELECT * FROM DUMMY' + maliciousInput, function (err, rs) {}); // $ Alert
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would have been nice to restrict this sink to only the cases where we've detected the app1.use(hdbext.middleware(hanaConfig)); call.
But we can't express that with MaD.

So this will support all databases that attach themselves to the req.db property (and have an exec(..) method).
I think that's fine, but I would like a second opinion @asgerf.

Copy link
Contributor Author

@Napalys Napalys Mar 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'm definitely not proud of the way I wrote this SQL sink, but I couldn't think of a way to express that in Model as Data. 🙈 The odds seem to be very low that there would exist path like this unrelated to hdbext.middleware(hanaConfig).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to go the extra mile here in order to make this work properly, because it's quite common to extend request/response objects from middlewares.

I'll aim to put up a PR that adds support for a new access path component called GuardedRouteHandler which should do what we need here. The idea is that it goes from the middleware object to all the route handlers guarded by it.

We should then be able to write the model like this:

Screenshot 2025-03-27 at 13 39 21

I have a working proof of concept locally just need to polish it up a bit.

You can either

  • leave this PR open and wait for GuardedRouteHandler support, or
  • remove the express line from the model and mark the alerts as MISSING and merge as it is. I'll add it back when adding GuardedRouteHandler support.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll leave this PR open and wait for GuardedRouteHandler support.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed f3af23e

@Napalys Napalys force-pushed the js/hana_db_client branch from b79d906 to f887c4c Compare March 28, 2025 13:07
@Napalys Napalys force-pushed the js/hana_db_client branch from f887c4c to 45c8ec9 Compare March 28, 2025 14:02
@Napalys Napalys requested review from asgerf and erik-krogh March 28, 2025 14:03
extensible: typeModel
data:
- ["hdb.Client", "hdb", "Member[createClient].ReturnValue"]
- ["hdb.Client", "@sap/hdbext", "Member[middleware].ReturnValue.GuardedRouteHandler.Parameter[0].Member[db]"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you also add a test that reg.db.exec(..) isn't a sink when there is no call to hdb.createClient().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 32d6ac8

@Napalys Napalys force-pushed the js/hana_db_client branch from 01ff06e to 32d6ac8 Compare March 30, 2025 12:09
@Napalys Napalys merged commit de8a328 into github:main Mar 31, 2025
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants