SQL Injection as a Feature

idiallo.com

100 points by foxfired 5 days ago


adontz - 3 days ago

What people often don't realize is that in a big business system a user may have no permission to raw data of some table, but may have permission to report which includes aggregated data of the same table, so report permissions cannot be deducted from base CRUD permissions.

If such SIAAS

    - Checks that query is SELECT query (can be tricky with CTE, requires proper SQL parser)
    - Allows editing said query by superuser only
    - Can be parametrized, including implicit $current_user_id$ parameter
    - Has it's own permissions and users can run the query if they have permissions
It's safe enough. I've seen and applied such "Edit raw SQL in HTML form" many times. It's super flexible, especially combined with some CSV-to-HTML, CSV-to-PDF, or CSV-to-XLS rendering engine.
EvanAnderson - 3 days ago

I am reminded of a Customer's grown up "tribal knowledge" around a long-unsupported custom application.

Typically and sadly, the developer used string concatenation to build queries. Some users figured out (or, perhaps, saw the developer do it) they could abuse "filter" fields in the Win32 thick-client application to get filtering functionality the client otherwise didn't offer.

Contrived example: AR aging report doesn't allow for filtering by Customer city. It does allow filtering by Customer name. In the Customer name filter box enter "' OR [City] = 'Boston" to get an AR aging report for only Boston customers.

The users had built-up a Word document with various magical incantations to get data they couldn't otherwise get.

I was impressed by the ingenuity even though it was all horrifying. (The application ran as the database server's superuser-equivalent with the password hard-coded in the client, so nothing was stop somebody from completely trashing the server. >sigh<)

ivanjermakov - 3 days ago

> In the code, someone added a string search for INSERT, UPDATE, and CREATE. If any of these strings were detected, the page returned an unauthorized response.

STRING SEARCH? If only there was a way to limit connection privileges to read-only DML.

dml2135 - 3 days ago

Ha, this reminds me of a story from my old job, before I became a software engineer.

I worked for an artist and we had an inventory system that a freelance web developer had built for us. I think it was some sort of php, laravel, mysql stack. There was a search bar that you could use to bring up records of artworks.

Everyone at the studio used this system but I was the main person that used it. Over time, I picked up some little tricks here and there. These were useful because engaging this freelance guy for new features involved a lot of back and forth, so if I could find my own improvement to a workflow that was always the easier option.

We didn't have a clear way to pull up works for a single decade. Until I somehow discovered that you could use `%` as a wildcard character in some cases, so I could pull up paintings from the 1970s but searching for `197%`, for example.

I remember proudly telling this to the freelance dev at one point and his eyes widened and he almost looked panicked. In retrospect I recognize that he was thinking about whether he left the system open to an injection attack.

By the end of my job there I had learned enough about this to realize it was a risk but didn't get curious enough to see if a `; DROP TABLE` query would work.

lenkite - 3 days ago

Gave analysts a workspace of their own with a SQLite snapshot copy of the main db. They could do whatever they liked with that copy with the tool of their choice.

zihotki - 3 days ago

When I worked on a similar functionality, I used sql parser and AST walker to verify that no mutations are done and only a subset of sql was whitelisted. That worked as a charm and it wasn't hard to implement. Benefits - no sql injections, cheap syntax check.

louis_saglio - 3 days ago

This is actually what SQL was intended for.

heckintime - 3 days ago

At this point, it'd be easier to give your users access to DBeaver or Bigquery directly. Also limiting their access to certain views with prepared data to avoid expensive queries.

For a UI based SQL tool I've used Looker few years ago and thought it was ok. I wonder how much AI tooling Google added since then to help with LookML generation. There are also other open source tools like mathesar (https://github.com/mathesar-foundation/mathesar) which look promising.

crazygringo - 3 days ago

It's easy in most modern multiuser databases to restrict a database user to SELECT privileges only, and to set a query timeout of something like 5 seconds (or 30 or whatever is appropriate), right?

Then the queries can be run only using that database user, and there's no risk of INSERT/UPDATE/DELETE. Injection isn't possible. And you can limit access to only the relevant tables as well, so you can't accidentally leak PII.

LikesPwsh - 3 days ago

Giving analysts direct SQL access can be great, but you should tell them to use an IDE rather than trying to build your own IDE in a text box.

subarctic - 3 days ago

The "machine fired me" story linked at the end is kind of spooky, especially these days when everyone's trying to use ai to automate as much as possible so they don't get left behind

codingdave - 3 days ago

I've been in scenarios when such UIs existed. But they always were protected so that only system admins had access to it, as a way to let them make quick queries in-app instead of having to pull up other tools. There was no additional access granted, it was just a question of UX, and we expected that anything beyond a simple ad-hoc query would be done with real tools, not in the app.

Also, the underlying databases were secured. Just because you can send a query to a database does not mean you are exposing additional data - database-level security exists and works well.

somat - 3 days ago

Not quite the same, but for a toy application I was building I had one of those terrible/clever ideas "hey the database has this elaborate comprehensive permission system, Why not have that be my applications permission system as well"

So every user is a database user and if the database sez they can view the data then they can view the data. And for my use case it worked surprisingly well.

I will note note that I think this is generally a bad idea, I have heard that the postgres role data structures scale poorly. and I personally would be terrified to expose a database to a potentially hostile environment.

See also: the schemaverse a game where you directly interface with the db server. https://github.com/Abstrct/Schemaverse

fifticon - 3 days ago

Why did the story end with a reference to "the machine fired me" essay (which I assume to be fiction, though admittedly funny and soon to be AI reality).

Is he implying, that tampering with the devil's query engine would get him escorted out of the building, or just trying to hook me up on the next story?

zX41ZdbW - 3 days ago

I use the approach of public apps built on top of free-form SQL queries. Examples:

https://adsb.exposed/ - type any query and get a visualization.

https://play.clickhouse.com/ - explore the database as you want without logging in.

EGreg - 3 days ago

Some of my clients actually wanted to be able to make arbitrary queries in the database.

And this isn't just about SQL queries. Often, people want to be able to make privileged changes to json config files, etc. etc.

So, I added a feature to the Qbix framework, to do just that. Essentially you have some privileged payloads, signed off by an Auditor role with their private key. You might even require M of N keys.

Then, for each Target (e.g. a database) you can use an ACL or Roles+Permissions for who can actually execute the payload against it.

This can be used on:

  * Smart Contracts

  * SQL Queries on Databases

  * Upgrade Scripts on Nix machines

  * Updates on package managers (versions that were vetted)
and much more.

Usually, when you have a bunch of "n00bs" who shouldn't be trusted with X, you want to set up a class of Auditors who sign off on the latest changes, and then a class of Admins who manage the roles, including Auditors and Users.

You don't need sys admins or dev ops. Just have standard container images / AMIs etc. and support only those. Don't even allow ssh into the instance, if you can help it. Let the instance be a pristine environment (Trusted Execution Environment) and discover arbitrary updates at well-known URLs, such as on github. You can have mirrors and fallbacks, but the key is that M of N Auditors from the organization's whitelist have signed off on the arbitrary code of any upgrade, whether delivered via a package manager or a git post-commit hook.

And all updates become automatic, and available to the n00bs to use. Role-based access is always enforced per-target when they attempt to use it. Inside the black box you can use simple HMAC to verify authorizations it issued earlier.

It took me a while to understand this, but the only way to solve security is to either have "pristine environments" that can run arbitrary code but always check M of N signatures for updates, with "byzantine fault tolerant consensus" on top. In the first one, you have to trust cloud providers. For the second one, you sacrifice some privacy. (e.g. with the new FreeNet's smart contracts).

PS: the M of N signatures might have to be hardened against quantum computers, so rather than using elliptic curve cryptography you might want to use lattice-based or my favorite quantum-resistant approach: SPHINCS+ based on Lamport signatures.

theknarf - 2 days ago

At that point just create a database user with read only permissions, delete the entire tool, and give them a copy of "mysql workbench" or "phpMyAdmin" or something similar.

- 20 hours ago
[deleted]
nogotnu - 20 hours ago

You actually reopened BI-tools (Tableau and others)