app/periscope/periscope_controller.rb in periscope_rails-0.0.3 vs app/periscope/periscope_controller.rb in periscope_rails-0.0.4

- old
+ new

@@ -1,60 +1,76 @@ -class PeriscopeController < ActionController::Base - before_filter :authenticate - protect_from_forgery :except => [:look, :login] - - def look - if !params[:sql].nil? - render :json => run_sql(params[:sql]) - else - render :json => {:error => "Command not understood"} - end - end - - def login - render :json => get_info() - end - - private - - def authenticate - unless PeriscopeRails::Config.check_password(params[:password].to_s) - render :json => {:error => "Password invalid."} - end - end - - def run_sql(sql_command) - #TODO: protect based on CFG, not blacklist - bad_words = %W{drop delete update into insert index add remove grant revoke create createdb} - bad_words += %W{createuser createrole destroy disconnect exec execute dropdb primary key rollback ; --} - - rows = nil - error_message = nil - command = sql_command.to_s.strip - command_words = command.downcase.gsub(/[^a-zA-Z0-9]/, " ").gsub(/\s+/, " ").split(" ") - if command == "" - #nothing - elsif (command_words & bad_words).size > 0 - error_message = "Potentially harmful keyword found, blocking script." - else - begin - ActiveRecord::Base.transaction do - rows = ActiveRecord::Base.connection.select_all(command) - p rows - raise "OK" #abort all transactions for extra protection - end - rescue Exception => e - error_message = e.message unless e.message == "OK" - end - end - return {:error => error_message, :data => rows} - end - - def get_info - tables = [] - table_names = ActiveRecord::Base.connection.tables.sort - table_names.each do |table_name| - tables << {:name => table_name, :columns => ActiveRecord::Base.connection.columns(table_name)} - end - return {:tables => tables, :error => nil} - end -end \ No newline at end of file +class PeriscopeController < ApplicationController + before_filter :authenticate + protect_from_forgery :except => [:look, :login] + + def look + if !params[:sql].nil? + render :json => run_sql(params[:sql]) + else + render :json => {:error => "Command not understood"} + end + end + + def login + render :json => get_info() + end + + private + + def authenticate + unless PeriscopeRails::Config.check_password(params[:password].to_s) + render :json => {:error => "Password invalid."} + end + end + + def run_sql(sql_command) + #TODO: protect based on CFG, not blacklist + bad_words = %W{drop delete update into insert index add remove grant revoke create createdb} + bad_words += %W{createuser createrole destroy disconnect exec execute dropdb primary key rollback ; --} + + rows = nil + error_message = nil + command = sql_command.to_s.strip + command_words = command.downcase.gsub(/[^a-zA-Z0-9]/, " ").gsub(/\s+/, " ").split(" ") + if command == "" + #nothing + elsif (command_words & bad_words).size > 0 + error_message = "Potentially harmful keyword found, blocking script." + else + begin + #custom_db_creds = PeriscopeRails::Config.get_db_creds() + #if custom_db_creds.nil? + # active_record = ActiveRecord::Base + #else + # # TODO: Establish this connection once rather than every time a query is issued + # active_record = Class.new(ActiveRecord::Base) + # custom_db_config = ActiveRecord::Base.connection_config.merge(custom_db_creds) + # active_record.establish_connection(custom_db_config) + #end + active_record = PeriscopeRails::Config.get_active_record() + active_record.transaction do + rows = active_record.connection.select_all(command) + rows.each do |row| + row.each_key do |column| + if PeriscopeRails::Config.matches_filter(column) + row[column] = '[FILTERED]' + end + end + end + raise "OK" #abort all transactions for extra protection + end + rescue Exception => e + error_message = e.message unless e.message == "OK" + end + end + return {:error => error_message, :data => rows} + end + + def get_info + tables = [] + table_names = ActiveRecord::Base.connection.tables.sort + table_names.each do |table_name| + tables << {:name => table_name, :columns => ActiveRecord::Base.connection.columns(table_name)} + end + return {:tables => tables, :error => nil} + end +end