CSS Injection: What's the Worst That Can Happen

What things should be taken point if we have to use unknown user css file

A CSS injection is nearly as good as script injection. You've got expression() in IE6-7 (and later in compatibility view), you've got behavior: (HTC) in IE, you've got -moz-binding: in Firefox, you've got content: to inject text, and occasionally, mostly in older browsers that don't block it, you've got url(javascript:...). Even without these you've got a fair amount of risk just from visual UI spoofing.

As long as a user stylesheet is limited to the user that made it, a user can only compromise themselves. The problem comes when users start sharing stylesheets. You might perhaps disallow users from picking the same external stylesheet address as another user to discourage this.

Allowing user css

Yes you do need to be careful, you can take a look at these for more info:

  • Ultimate XSS CSS Injection
  • HTML/CSS Injections - Primitive Malicious Code (or, What’s the worst that could happen?)

How to protect my injected elements CSS?

If you want reset ALL CSS properties, you can do it. It is big file, probbably not best solution, but it works.

.yourContainer * {
-webkit-align-content: stretch; -moz-align-content: stretch; align-content: stretch;
-webkit-align-items: stretch; -moz-align-items: stretch; align-items: stretch;
-webkit-align-self: stretch; -moz-align-self: stretch; align-self: stretch;
-webkit-animation-delay: 0s; -moz-animation-delay: 0s; animation-delay: 0s;
-webkit-animation-direction: normal; -moz-animation-direction: normal; animation-direction: normal;
-webkit-animation-duration: 0s; -moz-animation-duration: 0s; animation-duration: 0s;
-webkit-animation-fill-mode: none; -moz-animation-fill-mode: none; animation-fill-mode: none;
-webkit-animation-iteration-count: 1; -moz-animation-iteration-count: 1; animation-iteration-count: 1;
-webkit-animation-name: none; -moz-animation-name: none; animation-name: none;
-webkit-animation-play-state: running; -moz-animation-play-state: running; animation-play-state: running;
-webkit-animation-timing-function: ease; -moz-animation-timing-function: ease; animation-timing-function: ease;
-webkit-app-region: no-drag; -moz-app-region: no-drag; app-region: no-drag;
-webkit-appearance: none; -moz-appearance: none; appearance: none;
-webkit-backface-visibility: visible; -moz-backface-visibility: visible; backface-visibility: visible;
-webkit-background-clip: border-box; -moz-background-clip: border-box; background-clip: border-box;
-webkit-background-composite: source-over; -moz-background-composite: source-over; background-composite: source-over;
-webkit-background-origin: padding-box; -moz-background-origin: padding-box; background-origin: padding-box;
-webkit-background-size: auto; -moz-background-size: auto; background-size: auto;
-webkit-border-fit: border; -moz-border-fit: border; border-fit: border;
-webkit-border-horizontal-spacing: 0px; -moz-border-horizontal-spacing: 0px; border-horizontal-spacing: 0px;
-webkit-border-image: none; -moz-border-image: none; border-image: none;
-webkit-border-vertical-spacing: 0px; -moz-border-vertical-spacing: 0px; border-vertical-spacing: 0px;
-webkit-box-align: stretch; -moz-box-align: stretch; box-align: stretch;
-webkit-box-decoration-break: slice; -moz-box-decoration-break: slice; box-decoration-break: slice;
-webkit-box-direction: normal; -moz-box-direction: normal; box-direction: normal;
-webkit-box-flex: 0; -moz-box-flex: 0; box-flex: 0;
-webkit-box-flex-group: 1; -moz-box-flex-group: 1; box-flex-group: 1;
-webkit-box-lines: single; -moz-box-lines: single; box-lines: single;
-webkit-box-ordinal-group: 1; -moz-box-ordinal-group: 1; box-ordinal-group: 1;
-webkit-box-orient: horizontal; -moz-box-orient: horizontal; box-orient: horizontal;
-webkit-box-pack: start; -moz-box-pack: start; box-pack: start;
-webkit-box-reflect: none; -moz-box-reflect: none; box-reflect: none;
-webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none;
-webkit-clip-path: none; -moz-clip-path: none; clip-path: none;
-webkit-color-correction: default; -moz-color-correction: default; color-correction: default;
-webkit-column-axis: auto; -moz-column-axis: auto; column-axis: auto;
-webkit-column-break-after: auto; -moz-column-break-after: auto; column-break-after: auto;
-webkit-column-break-before: auto; -moz-column-break-before: auto; column-break-before: auto;
-webkit-column-break-inside: auto; -moz-column-break-inside: auto; column-break-inside: auto;
-webkit-column-count: auto; -moz-column-count: auto; column-count: auto;
-webkit-column-gap: normal; -moz-column-gap: normal; column-gap: normal;
-webkit-column-progression: normal; -moz-column-progression: normal; column-progression: normal;
-webkit-column-rule-color: rgb(0, 0, 0); -moz-column-rule-color: rgb(0, 0, 0); column-rule-color: rgb(0, 0, 0);
-webkit-column-rule-style: none; -moz-column-rule-style: none; column-rule-style: none;
-webkit-column-rule-width: 0px; -moz-column-rule-width: 0px; column-rule-width: 0px;
-webkit-column-span: none; -moz-column-span: none; column-span: none;
-webkit-column-width: auto; -moz-column-width: auto; column-width: auto;
-webkit-filter: none; -moz-filter: none; filter: none;
-webkit-flex-basis: auto; -moz-flex-basis: auto; flex-basis: auto;
-webkit-flex-direction: row; -moz-flex-direction: row; flex-direction: row;
-webkit-flex-grow: 0; -moz-flex-grow: 0; flex-grow: 0;
-webkit-flex-shrink: 1; -moz-flex-shrink: 1; flex-shrink: 1;
-webkit-flex-wrap: nowrap; -moz-flex-wrap: nowrap; flex-wrap: nowrap;
-webkit-flow-from: none; -moz-flow-from: none; flow-from: none;
-webkit-flow-into: none; -moz-flow-into: none; flow-into: none;
-webkit-font-kerning: auto; -moz-font-kerning: auto; font-kerning: auto;
-webkit-font-smoothing: auto; -moz-font-smoothing: auto; font-smoothing: auto;
-webkit-font-variant-ligatures: normal; -moz-font-variant-ligatures: normal; font-variant-ligatures: normal;
-webkit-grid-after: auto; -moz-grid-after: auto; grid-after: auto;
-webkit-grid-auto-columns: auto; -moz-grid-auto-columns: auto; grid-auto-columns: auto;
-webkit-grid-auto-flow: none; -moz-grid-auto-flow: none; grid-auto-flow: none;
-webkit-grid-auto-rows: auto; -moz-grid-auto-rows: auto; grid-auto-rows: auto;
-webkit-grid-before: auto; -moz-grid-before: auto; grid-before: auto;
-webkit-grid-columns: none; -moz-grid-columns: none; grid-columns: none;
-webkit-grid-end: auto; -moz-grid-end: auto; grid-end: auto;
-webkit-grid-rows: none; -moz-grid-rows: none; grid-rows: none;
-webkit-grid-start: auto; -moz-grid-start: auto; grid-start: auto;
-webkit-highlight: none; -moz-highlight: none; highlight: none;
-webkit-hyphenate-character: auto; -moz-hyphenate-character: auto; hyphenate-character: auto;
-webkit-hyphenate-limit-after: auto; -moz-hyphenate-limit-after: auto; hyphenate-limit-after: auto;
-webkit-hyphenate-limit-before: auto; -moz-hyphenate-limit-before: auto; hyphenate-limit-before: auto;
-webkit-hyphenate-limit-lines: no-limit; -moz-hyphenate-limit-lines: no-limit; hyphenate-limit-lines: no-limit;
-webkit-hyphens: manual; -moz-hyphens: manual; hyphens: manual;
-webkit-justify-content: flex-start; -moz-justify-content: flex-start; justify-content: flex-start;
-webkit-line-align: none; -moz-line-align: none; line-align: none;
-webkit-line-box-contain: block inline replaced; -moz-line-box-contain: block inline replaced; line-box-contain: block inline replaced;
-webkit-line-break: auto; -moz-line-break: auto; line-break: auto;
-webkit-line-clamp: none; -moz-line-clamp: none; line-clamp: none;
-webkit-line-grid: none; -moz-line-grid: none; line-grid: none;
-webkit-line-snap: none; -moz-line-snap: none; line-snap: none;
-webkit-locale: auto; -moz-locale: auto; locale: auto;
-webkit-margin-after-collapse: collapse; -moz-margin-after-collapse: collapse; margin-after-collapse: collapse;
-webkit-margin-before-collapse: collapse; -moz-margin-before-collapse: collapse; margin-before-collapse: collapse;
-webkit-marquee-direction: auto; -moz-marquee-direction: auto; marquee-direction: auto;
-webkit-marquee-increment: 6px; -moz-marquee-increment: 6px; marquee-increment: 6px;
-webkit-marquee-repetition: infinite; -moz-marquee-repetition: infinite; marquee-repetition: infinite;
-webkit-marquee-style: scroll; -moz-marquee-style: scroll; marquee-style: scroll;
-webkit-mask-box-image: none; -moz-mask-box-image: none; mask-box-image: none;
-webkit-mask-box-image-outset: 0px; -moz-mask-box-image-outset: 0px; mask-box-image-outset: 0px;
-webkit-mask-box-image-repeat: stretch; -moz-mask-box-image-repeat: stretch; mask-box-image-repeat: stretch;
-webkit-mask-box-image-slice: 0 fill; -moz-mask-box-image-slice: 0 fill; mask-box-image-slice: 0 fill;
-webkit-mask-box-image-source: none; -moz-mask-box-image-source: none; mask-box-image-source: none;
-webkit-mask-box-image-width: auto; -moz-mask-box-image-width: auto; mask-box-image-width: auto;
-webkit-mask-clip: border-box; -moz-mask-clip: border-box; mask-clip: border-box;
-webkit-mask-composite: source-over; -moz-mask-composite: source-over; mask-composite: source-over;
-webkit-mask-image: none; -moz-mask-image: none; mask-image: none;
-webkit-mask-origin: border-box; -moz-mask-origin: border-box; mask-origin: border-box;
-webkit-mask-position: 0% 0%; -moz-mask-position: 0% 0%; mask-position: 0% 0%;
-webkit-mask-repeat: repeat; -moz-mask-repeat: repeat; mask-repeat: repeat;
-webkit-mask-size: auto; -moz-mask-size: auto; mask-size: auto;
-webkit-nbsp-mode: normal; -moz-nbsp-mode: normal; nbsp-mode: normal;
-webkit-order: 0; -moz-order: 0; order: 0;
-webkit-perspective: none; -moz-perspective: none; perspective: none;
-webkit-perspective-origin: 640px 345px; -moz-perspective-origin: 640px 345px; perspective-origin: 640px 345px;
-webkit-print-color-adjust: economy; -moz-print-color-adjust: economy; print-color-adjust: economy;
-webkit-region-break-after: auto; -moz-region-break-after: auto; region-break-after: auto;
-webkit-region-break-before: auto; -moz-region-break-before: auto; region-break-before: auto;
-webkit-region-break-inside: auto; -moz-region-break-inside: auto; region-break-inside: auto;
-webkit-region-overflow: auto; -moz-region-overflow: auto; region-overflow: auto;
-webkit-rtl-ordering: logical; -moz-rtl-ordering: logical; rtl-ordering: logical;
-webkit-shape-inside: outside-shape; -moz-shape-inside: outside-shape; shape-inside: outside-shape;
-webkit-shape-margin: 0px; -moz-shape-margin: 0px; shape-margin: 0px;
-webkit-shape-outside: auto; -moz-shape-outside: auto; shape-outside: auto;
-webkit-shape-padding: 0px; -moz-shape-padding: 0px; shape-padding: 0px;
-webkit-svg-shadow: none; -moz-svg-shadow: none; svg-shadow: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0.180392); -moz-tap-highlight-color: rgba(0, 0, 0, 0.180392); tap-highlight-color: rgba(0, 0, 0, 0.180392);
-webkit-text-combine: none; -moz-text-combine: none; text-combine: none;
-webkit-text-decorations-in-effect: none; -moz-text-decorations-in-effect: none; text-decorations-in-effect: none;
-webkit-text-emphasis-color: rgb(0, 0, 0); -moz-text-emphasis-color: rgb(0, 0, 0); text-emphasis-color: rgb(0, 0, 0);
-webkit-text-emphasis-position: over; -moz-text-emphasis-position: over; text-emphasis-position: over;
-webkit-text-emphasis-style: none; -moz-text-emphasis-style: none; text-emphasis-style: none;
-webkit-text-fill-color: rgb(0, 0, 0); -moz-text-fill-color: rgb(0, 0, 0); text-fill-color: rgb(0, 0, 0);
-webkit-text-orientation: vertical-right; -moz-text-orientation: vertical-right; text-orientation: vertical-right;
-webkit-text-security: none; -moz-text-security: none; text-security: none;
-webkit-text-stroke-color: rgb(0, 0, 0); -moz-text-stroke-color: rgb(0, 0, 0); text-stroke-color: rgb(0, 0, 0);
-webkit-text-stroke-width: 0px; -moz-text-stroke-width: 0px; text-stroke-width: 0px;
-webkit-transform: none; -moz-transform: none; transform: none;
-webkit-transform-origin: 640px 345px; -moz-transform-origin: 640px 345px; transform-origin: 640px 345px;
-webkit-transform-style: flat; -moz-transform-style: flat; transform-style: flat;
-webkit-transition-delay: 0s; -moz-transition-delay: 0s; transition-delay: 0s;
-webkit-transition-duration: 0s; -moz-transition-duration: 0s; transition-duration: 0s;
-webkit-transition-property: all; -moz-transition-property: all; transition-property: all;
-webkit-transition-timing-function: ease; -moz-transition-timing-function: ease; transition-timing-function: ease;
-webkit-user-drag: auto; -moz-user-drag: auto; user-drag: auto;
-webkit-user-modify: read-only; -moz-user-modify: read-only; user-modify: read-only;
-webkit-user-select: text; -moz-user-select: text; user-select: text;
-webkit-wrap-flow: auto; -moz-wrap-flow: auto; wrap-flow: auto;
-webkit-wrap-through: wrap; -moz-wrap-through: wrap; wrap-through: wrap;
-webkit-writing-mode: horizontal-tb; -moz-writing-mode: horizontal-tb; writing-mode: horizontal-tb;

alignment-baseline: auto;
background-attachment: scroll;
background-clip: border-box;
background-color: rgba(0, 0, 0, 0);
background-image: none;
background-origin: padding-box;
background-position: 0% 0%;
background-repeat: repeat;
background-size: auto;
baseline-shift: baseline;
border-bottom-color: rgb(0, 0, 0);
border-bottom-left-radius: 0px;
border-bottom-right-radius: 0px;
border-bottom-style: none;
border-bottom-width: 0px;
border-collapse: separate;
border-image-outset: 0px;
border-image-repeat: stretch;
border-image-slice: 100%;
border-image-source: none;
border-image-width: 1;
border-left-color: rgb(0, 0, 0);
border-left-style: none;
border-left-width: 0px;
border-right-color: rgb(0, 0, 0);
border-right-style: none;
border-right-width: 0px;
border-top-color: rgb(0, 0, 0);
border-top-left-radius: 0px;
border-top-right-radius: 0px;
border-top-style: none;
border-top-width: 0px;
bottom: auto;
box-shadow: none;
box-sizing: content-box;
caption-side: top;
clear: none;
clip: auto;
clip-path: none;
clip-rule: nonzero;
color: rgb(0, 0, 0);
color-interpolation: srgb;
color-interpolation-filters: linearrgb;
color-rendering: auto;
cursor: auto;
direction: ltr;
display: block;
dominant-baseline: auto;
empty-cells: show;
fill: #000000;
fill-opacity: 1;
fill-rule: nonzero;
filter: none;
float: none;
flood-color: rgb(0, 0, 0);
flood-opacity: 1;
font-family: sans-serif;
font-size: 16px;
font-style: normal;
font-variant: normal;
font-weight: normal;
glyph-orientation-horizontal: 0deg;
glyph-orientation-vertical: auto;
height: auto;
image-rendering: auto;
kerning: 0;
left: auto;
letter-spacing: normal;
lighting-color: rgb(255, 255, 255);
line-height: normal;
list-style-image: none;
list-style-position: outside;
list-style-type: disc;
margin-bottom: 0px;
margin-left: 0px;
margin-right: 0px;
margin-top: 0px;
marker-end: none;
marker-mid: none;
marker-start: none;
mask: none;
mask-type: luminance;
max-height: none;
max-width: none;
min-height: 0px;
min-width: 0px;
opacity: 1;
orphans: auto;
outline-color: rgb(0, 0, 0);
outline-offset: 0px;
outline-style: none;
outline-width: 0px;
overflow-wrap: normal;
overflow-x: visible;
overflow-y: visible;
padding-bottom: 0px;
padding-left: 0px;
padding-right: 0px;
padding-top: 0px;
page-break-after: auto;
page-break-before: auto;
page-break-inside: auto;
pointer-events: auto;
position: static;
resize: none;
right: auto;
shape-rendering: auto;
speak: normal;
stop-color: rgb(0, 0, 0);
stop-opacity: 1;
stroke: none;
stroke-dasharray: none;
stroke-dashoffset: 0;
stroke-linecap: butt;
stroke-linejoin: miter;
stroke-miterlimit: 4;
stroke-opacity: 1;
stroke-width: 1;
tab-size: 8;
table-layout: auto;
text-align: start;
text-anchor: start;
text-decoration: none;
text-indent: 0px;
text-overflow: clip;
text-rendering: auto;
text-shadow: none;
text-transform: none;
top: auto;
transition-delay: 0s;
transition-duration: 0s;
transition-property: all;
transition-timing-function: ease;
unicode-bidi: normal;
vector-effect: none;
vertical-align: baseline;
visibility: visible;
white-space: normal;
widows: auto;
width: auto;
word-break: normal;
word-spacing: 0px;
word-wrap: normal;
writing-mode: lr-tb;
z-index: auto;
zoom: 1;
}

Is there any injection vulnerability in the body of an email?

There's a possible injection in the body text if you're speaking native SMTP to the mail server.

A single . on its own terminates the current body in SMTP, so in theory you could have user supplied input like this:

some body text
.
MAIL FROM: <...>
RCPT TO: <...>
DATA
Subject: here's some spam

here's a new body

and the SMTP server might allow the second message through.

Some SMTP servers can be configured to prevent this by not allowing SMTP commands to be pipelined (i.e. requiring the client to read the response before permitting the next command).

Can XSS attacks be performed from within a linked stylesheet?

In Internet Explorer, Firefox and other browsers you can embed JavaScript in CSS by specifying a javascript: URL in a url() CSS statement.

Even if you manage to filter these out, an attacker can still completely redesign the page (including all of its textual content) with advanced CSS. Therefore, it becomes extremely easy to trick users to execute stupid actions, which is what XSS is about. For example, you could make the Delete Account button fill the entire window and change its text to "Click here to win 1000$".

You can white-list a select few properties (text-*, font-*, color, background (only colors and gradients, no URLs or other fancy stuff)), but you'll have to reject anything that does not match these restrictions.



Related Topics



Leave a reply



Submit