3. I’m not a guru.
Khalid Baheyeldin Gerhard Killesreiter
These f olks are
Joshua Brauer Andy Kirkham
Dries Buytaert Greg Knaddison
Angela Byron Kieran Lal (coordinator) Drupal Security Team
Robert Castelo Adam Light
http://drupal.org/security-team
Nathaniel Catchpole John Morahan
Stéphane Corlosquet Karoly Negyesi
Heine Deelstra (team leader) Stella Power
Neil Drumm David Rothstein
Ben Jeavons Jakub Suchy
Dmitri Gaskin Mori Sugimoto (coordinator)
James Gilliland David Strauss
Charlie Gordon Oleg Terenchuk
Gábor Hojtsy Damien Tournoud
Morbus Iff Moshe Weitzman
Bart Jansens Peter Wolanin
Barry Jaspan Derek Wright
Chris Johnson Dave Reid
6. Reasons to be concerned
1. Security holes can lose time and money
Security hole
7. Reasons to be concerned
1. Security holes can lose time and money
2. Or get you sued
Security hole
8. Reasons to be concerned
1. Security holes can lose time and money
2. Or get you sued
3. Or be terribly embarrassing
Security hole
9. Reasons to be concerned
1. Security holes can lose time and money
2. Or get you sued
3. Or be terribly embarrassing
4. Users are slow to upgrade (your old code can be
around for a long time)
Security hole
10. Reasons to be concerned
1. Security holes can lose time and money
2. Or get you sued
3. Or be terribly embarrassing
4. Users are slow to upgrade (your old code can be
around for a long time)
5. If you want a Drupal CVS account, your request
can get a red flag if you’re not following basic
security protocol
Security hole
11. Reasons to be concerned
1. Security holes can lose time and money
2. Or get you sued
3. Or be terribly embarrassing
4. Users are slow to upgrade (your old code can be
around for a long time)
5. If you want a Drupal CVS account, your request
can get a red flag if you’re not following basic
security protocol
6. Drupal is becoming a more and more attractive Security hole
target
13. What we’re going to cover
1. Set up a free dev environment to play
14. What we’re going to cover
1. Set up a free dev environment to play
2. The golden rule of Drupal security
15. What we’re going to cover
1. Set up a free dev environment to play
2. The golden rule of Drupal security
3. A quick definition of common attaxss
16. What we’re going to cover
1. Set up a free dev environment to play
2. The golden rule of Drupal security
3. A quick definition of common attaxss
4. Our arsenal of functions (+ examples)
17. What we’re going to cover
1. Set up a free dev environment to play
2. The golden rule of Drupal security
3. A quick definition of common attaxss
4. Our arsenal of functions (+ examples)
5. Questions (maybe even some answers!)
18. What we’re going to cover
1. Set up a free dev environment to play
2. The golden rule of Drupal security
3. A quick definition of common attaxss
4. Our arsenal of functions (+ examples)
5. Questions (maybe even some answers!)
20. Set up a free dev enviornment
1. Don’t have an editor? Browse with Filezilla http://filezilla-
project.org/ and open in text editor.
21. Set up a free dev enviornment
1. Don’t have an editor? Browse with Filezilla http://filezilla-
project.org/ and open in text editor.
2. Sign up for an account at http://webenabled.com
22. Set up a free dev enviornment
1. Don’t have an editor? Browse with Filezilla http://filezilla-
project.org/ and open in text editor.
2. Sign up for an account at http://webenabled.com
3. After signing in, create an Acquia appliation (has a bunch
of modules already bundled)
23. Set up a free dev enviornment
1. Don’t have an editor? Browse with Filezilla http://filezilla-
project.org/ and open in text editor.
2. Sign up for an account at http://webenabled.com
3. After signing in, create an Acquia appliation (has a bunch
of modules already bundled)
4. Copy the SSH info, and connect using your editor.
26. The Golden Rule of Drupal Security
Whatchoothink?
Use the APIs.
27. The Golden Rule of Drupal Security
Whatchoothink?
Use the APIs.
This isn’t so bad.
28. The Golden Rule of Drupal Security
Whatchoothink?
Use the APIs.
This isn’t so bad.
29. The Golden Rule of Drupal Security
Whatchoothink?
Use the APIs.
This isn’t so bad.
APIs take a little while to learn
30. The Golden Rule of Drupal Security
Whatchoothink?
Use the APIs.
This isn’t so bad.
APIs take a little while to learn
31. The Golden Rule of Drupal Security
Whatchoothink?
Use the APIs.
This isn’t so bad.
APIs take a little while to learn Nearly every security-related
function has awesome side
benefits.
36. Common Attaxss
XSS - Cross-Site Scripting
SQL Injection
DOS - Denial of service
CSRF - Cross Site Request Forgeries
37. Our arsenal of functions
We need guns. 10 or so guns.
String filtering
Links
Access control
Database
Data passing
38. Our arsenal of functions
We need guns. 10 or so guns.
String filtering t()
Links
Access control
Database
Data passing
39. Our arsenal of functions
We need guns. 10 or so guns.
String filtering t()
check_plain ()
Links
Access control
Database
Data passing
40. Our arsenal of functions
We need guns. 10 or so guns.
String filtering t()
check_plain ()
check_markup ()
Links
Access control
Database
Data passing
41. Our arsenal of functions
We need guns. 10 or so guns.
String filtering t()
check_plain ()
check_markup ()
filter_xss_admin ()
Links
Access control
Database
Data passing
42. Our arsenal of functions
We need guns. 10 or so guns.
String filtering t()
check_plain ()
check_markup ()
filter_xss_admin ()
Links l ()
Access control
Database
Data passing
43. Our arsenal of functions
We need guns. 10 or so guns.
String filtering t()
check_plain ()
check_markup ()
filter_xss_admin ()
Links l ()
url ()
Access control
Database
Data passing
44. Our arsenal of functions
We need guns. 10 or so guns.
String filtering t()
check_plain ()
check_markup ()
filter_xss_admin ()
Links l ()
url ()
‘
Access control
Database
Data passing
45. Our arsenal of functions
We need guns. 10 or so guns.
String filtering t()
check_plain ()
check_markup ()
filter_xss_admin ()
Links l ()
url ()
‘
Access control user_access ()
Database
Data passing
46. Our arsenal of functions
We need guns. 10 or so guns.
String filtering t()
check_plain ()
check_markup ()
filter_xss_admin ()
Links l ()
url ()
‘
Access control user_access ()
Database db_query ()
Data passing
47. Our arsenal of functions
We need guns. 10 or so guns.
String filtering t()
check_plain ()
check_markup ()
filter_xss_admin ()
Links l ()
url ()
‘
Access control user_access ()
Database db_query ()
db_query_range ()
Data passing
48. Our arsenal of functions
We need guns. 10 or so guns.
String filtering t()
check_plain ()
check_markup ()
filter_xss_admin ()
Links l ()
url ()
‘
Access control user_access ()
Database db_query ()
db_query_range ()
Data passing drupal_get_token ()
51. Protects against:
XSS
t()
Purpose: Filters out the malicious, leaves the
delicious.
Bonus: Makes your text translatable into other
languages (Internationalization module) or
overridable though config (String Overrides module)
52. Protects against:
XSS
t()
Purpose: Filters out the malicious, leaves the
delicious.
Bonus: Makes your text translatable into other
languages (Internationalization module) or
overridable though config (String Overrides module)
Example:
53. Protects against:
XSS Mo’ about t()
3 variable replacement options
(for stuff that shouldn’t be translated, like paths)
54. Protects against:
XSS Mo’ about t()
3 variable replacement options
(for stuff that shouldn’t be translated, like paths)
! - No filtering
55. Protects against:
XSS Mo’ about t()
3 variable replacement options
(for stuff that shouldn’t be translated, like paths)
! - No filtering
@ - Plain text
56. Protects against:
XSS Mo’ about t()
3 variable replacement options
(for stuff that shouldn’t be translated, like paths)
! - No filtering
@ - Plain text
% - Highlighted
57. Protects against:
XSS Mo’ about t()
3 variable replacement options
(for stuff that shouldn’t be translated, like paths)
! - No filtering
@ - Plain text
% - Highlighted
t(“I !pity the foo’”, “<strong>pity</strong>”)
I pity the foo’
58. Protects against:
XSS Mo’ about t()
3 variable replacement options
(for stuff that shouldn’t be translated, like paths)
! - No filtering
@ - Plain text
% - Highlighted
t(“I !pity the foo’”, “<strong>pity</strong>”)
I pity the foo’
t(“I @pity the foo’”, “<strong>pity</strong>”)
I <strong>pity</strong> the foo’
59. Protects against:
XSS Mo’ about t()
3 variable replacement options
(for stuff that shouldn’t be translated, like paths)
! - No filtering
@ - Plain text
% - Highlighted
t(“I !pity the foo’”, “<strong>pity</strong>”)
I pity the foo’
t(“I @pity the foo’”, “<strong>pity</strong>”)
I <strong>pity</strong> the foo’
t(“I %pity the foo’”, “<strong>pity</strong>”)
I <strong>pity</strong> the foo’
62. Protects against:
XSS Mo’ about t()
format_plural() is nice
Drupal.t() for javascript
63. Protects against:
XSS Mo’ about t()
format_plural() is nice
Drupal.t() for javascript
Caveats
64. Protects against:
XSS Mo’ about t()
format_plural() is nice
Drupal.t() for javascript
Caveats
1. Don’t use l()
65. Protects against:
XSS Mo’ about t()
format_plural() is nice
Drupal.t() for javascript
Caveats
1. Don’t use l()
2. Wrap t() around entire sentences
66. Protects against:
XSS Mo’ about t()
format_plural() is nice
Drupal.t() for javascript
Caveats
1. Don’t use l()
2. Wrap t() around entire sentences
3. Avoid escaping quotation marks
67. Protects against:
XSS Mo’ about t()
format_plural() is nice
Drupal.t() for javascript
Caveats
1. Don’t use l()
2. Wrap t() around entire sentences
3. Avoid escaping quotation marks
4. Don’t pass a variable through t()
72. Protects against:
XSS
check_markup()
Purpose: Applies content filters to content. Super cool.
73. Protects against:
XSS
check_markup()
Purpose: Applies content filters to content. Super cool.
Bonus: Filters do more than filter, they also embed stuff
like blocks, views, images and links without giving the user
unnecessary access.
74. Protects against:
XSS
check_markup()
Purpose: Applies content filters to content. Super cool.
Bonus: Filters do more than filter, they also embed stuff
like blocks, views, images and links without giving the user
unnecessary access.
79. Protects against:
XSS
l() and URL()
Purpose: Laconic linking tool for leading without losing
location.
80. Protects against:
XSS
l() and URL()
Purpose: Laconic linking tool for leading without losing
location.
Bonus: Filters out HTML by default, but also insures that
the URL is always pointing to the right place, even if Drupal
moves.
81. Protects against:
XSS
l() and URL()
Purpose: Laconic linking tool for leading without losing
location.
Bonus: Filters out HTML by default, but also insures that
the URL is always pointing to the right place, even if Drupal
moves.
82. Protects against:
XSS
l() and URL()
Purpose: Laconic linking tool for leading without losing
location.
Bonus: Filters out HTML by default, but also insures that
the URL is always pointing to the right place, even if Drupal
moves.
83. Protects against:
XSS
l() and URL()
Purpose: Laconic linking tool for leading without losing
location.
Bonus: Filters out HTML by default, but also insures that
the URL is always pointing to the right place, even if Drupal
moves.
Other luscious options: attributes, query, fragment, html, alias
85. Protects against:
XSS, DOS
user_access()
Purpose: Keep users from accessing stuff they’re not supposed to.
86. Protects against:
XSS, DOS
user_access()
Purpose: Keep users from accessing stuff they’re not supposed to.
Step 1: Implement hook_perm()
87. Protects against:
XSS, DOS
user_access()
Purpose: Keep users from accessing stuff they’re not supposed to.
Step 1: Implement hook_perm()
Step 2: Use user_access()
to check permissions
88. Protects against:
XSS, DOS
user_access()
Purpose: Keep users from accessing stuff they’re not supposed to.
Step 1: Implement hook_perm()
Step 2: Use user_access()
to check permissions
89. Protects against:
XSS, DOS
user_access()
Purpose: Keep users from accessing stuff they’re not supposed to.
Step 1: Implement hook_perm()
Step 2: Use user_access()
to check permissions
92. Protects against:
XSS, DOS
user_access() continued
1. Granularity is a virtue
2. Access control doesn’t work unless you use it
93. Protects against:
XSS, DOS
user_access() continued
1. Granularity is a virtue
2. Access control doesn’t work unless you use it
3. Be cautious about using other module’s permissions
94. Protects against:
XSS, DOS
user_access() continued
1. Granularity is a virtue
2. Access control doesn’t work unless you use it
3. Be cautious about using other module’s permissions
4. It’s not just about your users, it’s also about the
hackers posing as your users.
96. Protects against:
SQL injection
db_query() is
WTF r
a
t hat be
?
doing
Purpose: Filters out inaccurate and potentially malicious material
out of a database query.
97. Protects against:
SQL injection
db_query() is
WTF r
a
t hat be
?
doing
Purpose: Filters out inaccurate and potentially malicious material
out of a database query.
Bonus: Instantly makes your queries cross-database compatible.
98. Protects against:
SQL injection
db_query() is
WTF r
a
t hat be
?
doing
Purpose: Filters out inaccurate and potentially malicious material
out of a database query.
Bonus: Instantly makes your queries cross-database compatible.
101. Protects against:
SQL injection db_query() continued
1. Wrap brackets around table names
2. Filter any user-supplied data by using placeholders
102. Protects against:
SQL injection db_query() continued
1. Wrap brackets around table names
2. Filter any user-supplied data by using placeholders
%s - String
103. Protects against:
SQL injection db_query() continued
1. Wrap brackets around table names
2. Filter any user-supplied data by using placeholders
%s - String
%d - Integer / Number
104. Protects against:
SQL injection db_query() continued
1. Wrap brackets around table names
2. Filter any user-supplied data by using placeholders
%s - String
%d - Integer / Number
%% - For LIKE queries
105. Protects against:
SQL injection db_query() continued
1. Wrap brackets around table names
2. Filter any user-supplied data by using placeholders
%s - String
%d - Integer / Number
%% - For LIKE queries
3. Note that there is usually a Drupal equivilant to
MySQL functions, such as:
106. Protects against:
SQL injection db_query() continued
1. Wrap brackets around table names
2. Filter any user-supplied data by using placeholders
%s - String
%d - Integer / Number
%% - For LIKE queries
3. Note that there is usually a Drupal equivilant to
MySQL functions, such as:
mysql_fetch_array = db_fetch_array
mysql_result - db_result
mysql_fetch_object - db_fetch_object
(see a pattern?)
107. Protects against:
DOS, SQL injection
db_query_range() ,o field o
f
Gre etings ou* know
o *y ng?
gr ass, d bear’s doi
at
w hat th
108. Protects against:
DOS, SQL injection
db_query_range() ,o field o
f
Gre etings ou* know
o *y ng?
gr ass, d bear’s doi
at
w hat th
Purpose: Limits the number of results returned
109. Protects against:
DOS, SQL injection
db_query_range() ,o field o
f
Gre etings ou* know
o *y ng?
gr ass, d bear’s doi
at
w hat th
Purpose: Limits the number of results returned
Bonus: Also helps with database compatability
110. Protects against:
DOS, SQL injection
db_query_range() ,o field o
f
Gre etings ou* know
o *y ng?
gr ass, d bear’s doi
at
w hat th
Purpose: Limits the number of results returned
Bonus: Also helps with database compatability
112. Protects against:
CSRF
drupal_get_token()
Purpose: Verify the source of a request (i.e. GET or POST)
113. Protects against:
CSRF
drupal_get_token()
Purpose: Verify the source of a request (i.e. GET or POST)
Step 1: Set the token
drupal_prepare_form() in /includes/form.inc
114. Protects against:
CSRF
drupal_get_token()
Purpose: Verify the source of a request (i.e. GET or POST)
Step 1: Set the token
drupal_prepare_form() in /includes/form.inc
Step 2: Check the token
drupal_validate_form() in /includes/form.inc
118. Protects against:
CSRF
drupal_get_token() cont’d
Let’s look at the code:
/includes/common.inc
119. Protects against:
CSRF
drupal_get_token() cont’d
Let’s look at the code:
/includes/common.inc
Works for AJAX, too!
120. Protects against:
CSRF
drupal_get_token() cont’d
Let’s look at the code:
/includes/common.inc
Works for AJAX, too!
1. Set a hidden input with a token
121. Protects against:
CSRF
drupal_get_token() cont’d
Let’s look at the code:
/includes/common.inc
Works for AJAX, too!
1. Set a hidden input with a token
2. Pass the value in the AJAX call
122. Protects against:
CSRF
drupal_get_token() cont’d
Let’s look at the code:
/includes/common.inc
Works for AJAX, too!
1. Set a hidden input with a token
2. Pass the value in the AJAX call
3. Check it server-side before processing
124. More security tips for your
consideration
1. Use the Form(s) API, it does a lot of heavy lifting
125. More security tips for your
consideration
1. Use the Form(s) API, it does a lot of heavy lifting
2. Set permissions properly
126. More security tips for your
consideration
1. Use the Form(s) API, it does a lot of heavy lifting
2. Set permissions properly
3. Don’t use User One for regular admin tasks
127. More security tips for your
consideration
1. Use the Form(s) API, it does a lot of heavy lifting
2. Set permissions properly
3. Don’t use User One for regular admin tasks
4. SSL certificates aren’t a cure-all
129. My info
Chris Shattuck
e s s
http://chrisshattuck.com
Twitter: stompeers e l
a m
S h
I sell Drupal development tutorial videos at
http://buildamodule.com
I also do Drupal consulting
User Experience (UX) . Interface Design (UI) . jQuery integration
Drupal Training . Guerrilla Usability . Module Development