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

Use zen_internals sql tokenizer #213

Merged
merged 42 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
a4bbddc
Update __init__.py and remove old sql injection algo
Sep 24, 2024
800a0ad
It's only up until 1 char user input
Sep 24, 2024
14d82b4
Better integer test using regex in sql_injection algo
Sep 24, 2024
97002ff
Bugfix for should_return_early sql inj : .contains => in
Sep 25, 2024
5b14d89
Add unit tests for should_return_early in sql_injection algo
Sep 25, 2024
3144aca
Update good and bad sql commands to remove mails, invalid sql and "are"
Sep 25, 2024
6d7de6b
Move union i snot union test to IS_NOT_INJECTION
Sep 25, 2024
76320ea
Remove parameterization of "dangerous chars"
Sep 25, 2024
4dd66f7
foobar) foobar ) and eurofoobar are all examples of sql injections
Sep 25, 2024
5297560
'123' as userinput should not be marked as an injection
Sep 25, 2024
8ade460
Bugfix : Lower query and user input on python side before sending to …
Sep 25, 2024
40f966a
Remove dialects and interchange them with an integer map
Sep 25, 2024
88d7696
Fix test_allow_escape_sequences by setting to not sql injection
Sep 25, 2024
b2c650e
Change what is "invalid query" and what is not
Sep 25, 2024
aa0183e
Fix safely escaped test with backtick
Sep 25, 2024
28bbcd5
Allow for alphanumerical input with dashes
Sep 26, 2024
14821e0
Used wrong naming, dashes when in fact referring to underscores
Sep 26, 2024
2df772c
Move keyword-only queries to "bad queries"
Sep 26, 2024
61a0383
Only lowercase query and userinput once
Sep 27, 2024
ba58135
Update makefile to auto download zen library with install and build
Sep 27, 2024
bfdb293
Use the new folder/naming of the lib.so file in sql injection
Sep 27, 2024
4c71136
Update all github workflows to use make commands for install
Sep 27, 2024
0335ade
Remove dialects from sink tests
Sep 27, 2024
6830d47
Allow aikido_zen/lib/*.so to be included in project, use for download
Sep 27, 2024
3085616
Add comments explaining the reasoning behind removing/altering tests
Sep 27, 2024
a600ee0
Add comments explaining why we removed the e-mail tests
Sep 27, 2024
07d28c6
Add comm'ents test back in as "Mysql" specific
Sep 30, 2024
3b1909f
Allow dialects in is_sql_injection and is_not_sql_injection
Sep 30, 2024
87dde9a
Add mysql specific tests and tests back in for backticks
Sep 30, 2024
dedc404
Also test escaped strings from dangerous strs as not injection
Sep 30, 2024
042a71e
Add comments for given query and add positive counter-examples
Oct 1, 2024
97433b6
Return false if return integer is 2
hansott Oct 23, 2024
00fbb56
Use `logger.debug`
hansott Oct 23, 2024
cbf04e3
Merge branch 'main' into update-sql-injection-algo-to-tokenizer
Nov 26, 2024
c12a0b2
Linting
Nov 26, 2024
bac09da
Download all rust binaries
Nov 26, 2024
6329071
Try-except and use get_lib_path
Nov 26, 2024
f197586
Fix makefile
Nov 26, 2024
af057c8
Fix a broken unit test that has a dialect import
Nov 26, 2024
b4b911d
Bump zen_internals v0.1.26 --> v0.1.31
Nov 26, 2024
b00e0fe
Get the library after early return in sql_injeciton algorithm
Nov 26, 2024
941b377
Update Makefile
bitterpanda63 Nov 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@ jobs:
- name: Add local.aikido.io to /etc/hosts
run: |
sudo echo "127.0.0.1 local.aikido.io" | sudo tee -a /etc/hosts
- name: Install poetry
run: pip install poetry
- name: Install dependencies
run: poetry install
- name: Installation
run: make install
- name: Run Pylint
run: |
poetry run pylint --fail-under=9 --rcfile=.pylintrc aikido_zen/
Expand Down Expand Up @@ -50,9 +48,6 @@ jobs:
- uses: actions/checkout@v4
- name: Install poetry
run: pip install poetry
- name: Install dependencies
run: poetry install

- name: Publish to PyPI
env:
POETRY_HTTP_BASIC_PYPI_USERNAME: __token__
Expand Down
6 changes: 2 additions & 4 deletions .github/workflows/test-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@ jobs:
- name: Add local.aikido.io to /etc/hosts
run: |
sudo echo "127.0.0.1 local.aikido.io" | sudo tee -a /etc/hosts
- name: Install poetry
run: pip install poetry
- name: Install dependencies
run: poetry install
- name: Installation
run: make install
- name: Run Pylint
run: |
poetry run pylint --fail-under=9 --rcfile=.pylintrc aikido_zen/
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ jobs:
run: |
python -m pip install --upgrade pip
make install
- name: Run tests with coverage
run: |
make cov
Expand Down
33 changes: 26 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.PHONY: build
build:
build: binaries _build
_build:
poetry build

.PHONY: clean
Expand All @@ -11,14 +11,12 @@ lint:
poetry run black aikido_zen/
poetry run pylint aikido_zen/

.PHONY: install
install:
install: binaries
pip install poetry
poetry install

.PHONY: dev_install
dev_install:
pip install poetry
dev_install: install _dev_install
_dev_install:
poetry install --with=dev


Expand All @@ -37,3 +35,24 @@ cov:
.PHONY: benchmark
benchmark:
k6 run -q ./benchmarks/flask-mysql-benchmarks.js

BASE_URL = https://github.com/AikidoSec/zen-internals/releases/download/v0.1.31
FILES = \
libzen_internals_aarch64-apple-darwin.dylib \
libzen_internals_aarch64-apple-darwin.dylib.sha256sum \
libzen_internals_aarch64-unknown-linux-gnu.so \
libzen_internals_aarch64-unknown-linux-gnu.so.sha256sum \
libzen_internals_x86_64-apple-darwin.dylib \
libzen_internals_x86_64-apple-darwin.dylib.sha256sum \
libzen_internals_x86_64-pc-windows-gnu.dll \
libzen_internals_x86_64-pc-windows-gnu.dll.sha256sum \
libzen_internals_x86_64-unknown-linux-gnu.so \
libzen_internals_x86_64-unknown-linux-gnu.so.sha256sum

binaries: binaries_make_dir $(addprefix aikido_zen/lib/, $(FILES))
binaries_make_dir:
rm -rf aikido_zen/lib
mkdir -p aikido_zen/lib/
aikido_zen/lib/%:
@echo "Downloading $*..."
curl -L -o $@ $(BASE_URL)/$*
7 changes: 3 additions & 4 deletions aikido_zen/sinks/asyncpg.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import copy
import aikido_zen.importhook as importhook
from aikido_zen.vulnerabilities.sql_injection.dialects import Postgres
from aikido_zen.background_process.packages import pkg_compat_check
import aikido_zen.vulnerabilities as vulns
from aikido_zen.helpers.logging import logger
Expand Down Expand Up @@ -36,7 +35,7 @@ def aikido_new__execute(_self, query, *args, **kwargs):
vulns.run_vulnerability_scan(
kind="sql_injection",
op="asyncpg.connection.Connection._execute",
args=(query, Postgres()),
args=(query, "postgres"),
)

return former__execute(_self, query, *args, **kwargs)
Expand All @@ -46,15 +45,15 @@ def aikido_new_executemany(_self, query, *args, **kwargs):
vulns.run_vulnerability_scan(
kind="sql_injection",
op="asyncpg.connection.Connection.executemany",
args=(query, Postgres()),
args=(query, "postgres"),
)
return former_executemany(_self, query, *args, **kwargs)

def aikido_new_execute(_self, query, *args, **kwargs):
vulns.run_vulnerability_scan(
kind="sql_injection",
op="asyncpg.connection.Connection.execute",
args=(query, Postgres()),
args=(query, "postgres"),
)
return former_execute(_self, query, *args, **kwargs)

Expand Down
5 changes: 2 additions & 3 deletions aikido_zen/sinks/mysqlclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import copy
import aikido_zen.importhook as importhook
from aikido_zen.vulnerabilities.sql_injection.dialects import MySQL
from aikido_zen.background_process.packages import pkg_compat_check
from aikido_zen.helpers.logging import logger
import aikido_zen.vulnerabilities as vulns
Expand All @@ -31,13 +30,13 @@ def aikido_new_execute(self, query, args=None):
logger.debug("Query is bytearray, normally comes from executemany.")
return prev_execute_func(self, query, args)
vulns.run_vulnerability_scan(
kind="sql_injection", op="MySQLdb.Cursor.execute", args=(query, MySQL())
kind="sql_injection", op="MySQLdb.Cursor.execute", args=(query, "mysql")
)
return prev_execute_func(self, query, args)

def aikido_new_executemany(self, query, args):
op = "MySQLdb.Cursor.executemany"
vulns.run_vulnerability_scan(kind="sql_injection", op=op, args=(query, MySQL()))
vulns.run_vulnerability_scan(kind="sql_injection", op=op, args=(query, "mysql"))
return prev_executemany_func(self, query, args)

setattr(mysql.Cursor, "execute", aikido_new_execute)
Expand Down
7 changes: 3 additions & 4 deletions aikido_zen/sinks/psycopg.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import copy
import aikido_zen.importhook as importhook
from aikido_zen.vulnerabilities.sql_injection.dialects import Postgres
from aikido_zen.background_process.packages import pkg_compat_check
import aikido_zen.vulnerabilities as vulns

Expand All @@ -27,19 +26,19 @@ def on_psycopg_import(psycopg):
def aikido_copy(self, statement, params=None, *args, **kwargs):
sql = statement
vulns.run_vulnerability_scan(
kind="sql_injection", op="psycopg.Cursor.copy", args=(sql, Postgres())
kind="sql_injection", op="psycopg.Cursor.copy", args=(sql, "postgres")
)
return former_copy_funtcion(self, statement, params, *args, **kwargs)

def aikido_execute(self, query, params=None, *args, **kwargs):
sql = query
vulns.run_vulnerability_scan(
kind="sql_injection", op="psycopg.Cursor.execute", args=(sql, Postgres())
kind="sql_injection", op="psycopg.Cursor.execute", args=(sql, "postgres")
)
return former_execute_function(self, query, params, *args, **kwargs)

def aikido_executemany(self, query, params_seq):
args = (query, Postgres())
args = (query, "postgres")
op = "psycopg.Cursor.executemany"
vulns.run_vulnerability_scan(kind="sql_injection", op=op, args=args)
return former_executemany_function(self, query, params_seq)
Expand Down
5 changes: 2 additions & 3 deletions aikido_zen/sinks/psycopg2.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import copy
import aikido_zen.importhook as importhook
from aikido_zen.vulnerabilities.sql_injection.dialects import Postgres
from aikido_zen.background_process.packages import pkg_compat_check
import aikido_zen.vulnerabilities as vulns

Expand All @@ -21,7 +20,7 @@ def execute(self, *args, **kwargs):
vulns.run_vulnerability_scan(
kind="sql_injection",
op="psycopg2.Connection.Cursor.execute",
args=(args[0], Postgres()), # args[0] : sql
args=(args[0], "postgres"), # args[0] : sql
)
if former_cursor_factory and hasattr(former_cursor_factory, "execute"):
return former_cursor_factory.execute(self, *args, **kwargs)
Expand All @@ -33,7 +32,7 @@ def executemany(self, *args, **kwargs):
vulns.run_vulnerability_scan(
kind="sql_injection",
op="psycopg2.Connection.Cursor.executemany",
args=(sql, Postgres()),
args=(sql, "postgres"),
)
if former_cursor_factory and hasattr(former_cursor_factory, "executemany"):
return former_cursor_factory.executemany(self, *args, **kwargs)
Expand Down
5 changes: 2 additions & 3 deletions aikido_zen/sinks/pymysql.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import copy
import logging
import aikido_zen.importhook as importhook
from aikido_zen.vulnerabilities.sql_injection.dialects import MySQL
from aikido_zen.background_process.packages import pkg_compat_check
import aikido_zen.vulnerabilities as vulns

Expand Down Expand Up @@ -34,13 +33,13 @@ def aikido_new_execute(self, query, args=None):
logger.debug("Query is bytearray, normally comes from executemany.")
return prev_execute_func(self, query, args)
vulns.run_vulnerability_scan(
kind="sql_injection", op="pymysql.Cursor.execute", args=(query, MySQL())
kind="sql_injection", op="pymysql.Cursor.execute", args=(query, "mysql")
)
return prev_execute_func(self, query, args)

def aikido_new_executemany(self, query, args):
op = "pymysql.Cursor.executemany"
vulns.run_vulnerability_scan(kind="sql_injection", op=op, args=(query, MySQL()))
vulns.run_vulnerability_scan(kind="sql_injection", op=op, args=(query, "mysql"))
return prev_executemany_func(self, query, args)

setattr(mysql.Cursor, "execute", aikido_new_execute)
Expand Down
11 changes: 5 additions & 6 deletions aikido_zen/sinks/tests/asyncpg_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import aikido_zen.sinks.asyncpg
import aikido_zen.sinks.os
from aikido_zen.background_process.comms import reset_comms
from aikido_zen.vulnerabilities.sql_injection.dialects import Postgres

kind = "sql_injection"
op = "MySQLdb.connections.query"
Expand Down Expand Up @@ -33,7 +32,7 @@ async def test_conn_execute(database_conn):
called_with_op = mock_run_vulnerability_scan.call_args[1]["op"]
called_with_kind = mock_run_vulnerability_scan.call_args[1]["kind"]
assert called_with_args[0] == query
assert isinstance(called_with_args[1], Postgres)
assert called_with_args[1] == "postgres"
assert called_with_op == "asyncpg.connection.Connection.execute"
assert called_with_kind == "sql_injection"

Expand All @@ -52,7 +51,7 @@ async def test_conn_fetchrow(database_conn):

called_with_args = mock_run_vulnerability_scan.call_args[1]["args"]
assert called_with_args[0] == query
assert isinstance(called_with_args[1], Postgres)
assert called_with_args[1] == "postgres"

await conn.close()

Expand All @@ -69,7 +68,7 @@ async def test_conn_fetch(database_conn):

called_with_args = mock_run_vulnerability_scan.call_args[1]["args"]
assert called_with_args[0] == query
assert isinstance(called_with_args[1], Postgres)
assert called_with_args[1] == "postgres"

await conn.close()

Expand All @@ -86,7 +85,7 @@ async def test_conn_fetchval(database_conn):

called_with_args = mock_run_vulnerability_scan.call_args[1]["args"]
assert called_with_args[0] == query
assert isinstance(called_with_args[1], Postgres)
assert called_with_args[1] == "postgres"

await conn.close()

Expand Down Expand Up @@ -152,6 +151,6 @@ async def test_conn_cursor(database_conn):

called_with_args = mock_run_vulnerability_scan.call_args[1]["args"]
assert called_with_args[0] == "BEGIN;"
assert isinstance(called_with_args[1], Postgres)
assert called_with_args[1] == "postgres"

await conn.close()
9 changes: 4 additions & 5 deletions aikido_zen/sinks/tests/mysqlclient_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from unittest.mock import patch
import aikido_zen.sinks.mysqlclient
from aikido_zen.background_process.comms import reset_comms
from aikido_zen.vulnerabilities.sql_injection.dialects import MySQL

kind = "sql_injection"
op = "MySQLdb.connections.query"
Expand All @@ -25,7 +24,7 @@ def test_cursor_execute(database_conn):
cursor.execute(query)
called_with_args = mock_run_vulnerability_scan.call_args[1]["args"]
assert called_with_args[0] == query
assert isinstance(called_with_args[1], MySQL)
assert called_with_args[1] == "mysql"

mock_run_vulnerability_scan.assert_called_once()
cursor.fetchall()
Expand All @@ -51,7 +50,7 @@ def test_cursor_execute_no_args(database_conn):
called_with_args[0]
== 'INSERT INTO dogs (dog_name, isAdmin) VALUES ("Doggo", TRUE)'
)
assert isinstance(called_with_args[1], MySQL)
assert called_with_args[1] == "mysql"

mock_run_vulnerability_scan.assert_called_once()
cursor.fetchall()
Expand Down Expand Up @@ -79,7 +78,7 @@ def test_cursor_executemany(database_conn):
called_with_args[0]
== "INSERT INTO dogs (dog_name, isAdmin) VALUES (%s, %s)"
)
assert isinstance(called_with_args[1], MySQL)
assert called_with_args[1] == "mysql"
mock_run_vulnerability_scan.assert_called_once()
database_conn.commit()
mock_run_vulnerability_scan.assert_called_once()
Expand All @@ -105,7 +104,7 @@ def test_cursor_execute_with_fstring(database_conn):
assert (
called_with_args[0] == "INSERT INTO dogs (dog_name, isAdmin) VALUES (%s, 1)"
)
assert isinstance(called_with_args[1], MySQL)
assert called_with_args[1] == "mysql"
mock_run_vulnerability_scan.assert_called_once()
database_conn.commit()
mock_run_vulnerability_scan.assert_called_once()
Expand Down
7 changes: 3 additions & 4 deletions aikido_zen/sinks/tests/psycopg2_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from unittest.mock import patch
import aikido_zen.sinks.psycopg2
from aikido_zen.background_process.comms import reset_comms
from aikido_zen.vulnerabilities.sql_injection.dialects import Postgres

kind = "sql_injection"
op = "pymysql.connections.query"
Expand All @@ -28,7 +27,7 @@ def test_cursor_execute(database_conn):

called_with_args = mock_run_vulnerability_scan.call_args[1]["args"]
assert called_with_args[0] == query
assert isinstance(called_with_args[1], Postgres)
assert called_with_args[1] == "postgres"
mock_run_vulnerability_scan.assert_called_once()

cursor.fetchall()
Expand All @@ -47,7 +46,7 @@ def test_cursor_execute_parameterized(database_conn):

called_with_args = mock_run_vulnerability_scan.call_args[1]["args"]
assert called_with_args[0] == query
assert isinstance(called_with_args[1], Postgres)
assert called_with_args[1] == "postgres"
mock_run_vulnerability_scan.assert_called_once()

database_conn.commit()
Expand All @@ -72,7 +71,7 @@ def test_cursor_executemany(database_conn):
called_with_args[0]
== "INSERT INTO dogs (dog_name, isadmin) VALUES (%s, %s)"
)
assert isinstance(called_with_args[1], Postgres)
assert called_with_args[1] == "postgres"
mock_run_vulnerability_scan.assert_called_once()

database_conn.commit()
Expand Down
Loading