This rule pertains to avoiding SQL Injection, which is a serious security vulnerability that can allow attackers to manipulate or control your database. SQL Injection occurs when untrusted data is inserted into a database query without proper sanitization or parameterization.
In the provided non-compliant code, the SQL queries are constructed by string concatenation with user-provided input. This is a dangerous practice as it allows an attacker to inject arbitrary SQL code into the query. For instance, if an attacker provides an ‘id’ value of “1; DROP TABLE analysis_results;”, it could lead to the deletion of an entire table.
To avoid SQL Injection, always use parameterized queries or prepared statements, which ensure that user-provided input is always treated as literal values, not executable code. In Ruby, you can use the ‘quote’ and ‘sanitize’ methods provided by ActiveRecord, or use ‘?’ placeholders in your SQL queries to safely include user-provided input. For example, you could write: ActiveRecord::Base.connection.execute("UPDATE analysis_results SET running_time_sec = ? WHERE id = ?", time, id). This ensures that the ’time’ and ‘id’ values are properly escaped, preventing SQL Injection.
Non-Compliant Code Examples
# controller# params[:q] = "'; DROP TABLE users; --"@users=User.where("email LIKE '%#{params[:q]}%'")
classNonCompliantController<ApplicationControllerdefshow(event:,context:)conn=PG::Connection.open(:dbname=>'datadog')res2=conn.exec_params('SELECT $1 AS a FROM B where C like %{id}'%{id:event['id']})res5=conn.exec_params("SELECT * AS a FROM B where C like #{event['id']}")enddefupdate2user=User.where("user_id = '#{params[:user][:id]}'")[0]ifuseruser.update_attributes(user_params_without_password)elseflash[:error]="Could not update user!"redirect_to"app.datadoghq.com/security/appsec/vm/library"endenddeftest3records=ActiveRecord::Base.connection.execute("INSERT INTO events (name) VALUES ('%s')"%params[:user])redirect_to"app.datadoghq.com/security/appsec/vm/library"enddeftest4records=ActiveRecord::Base.connection.execute(Kernel::sprintf("SELECT FROM event WHERE name='%s'",params[:user]))redirect_to"app.datadoghq.com/security/appsec/vm/library"enddeftest5records=ActiveRecord::Base.connection.execute("SELECT FROM event WHERE name='"+params[:user]+"'")redirect_to"app.datadoghq.com/security/appsec/vm/library"enddeftext_biouser=User.find_by"name = '#{params[:user_name]}'"endend
classCompliantController<ApplicationControllerdefshow(event:,context:)conn=PG::Connection.open(:dbname=>'datadog')res=conn.exec_params('SELECT $1 AS a FROM B where C like %D%',[event['id'],1,nil])res3=conn.exec_params('SELECT $1 AS a FROM B where C like {id}'%{id:"something"})query='SELECT $1 AS a FROM B where C like '+"something"res4=conn.exec_params(query)puts("SELECT * FROM foobar WHERE id = #{event['id']}")enddefok_test1message="Compliant example %s"%params[:user]redirect_tomessageenddefok_test2message=Kernel::sprintf("Compliant example %s",params[:user])redirect_tomessageenddefok_test3records="this is ok!"+params[:user]+"'"redirect_torecordsenddefok_test4user=User.where("id = ?","#{params[:id]}")[0]enddefok_test5redirect_url=params[:redirect]redirect_to"app.datadoghq.com/security/appsec/vm/library/{redirect_url}"endend
# Faraday HTTP client — not a DB call, should not be flaggeddefdelete_all_for_user_id(user_id)@client.delete_all(obfuscate_user_id(user_id))end
원활한 통합. Datadog Code Security 사용해 보기
Datadog Code Security
이 규칙을 사용해 Datadog Code Security로 코드 분석해 보기
이 규칙의 사용법
1
2
rulesets:- ruby-security # Rules to enforce Ruby security.
리포지토리 루트에서 위의 콘텐츠를 사용해 static-analysis.datadog.yml 생성
Datadog의 무료 IDE Plugins를 사용하거나 Code Security 스캔을 CI 파이프라인에 추가