CVE-2015-2972 (Ruby, published 2015-07-19T15:59Z)
Description: value: Multiple SQL injection vulnerabilities in Sysphonic Thetis before 2.3.0 allow remote attackers to execute arbitrary SQL commands via unspecified vectors.
Severity: HIGH (CVSS v3 base score: )
Weakness: CWE-89 \u2014 Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.
Repository: https://github.com/sysphonic/thetis
Files changed:
app/controllers/addressbook_controller.rb
app/controllers/config_controller.rb
app/controllers/desktop_controller.rb
app/controllers/equipment_controller.rb
app/controllers/folders_controller.rb
app/controllers/groups_controller.rb
app/controllers/items_controller.rb
app/controllers/locations_controller.rb
app/controllers/login_controller.rb
app/controllers/logs_controller.rb
app/controllers/mail_accounts_controller.rb
app/controllers/mail_filters_controller.rb
app/controllers/mail_folders_controller.rb
app/controllers/official_titles_controller.rb
app/controllers/paintmail_controller.rb
app/controllers/researches_controller.rb
app/controllers/schedules_controller.rb
app/controllers/send_mails_controller.rb
app/controllers/teams_controller.rb
app/controllers/templates_controller.rb
app/controllers/timecards_controller.rb
app/controllers/users_controller.rb
app/controllers/workflows_controller.rb
app/controllers/zeptair_dist_controller.rb
app/controllers/zeptair_post_controller.rb
app/controllers/zeptair_xlogs_controller.rb
app/helpers/addressbook_helper.rb
app/helpers/application_helper.rb
app/models/research.rb
Commit message: Reinforcement of security.
Signed-off-by: MORITA Shintaro <shin@sysphonic.com>


Vulnerable code:
    return if (params[:id].nil? or params[:id].empty? or @login_user.nil?)
#Copyright:: Copyright (c) 2007-2011 MORITA Shintaro, Sysphonic. All rights reserved.
      next if params[cat].nil? or params[cat].empty?
#Copyright:: Copyright (c) 2007-2011 MORITA Shintaro, Sysphonic. All rights reserved.
    unless params[:desktop].nil? or params[:desktop].empty?
#Copyright:: Copyright (c) 2007-2011 MORITA Shintaro, Sysphonic. All rights reserved.
    if (params[:groups].nil? or params[:groups].empty?)
    if (params[:teams].nil? or params[:teams].empty?)
    if date_s.nil? or date_s.empty?
#Copyright:: Copyright (c) 2007-2011 MORITA Shintaro, Sysphonic. All rights reserved.
    if params[:thetisBoxEdit].nil? or params[:thetisBoxEdit].empty?
    unless params[:thetisBoxEdit].nil? or params[:thetisBoxEdit].empty?
    if params[:thetisBoxSelKeeper].nil? or params[:thetisBoxSelKeeper].empty?
    if params[:id] != '0'
        @folder = Folder.find(params[:id])
    session[:folder_id] = params[:id]
      @folder = Folder.find(params[:id])
    session[:folder_id] = params[:id]
        @folder.set_read_users read_users
        @folder.set_write_users write_users
    if @group_id.nil? or @group_id.empty?
      @folder = Folder.find(params[:id])
    session[:folder_id] = params[:id]
      @folder.set_read_groups read_groups
      @folder.set_write_groups write_groups
      @folder = Folder.find(params[:id])
    session[:folder_id] = params[:id]
      @folder.set_read_teams read_teams
      @folder.set_write_teams write_teams
    folder_id = params[:id]

     Log.add_info(request, params.inspect)
    if params[:thetisBoxEdit].nil? or params[:thetisBoxEdit].empty?
    unless params[:thetisBoxEdit].nil? or params[:thetisBoxEdit].empty?
      @group.rename params[:thetisBoxEdit]
    if params[:thetisBoxSelKeeper].nil? or params[:thetisBoxSelKeeper].empty?
#Copyright:: Copyright (c) 2007-2011 MORITA Shintaro, Sysphonic. All rights reserved.
    unless params[:select_sorting].nil? or params[:select_sorting].empty?
    if params[:keyword].nil? or params[:keyword].empty?
    if !params[:select_sorting].nil?
    if params[:folder_id].nil? or params[:folder_id].empty?
      orders << '|' + value.split(',').join('|') + '|'
    if params[:id].nil? or params[:id].empty?
    if params[:id].nil? or params[:id].empty?
      @item.attributes = params[:item]
        remove_method :record_timestamps
    if params[:id].nil? or params[:id].empty?
      @item.attributes = params[:item]
    parent_item = attach.item || ((attach.comment.nil?) ? nil : attach.comment.item)
        remove_method :record_timestamps
   begin
      ensure
        if @team.nil?
          flash[:notice] = t('msg.already_deleted', :name => Team.model_name.human)
          return
        end
        @team.save if modified = @team.clear_users


    if location_id.nil? or location_id.empty?
    return if params[:id].nil? or params[:id].empty? or @login_user.nil?
#Copyright:: Copyright (c) 2007-2011 MORITA Shintaro, Sysphonic. All rights reserved.
      if params[:fwd_controller].nil? or params[:fwd_controller].empty?
      if params[:fwd_controller].nil? or params[:fwd_controller].empty?
#Copyright:: Copyright (c) 2007-2011 MORITA Shintaro, Sysphonic. All rights reserved.
    return if params[:id].nil? or params[:id].empty? or @login_user.nil?
#Copyright:: Copyright (c) 2007-2012 MORITA Shintaro, Sysphonic. All rights reserved.
    return if (params[:id].nil? or params[:id].empty? or @login_user.nil?)
#Copyright:: Copyright (c) 2007-2011 MORITA Shintaro, Sysphonic. All rights reserved.
    if params[:thetisBoxEdit].nil? or params[:thetisBoxEdit].empty?
    unless params[:thetisBoxEdit].nil? or params[:thetisBoxEdit].empty?
        mail_account_id = params[:mail_account_id]
      folder_ids = nil
      add_con = nil

      folder_ids = [@folder_id]

      sql = EmailsHelper.get_list_sql(@login_user, params[:keyword], folder_ids, @sort_col, @sort_type, 0, add_con)
    mail_id = params[:id]
      @email = Email.find(mail_id)
    SqlHelper.validate_token([mail_account_id])
    emails = MailFolder.get_mails(mail_folder.id, @login_user) || []

  rescue => evar
    Log.add_error(request, evar)
    render(:partial => 'ajax_folders_order', :layout => false)
    return if params[:id].nil? or params[:id].empty? or @login_user.nil?
#Copyright:: Copyright (c) 2007-2013 MORITA Shintaro, Sysphonic. All rights reserved.
    unless official_title_id.nil? or official_title_id.empty?
    unless official_title_id.nil? or official_title_id.empty?
    if @group_id.nil? or @group_id.empty?
#Copyright:: Copyright (c) 2007-2011 MORITA Shintaro, Sysphonic. All rights reserved.
    Research.save_config_yaml yaml
    if !params[:thetisBoxSelKeeper].nil?
    if group_id.nil? or group_id.empty?
      @group_ids = Research.get_statistics_groups 
    unless current_id.nil? or current_id.empty?
      Research.delete_statistics_group current_id
    @group_ids = Research.add_statistics_group group_id
    if group_id.nil? or group_id.empty?
    @group_ids = Research.delete_statistics_group group_id
    Research.set_statistics_groups order_ary
            Research.destroy_all('user_id=' + user_id.to_s)
#Copyright:: Copyright (c) 2007-2013 MORITA Shintaro, Sysphonic. All rights reserved.
          equipment = Equipment.find(equipment_id)
        if params[:fwd_controller].nil? or params[:fwd_controller].empty?
    if date_s.nil? or date_s.empty?
    if date_s.nil? or date_s.empty?
    if date_s.nil? or date_s.empty?
    if date_s.nil? or date_s.empty?
    unless params[:thetisBoxSelKeeper].nil? or params[:thetisBoxSelKeeper].empty?
#Copyright:: Copyright (c) 2007-2011 MORITA Shintaro, Sysphonic. All rights reserved.
    if mail_account_id.nil? or mail_account_id.empty?
#Copyright:: Copyright (c) 2007-2011 MORITA Shintaro, Sysphonic. All rights reserved.
    return if params[:id].nil? or params[:id].empty? or @login_user.nil?
#Copyright:: Copyright (c) 2007-2011 MORITA Shintaro, Sysphonic. All rights reserved.
    if @group_id.nil? or @group_id.empty?
    if @group_id.nil? or @group_id.empty?
#Copyright:: Copyright (c) 2007-2011 MORITA Shintaro, Sysphonic. All rights reserved.
    if date_s.nil? or date_s.empty?
        date = Date.parse date_s
    if params[:id].nil? or params[:id].empty?
    if params[:user_id].nil? or params[:user_id].empty?
    elsif @login_user.id.to_s == params[:user_id]
        unless params[:timecard]['start'].nil? or params[:timecard]['start'].empty?
        unless params[:timecard]['end'].nil? or params[:timecard]['end'].empty?
    if date_s.nil? or date_s.empty?
      @date = Date.parse date_s
    unless params[:timecard].nil? or params[:timecard].empty?
#Copyright:: Copyright (c) 2007-2011 MORITA Shintaro, Sysphonic. All rights reserved.











    if params[:thetisBoxSelKeeper].nil? or params[:thetisBoxSelKeeper].empty?
      unless params[:current_id] == nil or params[:current_id].empty?
#        @user.update_attribute(:groups, @user.groups)
    if params[:group_id].nil? or params[:group_id].empty?




    User.save_config_titles titles



          User.save_config_titles titles
      if password.nil? or password.empty?
#Copyright:: Copyright (c) 2007-2011 MORITA Shintaro, Sysphonic. All rights reserved.
    return if params[:id].nil? or params[:id].empty? or @login_user.nil?
#Copyright:: Copyright (c) 2007-2011 MORITA Shintaro, Sysphonic. All rights reserved.
    unless params[:attach_id].nil? or params[:attach_id].empty?
    unless params[:cmd_id].nil? or params[:cmd_id].empty?
#Copyright:: Copyright (c) 2007-2011 MORITA Shintaro, Sysphonic. All rights reserved.

#Copyright:: Copyright (c) 2007-2011 MORITA Shintaro, Sysphonic. All rights reserved.
        yaml[:statistics].delete :groups
    Research.save_config_yaml yaml
      ary.delete ''
    Research.save_config_yaml yaml
    ary.delete ''
    Research.save_config_yaml yaml
          


Fixed code:
    return unless request.post?

    return unless request.post?

      @address = nil
    return unless request.post?

    return unless request.post?

    return unless request.post?

    return if (params[:id].blank? or @login_user.nil?)
#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
    return unless request.post?

      next if params[cat].blank?
    return unless request.post?

    return unless request.post?

    return unless request.post?

    return unless request.post?

#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
    return unless request.post?

    return unless request.post?

    return unless request.post?

    unless params[:desktop].blank?
    return unless request.post?

    return unless request.post?

    return unless request.post?

    SqlHelper.validate_token([params[:id]])
    return unless request.post?

        toy = nil
    return unless request.post?

    return unless request.post?

    return unless request.post?

#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
    return unless request.post?

    SqlHelper.validate_token([params[:groups], params[:teams]])

    return unless request.post?

    SqlHelper.validate_token([params[:groups], params[:teams]])

    if params[:groups].blank?
    if params[:teams].blank?
    return unless request.post?

      SqlHelper.validate_token([equipment_id])
    if date_s.blank?
#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
    return unless request.post?

    if params[:thetisBoxEdit].blank?
    return unless request.post?

    unless params[:thetisBoxEdit].blank?
    return unless request.post?

    return unless request.post?

    if params[:thetisBoxSelKeeper].blank?
    SqlHelper.validate_token([@selected_id])
    SqlHelper.validate_token([@folder_id])
      SqlHelper.validate_token([@sort_col, @sort_type])
    SqlHelper.validate_token([@folder_id])
        @folder = nil
    return unless request.post?

    SqlHelper.validate_token([@folder_id, @group_id])
    return unless request.post?

        folder = nil
    folder_id = params[:id]
    SqlHelper.validate_token([folder_id])

    if folder_id != '0'
        @folder = Folder.find(folder_id)
    session[:folder_id] = folder_id
    return unless request.post?

    SqlHelper.validate_token([folder_id])
    folder_id = params[:id]
    SqlHelper.validate_token([folder_id])

      @folder = Folder.find(folder_id)
    session[:folder_id] = folder_id
      @folder = nil
    return unless request.post?

        @folder.set_read_users(read_users)
        @folder.set_write_users(write_users)
    SqlHelper.validate_token([@group_id])

    if @group_id.blank?
    folder_id = params[:id]
    SqlHelper.validate_token([folder_id])

      @folder = Folder.find(folder_id)
    session[:folder_id] = folder_id
    return unless request.post?

      @folder.set_read_groups(read_groups)
      @folder.set_write_groups(write_groups)
    folder_id = params[:id]
    SqlHelper.validate_token([folder_id])

      @folder = Folder.find(folder_id)
    session[:folder_id] = folder_id
    return unless request.post?

      @folder.set_read_teams(read_teams)
      @folder.set_write_teams(write_teams)
            item = nil
    SqlHelper.validate_token([folder_id])
            item = nil
    Log.add_info(request, params.inspect)

    return unless request.post?
    if params[:thetisBoxEdit].blank?
    return unless request.post?

    unless params[:thetisBoxEdit].blank?
      @group.rename(params[:thetisBoxEdit])
    return unless request.post?

    SqlHelper.validate_token([params[:id]])
    return unless request.post?

    if params[:thetisBoxSelKeeper].blank?
    SqlHelper.validate_token([@selected_id])
    return unless request.post?

    SqlHelper.validate_token([group_id])
            user = nil
    return unless request.post?

    SqlHelper.validate_token([org_group_id, group_id])
            user = nil
    SqlHelper.validate_token([@group_id])
    SqlHelper.validate_token([@group_id])
    return unless request.post?

        group = nil
    SqlHelper.validate_token([@group_id])
    SqlHelper.validate_token([@group_id])
    SqlHelper.validate_token([@group_id])
#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
    SqlHelper.validate_token([@folder_id])
    unless params[:select_sorting].blank?
    if params[:keyword].blank?
    unless params[:select_sorting].nil?
    if params[:folder_id].blank?
      @item = nil
    return unless request.post?

    return unless request.post?

    SqlHelper.validate_token([folder_id])
          item = nil
    return unless request.post?

    return unless request.post?

    return unless request.post?

    return unless request.post?

      user_ids = value.split(',')
      SqlHelper.validate_token([user_ids])
      orders << '|' + user_ids.join('|') + '|'
    return unless request.post?

    return unless request.post?

    if params[:id].blank?
    return unless request.post?

    if params[:id].blank?
      @item.attributes = params.require(:item).permit(Item::PERMIT_BASE)
    return unless request.post?

    return unless request.post?

    return unless request.post?

        remove_method(:record_timestamps)
    return unless request.post?

    if params[:id].blank?
      @item.attributes = params.require(:item).permit(Item::PERMIT_BASE)
    parent_item = (attach.item || ((attach.comment.nil?) ? nil : attach.comment.item))
    return unless request.post?

    return unless request.post?

    return unless request.post?

        remove_method(:record_timestamps)
    return unless request.post?

    return unless request.post?

    return unless request.post?

    return unless request.post?

    return unless request.post?

    return unless request.post?

    begin
    return unless request.post?

      end
      if @team.nil?
        flash[:notice] = t('msg.already_deleted', :name => Team.model_name.human)
        return
        modified = @team.clear_users
        @team.save if modified
    return unless request.post?

    return unless request.post?

    return unless request.post?

    return unless request.post?

    return unless request.post?

    SqlHelper.validate_token([params[:id]])

    return unless request.post?

    SqlHelper.validate_token([location_id])
    if location_id.blank?
        location = nil
      SqlHelper.validate_token([group_id])
    return if params[:id].blank? or @login_user.nil?
#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
      if params[:fwd_controller].blank?
      if params[:fwd_controller].blank?

    return unless request.post?

    return unless request.post?

#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
    return unless request.post?

    return unless request.post?

    SqlHelper.validate_token([mail_account_id])
    return if params[:id].blank? or @login_user.nil?
#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
    return unless request.post?

    return unless request.post?

          filter = nil
    return unless request.post?

    return unless request.post?

    return if (params[:id].blank? or @login_user.nil?)
#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
    return unless request.post?

    if params[:thetisBoxEdit].blank?
    return unless request.post?

    unless params[:thetisBoxEdit].blank?
    return unless request.post?

    SqlHelper.validate_token([mail_account_id])
    return unless request.post?

    SqlHelper.validate_token([parent_id])

      mail_account_id = params[:mail_account_id]
      SqlHelper.validate_token([mail_account_id])

    SqlHelper.validate_token([@folder_id])

      SqlHelper.validate_token([@sort_col, @sort_type])
      sql = EmailsHelper.get_list_sql(@login_user, params[:keyword], [@folder_id], @sort_col, @sort_type, 0, nil)
    email_id = params[:id]
      @email = Email.find(email_id)
    return unless request.post?

    SqlHelper.validate_token([@folder_id, mail_account_id])
    emails = (MailFolder.get_mails(mail_folder.id, @login_user) || [])
    return unless request.post?

    SqlHelper.validate_token([folder_id, mail_account_id])
    return unless request.post?

    SqlHelper.validate_token([@folder_id])
    return unless request.post?

    return unless request.post?

    return if params[:id].blank? or @login_user.nil?
#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
    SqlHelper.validate_token([@group_id, official_title_id])
    unless official_title_id.blank?
    SqlHelper.validate_token([@group_id, official_title_id])
    unless official_title_id.blank?
    return unless request.post?

    SqlHelper.validate_token([@group_id, official_title_id])
    return unless request.post?

    SqlHelper.validate_token([@group_id])
    if @group_id.blank?
    return unless request.post?

    SqlHelper.validate_token([@group_id])

    return unless request.post?

#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
    return unless request.post?

    return unless request.post?

    return unless request.post?

    Research.save_config_yaml(yaml)
    return unless request.post?

    return unless request.post?

    unless params[:thetisBoxSelKeeper].nil?
    SqlHelper.validate_token([current_id, group_id])
    if group_id.blank?
      @group_ids = Research.get_statistics_groups
    unless current_id.blank?
      Research.delete_statistics_group(current_id)
    @group_ids = Research.add_statistics_group(group_id)
    return unless request.post?

    SqlHelper.validate_token([group_id])
    if group_id.blank?
    @group_ids = Research.delete_statistics_group(group_id)
    return unless request.post?

    Research.set_statistics_groups(order_ary)
    return unless request.post?

    return unless request.post?

    return unless request.post?

    return unless request.post?

          SqlHelper.validate_token([user_id])
            Research.destroy_all("user_id=#{user_id.to_i}")
    return unless request.post?

    return unless request.post?

    return unless request.post?

#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
    return unless request.post?

    return unless request.post?

      SqlHelper.validate_token([holidays])
    return unless request.post?

        SqlHelper.validate_token([params[attr]])
          begin
            equipment = Equipment.find(equipment_id)
          rescue => evar
            equipment = nil
          end
        if params[:fwd_controller].blank?
    return unless request.post?

    if date_s.blank?
    if date_s.blank?
    if date_s.blank?
    SqlHelper.validate_token([@group_id, params[:id]])
    if date_s.blank?
    unless params[:thetisBoxSelKeeper].blank?
#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
    if mail_account_id.blank?
      SqlHelper.validate_token([account_xtype])
    return unless request.post?

    return unless request.post?

    return unless request.post?

    return unless request.post?

#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
    return unless request.post?

    return if params[:id].blank? or @login_user.nil?
#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
    return unless request.post?

    SqlHelper.validate_token([@group_id])
    if @group_id.blank?
    return unless request.post?

    SqlHelper.validate_token([@group_id])
    if @group_id.blank?
    return unless request.post?

    return unless request.post?

    return unless request.post?

#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
    if date_s.blank?
        date = Date.parse(date_s)
    return unless request.post?

    if params[:id].blank?
    if params[:user_id].blank?
    elsif (@login_user.id.to_s == params[:user_id])
        unless params[:timecard]['start'].blank?
        unless params[:timecard]['end'].blank?
    return unless request.post?

    return unless request.post?

    return unless request.post?

    if date_s.blank?
      @date = Date.parse(date_s)
      SqlHelper.validate_token([display_id])
    return unless request.post?

    return unless request.post?

    SqlHelper.validate_token([group_id, users_hash.keys])

    return unless request.post?

    unless params[:timecard].blank?
    return unless request.post?

    return unless request.post?

#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
    return unless request.post?

    return unless request.post?

    return unless request.post?

        SqlHelper.validate_token([user_id])
    return unless request.post?

    return unless request.post?

    return unless request.post?

    return unless request.post?

    if params[:thetisBoxSelKeeper].blank?
      unless params[:current_id].blank?
    return unless request.post?

    if params[:group_id].blank?
    return unless request.post?

    return unless request.post?

    return unless request.post?

    return unless request.post?

    User.save_config_titles(titles)
    return unless request.post?

    return unless request.post?

          User.save_config_titles(titles)
    return unless request.post?

    return unless request.post?

      if password.blank?
#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
    return unless request.post?

    return unless request.post?

    return unless request.post?

    return if params[:id].blank? or @login_user.nil?
#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
    return unless request.post?

    unless params[:attach_id].blank?
    unless params[:cmd_id].blank?
#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
    return unless request.post?

    return unless request.post?

#Copyright:: Copyright (c) 2007-2015 MORITA Shintaro, Sysphonic. All rights reserved.
    return unless request.post?

    SqlHelper.validate_token([params[:check_xlog].keys])
    return unless request.post?

    SqlHelper.validate_token([group_ids, team_ids])

  #=== self.stacktrace
  #
  #Gets backtrace.
  #
  #return:: Backtrace.
  #
  def self.stacktrace
    begin
      raise('')
    rescue => evar
      paths = Rails.root.split('/')
      paths.delete('')
      stacktrace = evar.backtrace.select {|line| !(line.match(paths.last).nil?)}.join("\n")
      stacktrace.pop  # Remove current stack.
    end
    return stacktrace
  end

        yaml[:statistics].delete(:groups)
    Research.save_config_yaml(yaml)
      ary.delete('')
    Research.save_config_yaml(yaml)
    ary.delete('')
    Research.save_config_yaml(yaml)