require'brakeman/checks/base_check'#Checks for session key length and http_only settingsclassBrakeman::CheckSessionSettings<Brakeman::BaseCheckBrakeman::Checks.addself@description="Checks for session key length and http_only settings"definitialize*argssuperunlesstracker.options[:rails3]@session_settings=Sexp.new(:colon2,Sexp.new(:const,:ActionController),:Base)else@session_settings=nilendenddefrun_checksettings=tracker.config.session_settingscheck_for_issuessettings,@app_tree.file_path("config/environment.rb")session_store=@app_tree.file_path("config/initializers/session_store.rb")secret_token=@app_tree.file_path("config/initializers/secret_token.rb")[session_store,secret_token].eachdo|file|iftracker.initializers[file]andnotignored?file.basenameprocesstracker.initializers[file]endendiftracker.options[:rails4]check_secrets_yamlendend#Looks for ActionController::Base.session = { ... }#in Rails 2.x apps##and App::Application.config.secret_token =#in Rails 3.x apps##and App::Application.config.secret_key_base =#in Rails 4.x appsdefprocess_attrasgnexpifnottracker.options[:rails3]andexp.target==@session_settingsandexp.method==:session=check_for_issuesexp.first_arg,@app_tree.file_path("config/initializers/session_store.rb")endiftracker.options[:rails3]andsettings_target?(exp.target)and(exp.method==:secret_token=orexp.method==:secret_key_base=)andstring?exp.first_argwarn_about_secret_tokenexp.line,@app_tree.file_path("config/initializers/secret_token.rb")endexpend#Looks for Rails3::Application.config.session_store :cookie_store, { ... }#in Rails 3.x appsdefprocess_callexpiftracker.options[:rails3]andsettings_target?(exp.target)andexp.method==:session_storecheck_for_rails3_issuesexp.second_arg,@app_tree.file_path("config/initializers/session_store.rb")endexpendprivatedefsettings_target?expcall?expandexp.method==:configandnode_type?exp.target,:colon2andexp.target.rhs==:Applicationenddefcheck_for_issuessettings,fileifsettingsandhash?settingsifvalue=(hash_access(settings,:session_http_only)||hash_access(settings,:http_only)||hash_access(settings,:httponly))iffalse?valuewarn_about_http_onlyvalue.line,fileendendifvalue=hash_access(settings,:secret)ifstring?valuewarn_about_secret_tokenvalue.line,fileendendendenddefcheck_for_rails3_issuessettings,fileifsettingsandhash?settingsifvalue=hash_access(settings,:httponly)iffalse?valuewarn_about_http_onlyvalue.line,fileendendifvalue=hash_access(settings,:secure)iffalse?valuewarn_about_secure_onlyvalue.line,fileendendendenddefcheck_secrets_yamlsecrets_file=@app_tree.file_path("config/secrets.yml")ifsecrets_file.exists?andnotignored?"secrets.yml"andnotignored?"config/*.yml"yaml=secrets_file.readrequire'yaml'beginsecrets=YAML.safe_loadyaml,aliases: truerescuePsych::SyntaxError,RuntimeError=>eBrakeman.notify"[Notice] #{self.class}: Unable to parse `#{secrets_file}`"Brakeman.debug"Failed to parse #{secrets_file}: #{e.inspect}"returnendifsecrets&&secrets["production"]andsecret=secrets["production"]["secret_key_base"]unlesssecret.include?"<%="line=yaml.lines.find_index{|l|l.include?secret}+1warn_about_secret_tokenline,@app_tree.file_path(secrets_file)endendendenddefwarn_about_http_onlyline,filewarn:warning_type=>"Session Setting",:warning_code=>:http_cookies,:message=>"Session cookies should be set to HTTP only",:confidence=>:high,:line=>line,:file=>file,:cwe_id=>[1004]enddefwarn_about_secret_tokenline,filewarn:warning_type=>"Session Setting",:warning_code=>:session_secret,:message=>"Session secret should not be included in version control",:confidence=>:high,:line=>line,:file=>file,:cwe_id=>[798]enddefwarn_about_secure_onlyline,filewarn:warning_type=>"Session Setting",:warning_code=>:secure_cookies,:message=>"Session cookie should be set to secure only",:confidence=>:high,:line=>line,:file=>file,:cwe_id=>[614]enddefignored?file[".","config","config/initializers"].eachdo|dir|ignore_file=@app_tree.file_path("#{dir}/.gitignore")if@app_tree.exists?ignore_fileinput=ignore_file.readreturntrueifinput.include?fileendendfalseendend