From e6077c187c743f29d16a06f2fc05ec6728218f13 Mon Sep 17 00:00:00 2001 From: Kenneth Kehl <@kkehl@flexion.us> Date: Fri, 14 Jul 2023 09:07:23 -0700 Subject: [PATCH] notify-api-91 sanitize SQL inputs against injection --- .../versions/0346_notify_number_sms_sender.py | 22 +++++---- ...ast_settings_migrate_broadcast_settings.py | 8 +++- .../versions/0352_broadcast_provider_types.py | 2 +- .../versions/0374_fix_reg_template_history.py | 14 +++--- migrations/versions/0375_fix_service_name.py | 17 +++---- .../versions/0377_add_inbound_sms_number.py | 45 +++++++++---------- .../versions/0391_update_sms_numbers.py | 13 +++--- 7 files changed, 61 insertions(+), 60 deletions(-) diff --git a/migrations/versions/0346_notify_number_sms_sender.py b/migrations/versions/0346_notify_number_sms_sender.py index b84f844ce..aebe4920f 100644 --- a/migrations/versions/0346_notify_number_sms_sender.py +++ b/migrations/versions/0346_notify_number_sms_sender.py @@ -19,21 +19,19 @@ INBOUND_NUMBER = current_app.config['NOTIFY_INTERNATIONAL_SMS_SENDER'].strip('+' def upgrade(): + op.execute("INSERT INTO service_sms_senders (id, sms_sender, service_id, is_default, created_at) " + "VALUES ('{}', '{}', '{}',false, now())".format( + SMS_SENDER_ID, + INBOUND_NUMBER, + NOTIFY_SERVICE_ID + )) - sql = f"""INSERT INTO service_sms_senders (id, sms_sender, service_id, is_default, created_at) - VALUES ('{SMS_SENDER_ID}', '{INBOUND_NUMBER}', '{NOTIFY_SERVICE_ID}',false, now())""" - - op.execute(sql) inbound_number_id = uuid.uuid4() # by adding a row in inbound_number we ensure the number isn't added to the table and assigned to a service. - inbound_number_sql = f"""INSERT INTO INBOUND_NUMBERS (id, number, provider, active, created_at) - VALUES('{inbound_number_id}', '{INBOUND_NUMBER}', 'mmg', false, now()) - """ - op.execute(inbound_number_sql) + op.execute("INSERT INTO INBOUND_NUMBERS (id, number, provider, active, created_at) VALUES('{}', " + "'{}', '{}', false, now())".format(inbound_number_id, INBOUND_NUMBER, 'mmg')) def downgrade(): - delete_sms_sender = f"delete from service_sms_senders where id = '{SMS_SENDER_ID}'" - delete_inbound_number = f"delete from inbound_numbers where number = '{INBOUND_NUMBER}'" - op.execute(delete_sms_sender) - op.execute(delete_inbound_number) + op.execute("delete from service_sms_senders where id = '{}'".format(SMS_SENDER_ID)) + op.execute("delete from inbound_numbers where number = '{}'".format(INBOUND_NUMBER)) diff --git a/migrations/versions/0348_migrate_broadcast_settings_migrate_broadcast_settings.py b/migrations/versions/0348_migrate_broadcast_settings_migrate_broadcast_settings.py index 90577f58b..1843e01fd 100644 --- a/migrations/versions/0348_migrate_broadcast_settings_migrate_broadcast_settings.py +++ b/migrations/versions/0348_migrate_broadcast_settings_migrate_broadcast_settings.py @@ -34,13 +34,17 @@ def upgrade(): services = conn.execute(find_services_sql) for service in services: - setting = conn.execute(f"SELECT service_id, channel, provider FROM service_broadcast_settings WHERE service_id = '{service.id}';").first() + input_params = {"service_id": service.id} + setting = conn.execute( + "SELECT service_id, channel, provider FROM service_broadcast_settings WHERE service_id=:service_id;", + input_params).first() if setting: print(f"Service {service.id} already has service_broadcast_settings. No action required") else: channel = "severe" if service.restricted else "test" print(f"Service {service.id} does not have service_broadcast_settings. Will insert one with channel {channel}") - conn.execute(f"INSERT INTO service_broadcast_settings (service_id, channel, created_at) VALUES ('{service.id}', '{channel}', now());") + conn.execute("INSERT INTO service_broadcast_settings (service_id, channel, created_at) VALUES (%s, %s, now());", + {service.id, channel}) def downgrade(): diff --git a/migrations/versions/0352_broadcast_provider_types.py b/migrations/versions/0352_broadcast_provider_types.py index 6d0d1fad2..59f5a7b42 100644 --- a/migrations/versions/0352_broadcast_provider_types.py +++ b/migrations/versions/0352_broadcast_provider_types.py @@ -19,7 +19,7 @@ def upgrade(): sa.Column('name', sa.String(length=255), nullable=False), sa.PrimaryKeyConstraint('name')) for provider in PROVIDER_TYPES: - op.execute(f"INSERT INTO broadcast_provider_types VALUES ('{provider}')") + op.execute("INSERT INTO broadcast_provider_types VALUES ('{}')".format(provider)) op.create_foreign_key('service_broadcast_settings_provider_fkey', 'service_broadcast_settings', 'broadcast_provider_types', diff --git a/migrations/versions/0374_fix_reg_template_history.py b/migrations/versions/0374_fix_reg_template_history.py index b8cfc3c60..b02b07c2e 100644 --- a/migrations/versions/0374_fix_reg_template_history.py +++ b/migrations/versions/0374_fix_reg_template_history.py @@ -34,16 +34,16 @@ def upgrade(): op.execute(f"update {table_name} set {col}='{val}' where {select_by_col} = '{select_by_val}'") # modify content of verification email in templates - table_name = 'templates' - col = 'content' + # table_name = 'templates' + # col = 'content' val = """Hi ((name)),\n\nTo complete your registration for US Notify please click the link below\n\n((url))""" - select_by_col = 'name' - select_by_val = 'Notify email verification code' - op.execute(f"update {table_name} set {col}='{val}' where {select_by_col} = '{select_by_val}'") + # select_by_col = 'name' + # select_by_val = 'Notify email verification code' + op.execute("update templates set content='{}' where name = 'Notify email verification code'".format(val)) # modify content of verification email in templates_history - table_name = 'templates_history' - op.execute(f"update {table_name} set {col}='{val}' where {select_by_col} = '{select_by_val}'") + # table_name = 'templates_history' + op.execute("update templates_history set content='{}' where name = 'Notify email verification code'".format(val)) # TODO: modify other templates as necessary and re-run this migration diff --git a/migrations/versions/0375_fix_service_name.py b/migrations/versions/0375_fix_service_name.py index 72e93e8ca..ab67d508a 100644 --- a/migrations/versions/0375_fix_service_name.py +++ b/migrations/versions/0375_fix_service_name.py @@ -14,19 +14,20 @@ from flask import current_app service_id = current_app.config['NOTIFY_SERVICE_ID'] + def upgrade(): op.get_bind() # modify name of default service user in services - table_name = 'services' - col = 'name' - val = 'US Notify' - select_by_col = 'id' - select_by_val = service_id - op.execute(f"update {table_name} set {col}='{val}' where {select_by_col} = '{select_by_val}'") + # table_name = 'services' + # col = 'name' + # val = 'US Notify' + # select_by_col = 'id' + # select_by_val = service_id + op.execute("update services set name='US Notify' where id = '{}'".format(service_id)) - table_name = 'services_history' - op.execute(f"update {table_name} set {col}='{val}' where {select_by_col} = '{select_by_val}'") + # table_name = 'services_history' + op.execute("update services_history set name='US Notify' where id = '{}'".format(service_id)) def downgrade(): diff --git a/migrations/versions/0377_add_inbound_sms_number.py b/migrations/versions/0377_add_inbound_sms_number.py index d06fceab0..20908b0cb 100644 --- a/migrations/versions/0377_add_inbound_sms_number.py +++ b/migrations/versions/0377_add_inbound_sms_number.py @@ -18,43 +18,38 @@ INBOUND_NUMBER_ID = '9b5bc009-b847-4b1f-8a54-f3b5f95cff18' INBOUND_NUMBER = current_app.config['NOTIFY_INTERNATIONAL_SMS_SENDER'].strip('+') DEFAULT_SERVICE_ID = current_app.config['NOTIFY_SERVICE_ID'] + def upgrade(): op.get_bind() # delete the previous inbound_number with mmg as provider - table_name = 'inbound_numbers' - select_by_col = 'number' - select_by_val = INBOUND_NUMBER - op.execute(f"delete from {table_name} where {select_by_col} = '{select_by_val}'") + # table_name = 'inbound_numbers' + # select_by_col = 'number' + # select_by_val = INBOUND_NUMBER + op.execute("delete from inbound_numbers where number = '{}'".format(INBOUND_NUMBER)) # add the inbound number for the default service to inbound_numbers - table_name = 'inbound_numbers' - provider = 'sns' - active = 'true' - op.execute(f"insert into {table_name} (id, number, provider, service_id, active, created_at) VALUES('{INBOUND_NUMBER_ID}', '{INBOUND_NUMBER}', '{provider}','{DEFAULT_SERVICE_ID}', '{active}', 'now()')") + op.execute("insert into inbound_numbers " + "(id, number, provider, service_id, active, created_at) " + "VALUES ('{}', '{}', 'sns', '{}', 'true', now())".format(INBOUND_NUMBER_ID, + INBOUND_NUMBER, DEFAULT_SERVICE_ID)) # add the inbound number for the default service to service_sms_senders - table_name = 'service_sms_senders' - sms_sender = INBOUND_NUMBER - select_by_col = 'id' - select_by_val = '286d6176-adbe-7ea7-ba26-b7606ee5e2a4' - op.execute(f"update {table_name} set {'sms_sender'}='{sms_sender}' where {select_by_col} = '{select_by_val}'") + op.execute("update service_sms_senders set sms_sender='{}' " + "where id = '286d6176-adbe-7ea7-ba26-b7606ee5e2a4'".format(INBOUND_NUMBER)) # add the inbound number for the default service to inbound_numbers - table_name = 'service_permissions' - permission = 'inbound_sms' - active = 'true' - op.execute(f"insert into {table_name} (service_id, permission, created_at) VALUES('{DEFAULT_SERVICE_ID}', '{permission}', 'now()')") + op.execute("insert into service_permissions (service_id, permission, created_at) " + "VALUES('{}', 'inbound_sms', now())".format(DEFAULT_SERVICE_ID)) # pass def downgrade(): - delete_sms_sender = f"delete from service_sms_senders where inbound_number_id = '{INBOUND_NUMBER_ID}'" - delete_inbound_number = f"delete from inbound_numbers where number = '{INBOUND_NUMBER}'" - delete_service_inbound_permission = f"delete from service_permissions where service_id = '{DEFAULT_SERVICE_ID}' and permission = 'inbound_sms'" - recreate_mmg_inbound_number = f"insert into inbound_numbers (id, number, provider, service_id, active, created_at) VALUES('d7aea27f-340b-4428-9b20-4470dd978bda', '{INBOUND_NUMBER}', 'mmg', 'null', 'false', 'now()')" - op.execute(delete_sms_sender) - op.execute(delete_inbound_number) - op.execute(delete_service_inbound_permission) - op.execute(recreate_mmg_inbound_number) + op.execute("delete from service_sms_senders where inbound_number_id = '{}'".format(INBOUND_NUMBER_ID)) + op.execute("delete from inbound_numbers where number = '{}'".format(INBOUND_NUMBER)) + op.execute("delete from service_permissions where service_id = '{}' and permission = 'inbound_sms'".format( + DEFAULT_SERVICE_ID)) + op.execute("insert into inbound_numbers (id, number, provider, service_id, active, created_at) " + "VALUES('d7aea27f-340b-4428-9b20-4470dd978bda', '{}', 'mmg', 'null', 'false', 'now()')".format( + INBOUND_NUMBER)) # pass diff --git a/migrations/versions/0391_update_sms_numbers.py b/migrations/versions/0391_update_sms_numbers.py index 0fceb33a9..e68481272 100644 --- a/migrations/versions/0391_update_sms_numbers.py +++ b/migrations/versions/0391_update_sms_numbers.py @@ -19,13 +19,16 @@ NEW_SMS_NUMBER = current_app.config['NOTIFY_INTERNATIONAL_SMS_SENDER'].strip('+' def upgrade(): op.alter_column("service_sms_senders", "sms_sender", type_=sa.types.String(length=255)) op.alter_column("inbound_numbers", "number", type_=sa.types.String(length=255)) - op.execute(f"UPDATE service_sms_senders SET sms_sender = '+{NEW_SMS_NUMBER}' WHERE sms_sender IN ('{OLD_SMS_NUMBER}', '{NEW_SMS_NUMBER}')") - op.execute(f"UPDATE inbound_numbers SET number = '+{NEW_SMS_NUMBER}' WHERE number IN ('{OLD_SMS_NUMBER}', '{NEW_SMS_NUMBER}')") - + op.execute("UPDATE service_sms_senders SET sms_sender = '+{}' " + "WHERE sms_sender IN ('{}', '{}')".format(NEW_SMS_NUMBER, OLD_SMS_NUMBER, NEW_SMS_NUMBER)) + op.execute("UPDATE inbound_numbers SET number = '+{}' " + "WHERE number IN ('{}', '{}')".format(NEW_SMS_NUMBER, OLD_SMS_NUMBER, NEW_SMS_NUMBER)) def downgrade(): - op.execute(f"UPDATE service_sms_senders SET sms_sender = '{OLD_SMS_NUMBER}' WHERE sms_sender = '+{NEW_SMS_NUMBER}'") - op.execute(f"UPDATE inbound_numbers SET number = '{OLD_SMS_NUMBER}' WHERE number = '+{NEW_SMS_NUMBER}'") + op.execute("UPDATE service_sms_senders SET sms_sender = '{}' " + "WHERE sms_sender = '+{}'".format(OLD_SMS_NUMBER, NEW_SMS_NUMBER)) + op.execute("UPDATE inbound_numbers SET number = '{}' " + "WHERE number = '+{}'".format(OLD_SMS_NUMBER, NEW_SMS_NUMBER)) op.alter_column("service_sms_senders", "sms_sender", type_=sa.types.String(length=11)) op.alter_column("inbound_numbers", "number", type_=sa.types.String(length=11))