Is a SQLAlchemy query vulnerable to injection attacks? - python

I have the following query that uses like to search a blog. I am not sure if I'm making myself vulnerable to a SQL injection attack if I do this. How is SQLAlchemy handling this? Is it safe?
search_results = Blog.query.with_entities(Blog.blog_title).filter(Blog.blog_title.like("%"+ searchQuery['queryText'] +"%")).all()

The underlying db-api library for whatever database you're using (sqlite3, psycopg2, etc.) escapes parameters. SQLAlchemy simply passes the statement and parameters to execute, the driver does whatever is needed. Assuming you are not writing raw SQL that includes parameters yourself, you are not vulnerable to injection. Your example is not vulnerable to injection.

Related

Autocomplete SQL query in db.execute('') on VScode

When writing SQL query in python (Flask, if that's necessary) execute(), is there a setting or extensions that would recognize SQL keywords like SELECT, UPDATE, and suggest them with IntelliSense or the like?
Right now the query is recognized as in the picture and keywords are not being suggested.
SQL query keywords in VScode are not recognized (the whole query is green)
No, because you're just putting in a string into execute() that is later read by SQLAlchemy (which I assume you're using). These aren't actually python keywords which IntelliSense can predict. However, you can use the SQLAlchemy ORM, or the higher level query object, which does not use SQL keywords but python methods to manipulate your database. Using this, you might find that IntelliSense can find the definition/declaration of the SQLAlchemy method and offer the usual pointers and helpers it does.
There are other advantages of using the higher level query class of SQLAlchemy, a significant one being you are less likely to be subject to SQL injections and attacks. Because you are executing raw SQL with the execute() command and simply putting an id from the session in, an attacker could alter the session value and inject harmful SQL into your application.
Anyway, that's beside the point but I thought it was worth letting you know.

How to avoid SQL injection on query

My SQL query construction in python code is:
query = '''
SELECT {return_col}
FROM {table_name}
'''.format(colA, tableA)
When I run Bandit security tool, it says "Possible SQL injection vector through string-based query construction."
How do I avoid it?
Best practices recommend to avoid to dynamically build the query and instead use a parameterized query. But the goal is precisely to avoid what you are doing here: prevent a forged parameter to allow an arbitrary query.
If you know why you allow to query any field on any table, and if the account running the query has only SELECT privilege on the database, then you can ignore the warning: it just says that you could allow requests on any table... what you want to do!
But kindly examine the security implications. In some use cases it may be perfectly fine, in others it could be terrible.

Integrate PyQt with a sql orm library (sqlalchemy, peewee, etc.)

PyQt has some nice features like QSqlTableModel and QSqlRelationalTableModel, however, it doesn't contain ORM functionalities and I hate using raw SQL statements in my program. What is a best way to integrate a SQL ORM library like Sqlalchemy, to PyQt SQL facilities? Currently the only solution I can think of is to build my object models in SqlAlchemy and execute the compiled SQL statements with QSqlDatabase manually. Is there any better way to do this? Are there any ways, say, to build a custom backend/adapter for SqlAlchemy that use QSqlDatabase? Other ORM libraries like Peewee are fine, too.
https://docs.sqlalchemy.org/en/13/core/engines.html?highlight=create_engine#sqlalchemy.create_engine
Create a fake engine using the 'mock' strategy that redirects all compiled sql statements to the QSqlDatabase to execute.
There seems to be a catch: functionalities that require interaction with a real database will not work, like checking if a table exists before creation.
Also this doesn't seem to work with the Session API, any calls to commit() and flush() will cause a NotImplementedError.

Is SQL injection protection built into SQLAlchemy's ORM or Core?

I'm developing an aiohttp server application, and I just saw that apparently it isn't able to use SQLAlchemy's ORM layer. So, I was wondering: if my application will only be able to use SQLAlchemy's core, is it still protected against SQL injection attacks?
My code is the following:
async def add_sensor(db_engine, name):
async with db_engine.acquire() as connection:
query = model.Sensor.__table__.insert().values(name=name)
await connection.execute(query)
A comment on the accepted answer in this related question makes me doubt:
you can still use execute() or other literal data that will NOT be
escaped by SQLAlchemy.
So, with the execute() used in my code, does the above quote mean that my code is unsafe? And in general: is protection against SQL Injection only possible with the SQLAlchemy ORM layer, as with the Core layer you'll end up launching execute()?
in your example above i dont see any variable beeing supplied to the database query. Since there is no user supplied input there is also no Sql Injection possible.
Even if there would be a user supplied value as long as you dont use handwritten sql statements with sqlalchemy and instead use the orm model approach (model.Sensor.__table__.select()) as can be seen in your example you are secure against Sql Injection.
In the end its all about telling sqlalchemy explicitely what columns and tables should be used to select and insert data from/to and keeping that separate from the data that is beeing inserted or selected. Never combine the data string with the query string and always use sqlalchemy orm model objects to describe your query.
Bad way (Sql Injectable):
Session.execute("select * form users where name = %s" % request.GET['name'])
Good way (Not Sql Injectable):
Session.execute(model.users.__table__.select().where(model.users.name == request.GET['name']))

In SQLAlchemy how do I preview SQL statements before committing for debugging purposes?

I want to see the SQL code instead of doing an actual db.commit(). This is for a one-off database population script that I want to verify is working as intended before actually making the changes.
Try calling str() on the query object.
print query_object.str()
From:
How do I get a raw, compiled SQL query from a SQLAlchemy expression?
Other possible solutions:
SQLAlchemy: print the actual query
How to retrieve executed SQL code from SQLAlchemy
The newest (as of v0.9) answer is also:
Retrieving ultimate sql query sentence (with the values in place of any '?') (by Mike Bayer)

Categories