Browser Security-css、javascript

wyzsk發表於2020-08-19
作者: 瞌睡龍 · 2013/06/19 18:55

層疊樣式表(css)


呼叫方式有三種:

1 用<style>
2 透過<link rel=stylesheet>,或者使用style引數。
3 XML(包括XHTML)可以透過<?xml-stylesheet href=...?>

瀏覽器進行解析的時候會先HTML解析再做CSS解析,所以下面的程式碼會出錯:

<style>
some_descriptor {
 background: url('http://www.example.com/</style><h1 > Gotcha!'); } 
</style>

字元編碼:

為了保證在css中可以使用可能產生問題的字元,css提供了一種方式由反斜槓()加六位十六進位制數字。

字元e可以編碼成\65 \065 \000065,當後面緊跟的字元也是十六進位制字元中的一種的時候,只有最後一個才是對的。

例如teak編碼成 t\65ak 不會正常,因為會解碼時會把\65a當成一個字元。

為了避免上述情況可以編碼以後加一個空白符,例如:t\65 k。

很多CSS解析器同樣會解析引號之外的字串。

下面兩個程式碼IE下相同

<A STYLE='color: expression\028 alert \028 1 \029 \029'>
<A STYLE='color: expression(alert(1))'>

Fuzzing

CSS的解析規則與HTML和JavaScript在幾個方面不同。

JavaScript在語法錯誤的時候,整個程式碼都會被忽略,而CSS解析錯誤時,瀏覽器嘗試忽略錯誤的程式碼。

這點上跟HTML比較類似,因為HTML語法錯誤時,瀏覽器會嘗試修復並展現出來,

@符號用來在CSS樣式表中定義一個特殊屬性,定義字符集(@charset)或者media的樣式(@media)。

匯入外部樣式(@import)或外部字型(@font-face)或名稱空間(@namespace)或定義一個演示檔案(@page)。

定義字符集的時候,可以定義一個多位元組字符集(如:SHIFT-JIS,BIG5,EUC-JP,EUC-KR或GB2312)可能會使反斜線失效:

@charset "GB-2312";
*{
content:"a%90\"; color:red; z:k";
}

會解析為:

@charset "GB-2312";
*{
content:"a撞"; color:red; z:k";
}

還有一種時UTF-7字元:

@charset "UTF-7";
*{
content:"a"; color:red; z:k";
}

會解析為:

@charset "UTF-7";
*{
content:"a"; color:red; z:k";
}

[email protected]

+/v8-
*{
content:"a"; color:red; z:k";
}

在一些瀏覽器中匯入的時候可以定義字符集:

<link rel=stylesheet charset=UTF-7 src=stylesheet>

CSS的選擇器是非常有趣的部分,他可以包含字串,表示式,函式。選擇器也可以由多行組成:

CSS中的宣告時一個 屬性/值 對裡面的規則集,通常形式如下:

property: value;

property是一個關鍵字,包括字母數字破折號,和大於0x7F的字元,也有繞過的方式:

-moz-binding與\2d moz\2d binding相等。

IE中property沒有嚴格遵守這個規則,如果一個屬性包含多個字,只有第一個字將被使用,其他的都會忽略:

a b c: value;
a: value;

上面兩個規則是等效的。 並且IE中:可以替換為=

a = value;
a: value;

上面兩個也是等效的。

同樣重要的是IE允許多行的字串,URL,選擇器。

CSS最明顯的侷限性是,他本身不是一種程式語言,而是一種語言風格,他沒有任何的程式設計邏輯。

他很難不借助於JavaScript進行攻擊,下面主要討論的是完全基於CSS不依賴於其他指令碼語言的攻擊。

整體的邏輯:

element:condition{
   action;
   }

element可以為任意值,condition為CSS選擇器,如:visited,:active,:hover,:selected。 事件選擇器:

1 :hover 懸停滑鼠在一個元素。
2 :active 點選一個元素。
3 :focus 游標放在一個元素上。

CSS造成點選劫持:

<style>
iframe{
filter:alpha(opacity=0);opacity: 0;
position: absolute;top: 0px;left: 0px;
height: 300px;width: 250px;
}
img{
position: absolute;top: 0px;left: 0px;
height: 300px;width: 250px;
}
</style>
<img src="使用者看到的圖片">
<iframe src="使用者實際操作的頁面"></iframe>

點選劫持的防禦方法一是新增X-FRAME-OPTIONS:NEVER頭,另外一種方式是利用JavaScript:

<body>
<script>
if(top!=self)
document.write('<plaintext>');
</script>

兩種方式都有侷限性,之前發過點選劫持的文件了,詳見:/tips/?id=104

如下程式碼是一個有效的CSS2的程式碼,並且在Firefox,Safari,Chrome,Opera,IE7,IE8,IE9中沒有影響,但是在IE6中,可執行程式碼:

<style>
foo[bar|="} *{xss: expression(alert(1));} x{"]{
  color:red;
}
</style>

以下程式碼中的color可以編碼為c\olor,\c\o\l\or,c\6f l\06f r 。

*{
color: red;
}

瀏覽器指令碼語言


解析javascript的時候以下兩段程式碼不相同:

程式碼一 程式碼二
&#x3cscript> var my_variable1 = 1; var my_variable2 = &#x3c/script> &#x3cscript> 2; &#x3c/script> &#x3cscript> var my_variable1 = 1; var my_variable2 = 2; &#x3c/script>

這是因為<script>在解析之前並沒有連結起來,相反,程式碼一中的第一個script標籤會引起錯誤。

從而導致整個標籤被忽略,所有標籤內的程式碼都無法執行。

在JS中有兩種定義函式的方式:

var aaa=function(){...}
function aaa(){...}

var 方式定義的函式,不能先呼叫函式,後宣告,只能先宣告函式,然後呼叫。

function方式定義函式可以先呼叫,後宣告。

<script>  
//aaa();這樣呼叫就會出錯  
var aaa = function(){  
  alert("A");  
}  
aaa();//這樣就不會出錯  
//先呼叫後宣告  
bbb();  
function bbb(){  
  alert("bb");  
}  
</script>

出於歷史原因,某些HTML元素(<IMG>,<FORM>,<EMBED>,<object>,<APPLET>)的名字也直接對映到文件的名稱空間,如下面的程式碼片段所示:

<img name="hello" src="http://www.example.com/">
<script>
 alert(document.hello.src);
</script>

DOM操作:

document.getElementById("output").innerHTML = "<b>Hi mom!</b>";

向id為output的標籤裡插入<b>Hi mom!</b>。 採用.innerHTML插入資料時,必須為完整的資料塊,比如下面的程式碼:

some_element.innerHTML = "<b>Hi";
some_element.innerHTML += " mom!</b><i>";

等同於下面的程式碼:

some_element.innerHTML = "<b>Hi</b> mom!<i></i>";

DOM操作時,其本身會對一些字元做解碼處理,如下程式碼:

<textarea style="display:none" id="json">
{
  "name":"Jack&quot;",
  "country":"China"
}
</textarea>
My name is :<span id="me">loading...</span>
<script>
function $(id){
  return document.getElementById(id);
}
var data=$("json").value;
alert(data);
var profile=eval("("+data+")");//把string轉成object方便操作
$("me").innerHTML = profile.name;
</script>

可以看到alert出的data資料為

{
     "name":"Jack"",
     "country":"China"
}

下面的例子是使用getAttribute時也會解碼:

<img id="pic" src="http://www.baidu.com/img/baidu_sylogo1.gif" bigpic="http://baidu.com&quot;&gt;&lt;img src=1 onerror=alert(1)&gt;&lt;i b =" onclick="test()">
<div id="bigimage">
</div>
<script>
function $(id){
  return document.getElementById(id);
}
function test(){
  big=$("pic").getAttribute("bigpic");//big此時為:http://baidu.com"><img src=1 onerror=alert(1)><i b =
  $("bigimage").innerHTML="<img src=\"" + big + "\"/>";
}
</script>

javascript編碼

javascript支援多種字元編碼方式:

1 C語言的編碼,\b表示退格,\t表示水平製表符等等,公認的ECMAScript編碼。
2 三位數字:用反斜槓加八位8進位制來表示,如\145可表示字元e,該語法不屬於ECMAScript,但是基本所有的瀏覽器都支援。
3 兩位數字:用反斜槓加x加八位16進製表示,如\x65可表示字元e,同樣不屬於ECMAScript,但是在解析底層,C語言中有很好的支援。
4 四位數字:Unicode編碼,十六位16進製表示,如\u0065可表示字元e,屬於ECMAScript編碼。

需要注意的是組後一種編碼方式不止在字串中才可以表示,如下程式碼也可正常的執行(但是不可替代括號與引號):

<script>
\u0061lert("This displays a message!");
</script>

Fuzzing

JavaScript中,window物件是一個全域性變數,並且預設定義的變數都為全域性變數,window下的方法可以直接訪問:

<script type="text/javascript">
alert(1);
window.alert(1); 
window.alert(window.alert); 
</script>

並且可重寫:

<script type="text/javascript">
function alert() {}
alert(1)
</script>

定義陣列的兩種方式:

<script type="text/javascript">
x=[1,alert,{},[],/a/];
alert(x[4]);
</script>

預設返回最後一個:

<script type="text/javascript">
objLiteral={'objProperty':123};
alert(objLiteral[0,1,2,3,'objProperty']);
</script>
<script type="text/javascript">
objLiteral={'objProperty':123};
alert(objLiteral[(0,1,2,3,(0,'objProperty'))]);
</script>

JavaScript中定義字串除了'string',"string"方式之外,還有其他的方式:

<script type="text/javascript">
alert(/I am a string/+'');
alert(/I am a string/.source);
alert(/I am a string/['source']);
alert(['I am a string']+[])
</script>

第一個alert中是一個正規表示式加一個空字串,JavaScript會把正則強制轉為字串。 第二個alert中使用了標準的正則物件的source屬性,返回結果為正則匹配完的字串,第三個相同是屬性的另外一種訪問方式。 第三個alert中是利用了訪問陣列時如果不是指定的訪問一個元素,會自動呼叫toString()方法,轉為字串。 還有一種非標準的使用字串的方式(IE8,Safari,Opera,Firefox和Chrome已經支援),使用類似陣列的方式:

<script type="text/javascript">
alert('abcdefg'[0]);
</script>

火狐當中對函式名的規範非常的寬泛:

<script type="text/javascript">
window.function=function function(){return function function() {return function function(){alert('Works in Firefox')}()}()}()
</script>

JavaScript支援多行的字串,當一\結尾時,下一行的字串會接著上一行的結尾:

<script type="text/javascript"> 
alert("this is a \
\
\
\
\
string");
</script>

似乎所有的JavaScript引擎都支援函式之前的運算子,如:+,-,~,++,--,!,運算子也可寫在typeof和void之前。

<script type="text/javascript"> 
!~+-++alert(1)
</script>
<script type="text/javascript"> 
void~void~typeof~typeof--alert(2)
</script>
<script type="text/javascript"> 
alert(3)/abc
</script>

最新的Chrome與Safari前兩個已經不會執行了。 檢視控制檯可以看到三個js其實都是報錯了的,前兩個是由於alert函式返回的是undefined,進行++和--操作的時候是非法的。 最後一個是試圖用alert函式除以一個未宣告的變數,先執行alert函式後再除的時候報錯。

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章