How to avoid SQL injection on query - python

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.

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.

Preventing SQL Injection for online SQL querying

I have a small Python project site where a visitor can practice writing SQL code. This code actually runs and returns values. I know that I need to prevent SQL injection, but I'm not sure the best approach since the purpose of the site is that users should be able to write and execute arbitrary SQL code against a real database.
What should I look to do to prevent malicious behavior? I want to prevent statements such as DROP xyz;, but users should still be able to execute code. I think maybe the ideal solution is that users can only "read" from the database, ie. they can only run SELECT statements (or variations). But I'm not sure if "read only" captures all edge cases of malicious behavior.
Need to prevent malicious SQL querying, but also need to allow users to execute code
Using SQLite now but will probably move to postgres
I'm strictly using SQL at this point but may want to add Python and other languages in the future
The site is built with Python (Flask)
Any ideas or suggestions would be helpful
There is no way to prevent SQL injection for a site that takes SQL statements as user input and runs them verbatim. The purpose of the site is SQL injection. The only way you can prevent SQL injection is to not develop this site.
If you do develop the site, how can you prevent malicious SQL? Answer: don't let malicious users have access to this site. Only allow trusted users to use it.
Okay, I assume you do want to develop the site and you do want to allow all users, without doing a lot of work to screen them.
Then it becomes a task of limiting the potential damage they can do. Restrict their privileges carefully, so they only have access to create objects and run queries in a specific schema.
Or better yet, launch a Docker container for each individual to have their own private database instance, and restrict the CPU and memory the container can use.

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']))

Is a SQLAlchemy query vulnerable to injection attacks?

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.

Parsing SQL Query into a DOM-like tree to enable automatic permutation?

I have a large and complicated sql view that I am attempting to debug. There is a record not showing in the view and I need to determine which clause or join is causing the record to now show up. At the moment I am doing this in a very manual way, removing clauses one at a time and running the query to see if the required row shows up.
I think that it would be great if I could do this programmatically because I end up diving into queries like this about once a fortnight.
Does anybody know if there is a way to parse an SQL query into a tree of objects (for example those in sqlalchemy.sql.expression) so I am able to permuate the tree and execute the results?
If you don't already have the view defined in SQLAlchemy, I don't think it can help you.
You could try something like sqlparse which might get you some of the way there.
You could permute it's output and execute the permutations as raw sql using SQLA.

Categories