There may eventually be a time when you need to allow people to write some HTML on your site. Maybe you have a bulletin board or something or else possibly you are writing some kind of email app or wiki.
The main problem with this is that you potentially open your site to Cross Site Scripting (XSS) attacks (more info at http://en.wikipedia.org/wiki/Cross-site_scripting). Basically in an XSS attack, someone puts in a little JavaScript in your site via a user input and when someone else looks at the page the first person steals the other's cookies. In fact you can unwittingly open your site to XSS attacks just by forgetting to encode all your user inputted text by using the h() function.
This is essentially a backwards approach to the problem however. What you really want to do is close everything down by default and then make a mental effort to allow it to use HTML. Even then, you may run into the problem of people running script tags.
Enter XSS Terminate. This is a handy little plug in which will basically strip all HTML tags out of any field going to and from the database by default. You can additionally apply either Rails' sanitize method to strip out scripts while allowing some basic HTML tags or else use html5lib_sanitize to strip out the scripts while allowing for normal browser quirks (sanitize requires strict XHTML standards).
In any case, the real reason I am writing this is that the XSS terminate usage instructions contain a couple of errors.
Where the site says
In any case, the next problem is that the HTML elements entered by the user will probably read your default stylesheets. While you may want this, you may actually want the HTML to look kind of clean and distinct from your site (to highlight the fact that it is user generated content).
There is no easy way unfortunately to reset the css in a specific section so I had to search around for a default browser stylesheet online and then manually prefix every element with .text-entry. Because I am a nice guy, I am including it here (just do a text replace on .text-entry to use your own class name).
Enjoy!
.text-entry div,.text-entry dl,.text-entry dt,.text-entry dd,.text-entry ul,.text-entry ol,.text-entry li,.text-entry h1,.text-entry h2,.text-entry h3,.text-entry h4,.text-entry h5,.text-entry h6,.text-entry pre,.text-entry form,.text-entry fieldset,.text-entry input,.text-entry textarea,.text-entry p,.text-entry blockquote,.text-entry th,.text-entry td {
margin:0 !important ;
padding:0 !important ;
background:none !important;
background-color:none !important ;
border:none !important ;
font-family: Arial, Helvetica, sans-serif !important ;
color:#000 !important;
text-transform:none !important;
}
.text-entry table {
border-collapse:collapse;
border-spacing:0;
}
.text-entry fieldset,.text-entry img {
border:0;
}
.text-entry address,.text-entry caption,.text-entry cite,.text-entry code,.text-entry dfn,.text-entry em,.text-entry strong,.text-entry th,.text-entry var {
font-style:normal;
font-weight:normal;
}
.text-entry caption,.text-entry th {
text-align:left;
}
.text-entry h1,.text-entry h2,.text-entry h3,.text-entry h4,.text-entry h5,.text-entry h6 {
font-size:100%;
font-weight:normal;
}
.text-entry q:before,.text-entry q:after {
content:'';
}
.text-entry abbr,.text-entry acronym { border:0;
}
.text-entry address,
.text-entry blockquote,
.text-entry dd, .text-entry div,
.text-entry dl, .text-entry dt, .text-entry fieldset, .text-entry form,
.text-entry h1, .text-entry h2, .text-entry h3, .text-entry h4,
.text-entry h5, .text-entry h6,
.text-entry ol, .text-entry p, .text-entry ul, .text-entry center,
.text-entry dir, .text-entry hr, .text-entry menu, .text-entry pre { display: block }
.text-entry li { display: list-item; margin-left: 10px !important }
.text-entry head { display: none }
.text-entry table { display: table }
.text-entry tr { display: table-row }
.text-entry thead { display: table-header-group }
.text-entry tbody { display: table-row-group }
.text-entry tfoot { display: table-footer-group }
.text-entry col { display: table-column }
.text-entry colgroup { display: table-column-group }
.text-entry td, .text-entry th { display: table-cell }
.text-entry caption { display: table-caption }
.text-entry th { font-weight: bolder; text-align: center }
.text-entry caption { text-align: center }
.text-entry body { margin: 8px }
.text-entry h1 { font-size: 2em; margin: .67em 0 }
.text-entry h2 { font-size: 1.5em; margin: .75em 0 }
.text-entry h3 { font-size: 1.17em; margin: .83em 0 }
.text-entry h4, .text-entry p,
.text-entry blockquote, .text-entry ul,
.text-entry fieldset, .text-entry form,
.text-entry ol, .text-entry dl, .text-entry dir,
.text-entry menu { margin: 1.12em 0 }
.text-entry h5 { font-size: .83em; margin: 1.5em 0 }
.text-entry h6 { font-size: .75em; margin: 1.67em 0 }
.text-entry h1, .text-entry h2, .text-entry h3, .text-entry h4,
.text-entry h5, .text-entry h6, .text-entry b,
.text-entry strong { font-weight: bolder }
.text-entry blockquote { margin-left: 40px; margin-right: 40px }
.text-entry i, .text-entry cite, .text-entry em,
.text-entry var, .text-entry address { font-style: italic }
.text-entry pre, .text-entry tt, .text-entry code,
.text-entry kbd, .text-entry samp { font-family: monospace }
.text-entry pre { white-space: pre }
.text-entry button, .text-entry textarea,
.text-entry input, .text-entry select { display: inline-block }
.text-entry big { font-size: 1.17em }
.text-entry small, .text-entry sub, .text-entry sup { font-size: .83em }
.text-entry sub { vertical-align: sub }
.text-entry sup { vertical-align: super }
.text-entry table { border-spacing: 2px; }
.text-entry thead, .text-entry tbody,
.text-entry tfoot { vertical-align: middle }
.text-entry td, .text-entry th { vertical-align: inherit }
.text-entry s, .text-entry strike, .text-entry del { text-decoration: line-through }
.text-entry hr { border: 1px inset }
.text-entry ol, .text-entry ul, .text-entry dir,
.text-entry menu, .text-entry dd { margin-left: 40px }
.text-entry ol { list-style-type: decimal }
.text-entry ol ul, .text-entry ul ol,
.text-entry ul ul, .text-entry ol ol { margin-top: 0; margin-bottom: 0 }
.text-entry u, .text-entry ins { text-decoration: underline }
.text-entry br:before { content: "\A" }
.text-entry :before, .text-entry :after { white-space: pre-line }
.text-entry center { text-align: center }
.text-entry :link, .text-entry :visited { text-decoration: underline }
.text-entry :focus { outline: thin dotted invert }
.text-entry a {color:blue !important;}
.text-entry a:visited {color:purple !important;}
The main problem with this is that you potentially open your site to Cross Site Scripting (XSS) attacks (more info at http://en.wikipedia.org/wiki/Cross-site_scripting). Basically in an XSS attack, someone puts in a little JavaScript in your site via a user input and when someone else looks at the page the first person steals the other's cookies. In fact you can unwittingly open your site to XSS attacks just by forgetting to encode all your user inputted text by using the h() function.
This is essentially a backwards approach to the problem however. What you really want to do is close everything down by default and then make a mental effort to allow it to use HTML. Even then, you may run into the problem of people running script tags.
Enter XSS Terminate. This is a handy little plug in which will basically strip all HTML tags out of any field going to and from the database by default. You can additionally apply either Rails' sanitize method to strip out scripts while allowing some basic HTML tags or else use html5lib_sanitize to strip out the scripts while allowing for normal browser quirks (sanitize requires strict XHTML standards).
In any case, the real reason I am writing this is that the XSS terminate usage instructions contain a couple of errors.
Where the site says
class Review < ActiveRecord::BaseI found this didn't work for me. After some trial and error I found the following fix
xss_sanitize :sanitize => [ :body, :author_name]
end
class Review < ActiveRecord::BaseI also had problems with
xss_terminate :sanitize => [ :body, :author_name]
end
class Message < ActiveRecord::Baseinstead I did the following
xss_terminate :except => [ :body ], :sanitize => [ :title ]
end
class Message < ActiveRecord::BaseBasically though you probably don't want to use :except without using :sanitize or :html5lib_sanitize. Ever... And I mean it... Otherwise the next email you get will be from your sysadmin (if you are lucky) or your lawyer (if you are not).
xss_terminate :except => [ :body, :title ]
xss_terminate :sanitize => [ :title ]
end
In any case, the next problem is that the HTML elements entered by the user will probably read your default stylesheets. While you may want this, you may actually want the HTML to look kind of clean and distinct from your site (to highlight the fact that it is user generated content).
There is no easy way unfortunately to reset the css in a specific section so I had to search around for a default browser stylesheet online and then manually prefix every element with .text-entry. Because I am a nice guy, I am including it here (just do a text replace on .text-entry to use your own class name).
Enjoy!
.text-entry div,.text-entry dl,.text-entry dt,.text-entry dd,.text-entry ul,.text-entry ol,.text-entry li,.text-entry h1,.text-entry h2,.text-entry h3,.text-entry h4,.text-entry h5,.text-entry h6,.text-entry pre,.text-entry form,.text-entry fieldset,.text-entry input,.text-entry textarea,.text-entry p,.text-entry blockquote,.text-entry th,.text-entry td {
margin:0 !important ;
padding:0 !important ;
background:none !important;
background-color:none !important ;
border:none !important ;
font-family: Arial, Helvetica, sans-serif !important ;
color:#000 !important;
text-transform:none !important;
}
.text-entry table {
border-collapse:collapse;
border-spacing:0;
}
.text-entry fieldset,.text-entry img {
border:0;
}
.text-entry address,.text-entry caption,.text-entry cite,.text-entry code,.text-entry dfn,.text-entry em,.text-entry strong,.text-entry th,.text-entry var {
font-style:normal;
font-weight:normal;
}
.text-entry caption,.text-entry th {
text-align:left;
}
.text-entry h1,.text-entry h2,.text-entry h3,.text-entry h4,.text-entry h5,.text-entry h6 {
font-size:100%;
font-weight:normal;
}
.text-entry q:before,.text-entry q:after {
content:'';
}
.text-entry abbr,.text-entry acronym { border:0;
}
.text-entry address,
.text-entry blockquote,
.text-entry dd, .text-entry div,
.text-entry dl, .text-entry dt, .text-entry fieldset, .text-entry form,
.text-entry h1, .text-entry h2, .text-entry h3, .text-entry h4,
.text-entry h5, .text-entry h6,
.text-entry ol, .text-entry p, .text-entry ul, .text-entry center,
.text-entry dir, .text-entry hr, .text-entry menu, .text-entry pre { display: block }
.text-entry li { display: list-item; margin-left: 10px !important }
.text-entry head { display: none }
.text-entry table { display: table }
.text-entry tr { display: table-row }
.text-entry thead { display: table-header-group }
.text-entry tbody { display: table-row-group }
.text-entry tfoot { display: table-footer-group }
.text-entry col { display: table-column }
.text-entry colgroup { display: table-column-group }
.text-entry td, .text-entry th { display: table-cell }
.text-entry caption { display: table-caption }
.text-entry th { font-weight: bolder; text-align: center }
.text-entry caption { text-align: center }
.text-entry body { margin: 8px }
.text-entry h1 { font-size: 2em; margin: .67em 0 }
.text-entry h2 { font-size: 1.5em; margin: .75em 0 }
.text-entry h3 { font-size: 1.17em; margin: .83em 0 }
.text-entry h4, .text-entry p,
.text-entry blockquote, .text-entry ul,
.text-entry fieldset, .text-entry form,
.text-entry ol, .text-entry dl, .text-entry dir,
.text-entry menu { margin: 1.12em 0 }
.text-entry h5 { font-size: .83em; margin: 1.5em 0 }
.text-entry h6 { font-size: .75em; margin: 1.67em 0 }
.text-entry h1, .text-entry h2, .text-entry h3, .text-entry h4,
.text-entry h5, .text-entry h6, .text-entry b,
.text-entry strong { font-weight: bolder }
.text-entry blockquote { margin-left: 40px; margin-right: 40px }
.text-entry i, .text-entry cite, .text-entry em,
.text-entry var, .text-entry address { font-style: italic }
.text-entry pre, .text-entry tt, .text-entry code,
.text-entry kbd, .text-entry samp { font-family: monospace }
.text-entry pre { white-space: pre }
.text-entry button, .text-entry textarea,
.text-entry input, .text-entry select { display: inline-block }
.text-entry big { font-size: 1.17em }
.text-entry small, .text-entry sub, .text-entry sup { font-size: .83em }
.text-entry sub { vertical-align: sub }
.text-entry sup { vertical-align: super }
.text-entry table { border-spacing: 2px; }
.text-entry thead, .text-entry tbody,
.text-entry tfoot { vertical-align: middle }
.text-entry td, .text-entry th { vertical-align: inherit }
.text-entry s, .text-entry strike, .text-entry del { text-decoration: line-through }
.text-entry hr { border: 1px inset }
.text-entry ol, .text-entry ul, .text-entry dir,
.text-entry menu, .text-entry dd { margin-left: 40px }
.text-entry ol { list-style-type: decimal }
.text-entry ol ul, .text-entry ul ol,
.text-entry ul ul, .text-entry ol ol { margin-top: 0; margin-bottom: 0 }
.text-entry u, .text-entry ins { text-decoration: underline }
.text-entry br:before { content: "\A" }
.text-entry :before, .text-entry :after { white-space: pre-line }
.text-entry center { text-align: center }
.text-entry :link, .text-entry :visited { text-decoration: underline }
.text-entry :focus { outline: thin dotted invert }
.text-entry a {color:blue !important;}
.text-entry a:visited {color:purple !important;}
Comments
It appears that the standard Rails 2 sanitize function is a little heavy handed for use with Yahoo's Rich Text Editor. Yes it allows HTML and strips out any script tags, but it also strips out the style attribute as well.
In any case, replacing it with html5lib_sanitize seems to do with trick...
Help, please. All recommend this program to effectively advertise on the Internet, this is the best program!
[url=http://cialisgenericoad.pun.pl/ ]vendo cialis online[/url] [url=http://viagragenericons.pun.pl/ ] viagra en espana[/url] [url=http://comprarcialisal.pun.pl/ ] cialis online[/url] [url=http://viagragenericomo.pun.pl/ ]comprar viagra [/url] [url=http://compracialishl.pun.pl/ ]vendo cialis [/url] [url=http://comprarviagrawk.pun.pl/ ]comprar viagra en espana[/url]