taibeihacker
Moderator
0x01 什么是xpath
XPath即為XML路徑語言,是W3CXSLT標準的主要元素,它是一種用來確定XML(標准通用標記語言的子集)文檔中某部分位置的語言。
XPath基於XML的樹狀結構,有不同類型的節點,包括元素節點,屬性節點和文本節點,提供在數據結構樹中找尋節點的能力,可用來在XML文檔中對元素和屬性進行遍歷。
XPath 使用路徑表達式來選取XML 文檔中的節點或者節點集。這些路徑表達式和我們在常規的電腦文件系統中看到的表達式非常相似。
XPath是一種用來在內存中導航整個XML樹的語言,它的設計初衷是作為一種面向XSLT和XPointer的語言,後來獨立成了一種W3C標準.
0x02 XPath基础语法
(1)查询基本语句
//users/user[loginID/text()=’abc’and password/text()=’test123’] 。
這是一個XPath查詢語句,獲取loginID為abc的所有user數據,用戶需要提交正確的loginID和password才能返回結果。如果黑客在loginID 字段中輸入:' or 1=1 並在password 中輸入:' or 1=1 就能繞過校驗,成功獲取所有user數據
//users/user[LoginID/text()=''or
1=1 and password/text()=''or 1=1]
(2)节点类型
在XPath中,XML文檔被作為節點樹對待,XPath中有七種結點類型:元素、屬性、文本、命名空間、處理指令、註釋以及文檔節點(或成為根節點)。文檔的根節點即是文檔結點;對應屬性有屬性結點,元素有元素結點。element (元素)
attribute (屬性)
text (文本)
namespace (命名空間)
processing-instruction (處理指令)
comment (註釋)
root (根節點)
例如下面的XML文檔,
?xml version='1.0'
encoding='ISO-8859-1'?
bookstore
book
title
lang='en'Harry Potter/title
authorJ K.
Rowling/author
year2005/year
price29.99/price
/book
/bookstore
bookstore根節點
authorJ K.
Rowling/author元素節點
lang='en'屬性節點
(3)表达式
XPath通過路徑表達式(PathExpression)來選取節點,基本規則:
表達式
描述
nodename
選取此節點的所有子節點
/
從根節點選取
//
從匹配選擇的當前節點選擇文檔中的節點,而不考慮它們的位置
.
選取當前節點
.
選取當前節點的父節點
@
選取屬性或 @*:匹配任何屬性節點
*
匹配任何元素節點
來看一個XML實例,
?xml version='1.0'
encoding='ISO-8859-1'?
bookstore
book
title
lang='eng'Harry Potter/title
price29.99/price
/book
book
title
lang='eng'Learning XML/title
price39.95/price
/book
/bookstore
則:
路徑表達式結果
表達式
結果
bookstore
選取bookstore元素的所有子節點
/bookstore
選取根元素bookstore
bookstore/book
選取屬於bookstore的子元素的所有book元素
//book
選取所有book子元素,而不管它們在文檔中的位置
bookstore//book
選擇屬於bookstore元素的後代的所有book元素,而不管它們位於bookstore之下的什麼位置
//@lang
選取名為lang的所有屬性
(4)限定语
限定語是對路徑表達式的附加條件,用來查找某個特定的節點或者包含某個指定的值的節點.限定語被嵌在方括號中.路徑表達式結果:
表達式
結果
/bookstore/book[1]
選取屬於bookstore子元素的第一個book元素
/bookstore/book[last()]
選取屬於bookstore子元素的最後一個book元素
//title[@lang]
選取所有擁有名為lang的屬性的title元素
//title[@lang=’eng’]
選取所有title元素,且這些元素擁有值為eng的lang屬性
/bookstore/book[price35.00]/title
選取bookstore元素中的book元素的所有title元素,
且其中的price元素的值須大於35.00
(5)通配符
XPath通配符可用來選取未知的XML元素.通配符
描述
*
匹配任何元素節點
@*
匹配任何屬性節點
node()
匹配任何類型的節點
實例,
表達式
結果
/bookstore/*
選取bookstore元素的所有子元素
//*
選取文檔中的所有元素
//title[@*]
選取所有帶有屬性的title元素
(6) 选取多个路径
可以在路徑表達式中使用”|”運算符來選取若干路徑.實例,
表達式
結果
//book/title \
//book/price
選取book元素的所有title和price元素
bookstore/book/title \
//price
選取屬於bookstore元素的book元素的所有title元素,以及文檔中所有的price元素
(7) 运算符
路徑表達式中可以使用一些常見的數學運算符和邏輯運算符,
(8) 函数
名稱結果ancestor
選取當前節點的所有先輩(父、祖父等)
ancestor-or-self
選取當前節點的所有先輩(父、祖父等)以及當前節點本身
attribute
選取當前節點的所有屬性
child
選取當前節點的所有子元素。
descendant
選取當前節點的所有後代元素(子、孫等)。
descendant-or-self
選取當前節點的所有後代元素(子、孫等)以及當前節點本身。
following
選取文檔中當前節點的結束標籤之後的所有節點。
namespace
選取當前節點的所有命名空間節點
parent
選取當前節點的父節點。
preceding
選取文檔中當前節點的開始標籤之前的所有節點。
preceding-sibling
選取當前節點之前的所有同級節點。
self
選取當前節點。
路徑表達式可以是絕對路徑,也可以是相對路徑。例如:
绝对位置路径:/step/step/.
相对位置路径:step/step/.
其中的每一步又可以是一個表達式,包括:
軸(函數)(axis)
定義所選節點與當前節點之間的樹關係
節點測試(node-test)
識別某個軸內部的節點
零個或者更多謂語(predicate)
更深入地提煉所選的節點集
例如:例子結果
child:book
選取所有屬於當前節點的子元素的book節點
attribute:lang
選取當前節點的lang屬性
child:*
選取當前節點的所有子元素
attribute:*
選取當前節點的所有屬性
child:text()
選取當前節點的所有文本子節點
child:node()
選取當前節點的所有子節點
descendant:book
選取當前節點的所有book後代
ancestor:book
選擇當前節點的所有book先輩
ancestor-or-self:book
選取當前節點的所有book先輩以及當前節點(假如此節點是book節點的話)
child:*/child

選取當前節點的所有price孫。
0x03 XPath注入的定义
XPath注入攻擊,是指利用XPath 解析器的鬆散輸入和容錯特性,能夠在URL、表單或其它信息上附帶惡意的XPath 查詢代碼,以獲得權限信息的訪問權並更改這些信息。 XPath注入攻擊是針對Web服務應用新的攻擊方法,它允許攻擊者在事先不知道XPath查詢相關知識的情況下,通過XPath查詢得到一個XML文檔的完整內容。 Xpath注入攻擊本質上和SQL注入攻擊是類似的,都是輸入一些惡意的查詢等代碼字符串,從而對網站進行攻擊。
0x04 xpath注入描述
XPath注入攻擊是指利用XPath 解析器的鬆散輸入和容錯特性,能夠在URL、表單或其它信息上附帶惡意的XPath 查詢代碼,以獲得權限信息的訪問權並更改這些信息。 XPath注入發生在當站點使用用戶輸入的信息來構造請求以獲取XML數據。攻擊者對站點發送經過特殊構造的信息來探究站點使用的XML是如何構造的,從而進一步獲取正常途徑下無法獲取的數據。當XML數據被用作賬戶驗證時,攻擊者還可以提升他的權限。0x05 xpath注入原理
xpath注入的原理其實和sql注入很像, XPath注入攻擊主要是通過構建特殊的輸入,這些輸入往往是XPath語法中的一些組合,這些輸入將作為參數傳入Web 應用程序,通過執行XPath查詢而執行入侵者想要的操作,但是,注入的對像不是數據庫users表了,而是一個存儲數據的XML文件。攻擊者可以獲取XML 數據的組織結構,或者訪問在正常情況下不允許訪問的數據,如果XML 數據被用於用戶認證,那麼攻擊者就可以提升他的權限。因為xpath不存在訪問控制,所以我們不會遇到許多在SQL注入中經常遇到的訪問限制。 XML 中沒有訪問控製或者用戶認證,如果用戶有權限使用XPath 查詢,並且之間沒有防禦系統或者查詢語句沒有被防禦系統過濾,那麼用戶就能夠訪問整個XML 文檔。 注入出現的位置也就是cookie,headers,request parameters/input等。下面以登錄驗證中的模塊為例,說明XPath注入攻擊的實現原理。在Web 應用程序的登錄驗證程序中,一般有用戶名(username)和密碼(password) 兩個參數,程序會通過用戶所提交輸入的用戶名和密碼來執行授權操作。若驗證數據存放在XML文件中,其原理是通過查找user表中的用戶名(username)和密碼(password)的結果來進行授權訪問,
例存在user.xml文件如下:
users
user
firstnameBen/firstname
lastnameElmore/lastname
loginIDabc/loginID
passwordtest123/password
/user
user
firstnameShlomy/firstname
lastnameGantz/lastname
loginIDxyz/loginID
password123test/password
/user
則在XPath中其典型的查詢語句如下:
//users/user[loginID/text()='xyz'and password/text()='123test']
但是,可以採用如下的方法實施注入攻擊,繞過身份驗證。如果用
戶傳入一個login 和password,例如loginID='xyz' 和password='123test',則該查詢語句將返回true。但如果用戶傳入類似' or 1=1 or ''=' 的值,那麼該查詢語句也會得到true 返回值,因為XPath 查詢語句最終會變成如下代碼:
//users/user[loginID/text()=''or 1=1 or ''='' and
password/text()='' or 1=1 or ''='']
這個字符串會在邏輯上使查詢一直返回true 並將一直允許攻擊者訪問系統。攻擊者可以利用XPath 在應用程序中動態地操作XML 文檔。攻擊完成登錄可以再通過XPath盲入技術獲取最高權限帳號和其它重要文檔信息。延展開來,xpath的注入還有很多花樣,像是通過updataxml()函數實現xpth報錯注入,還有xpth的盲注
1.xpath实列原理一
主流腳本語言都支持對XPath的處理,下面我以PHP來學習XPath注入的原理.blog.xml:?xml version='1.0' encoding='UTF-8'?
root
users
user
id1/id
usernameadmin/username
password
type='md5'0192023a7bbd73250516f069df18b500/password
/user
user
id2/id
usernamejack/username
password
type='md5'1d6c1e168e362bc0092f247399003a88/password
/user
user
id3/id
usernametony/username
password
type='md5'cc20f43c8c24dbc0b2539489b113277a/password
/user
/users
secret
flagflag{My_f1rst_xp4th_iNjecti0n}/flag
/secret
/root
index.php:?php
$xml=simplexml_load_file('blog.xml');
$name=$_GET['name'];
$pwd=md5($_GET['pwd']);
$query=
'/root/users/user[username/text()=''.$name.'' and password/text()=''.$pwd.'']';
echo $query;
$result=$xml-xpath($query);
if($result) {
echo
'h2Welcome/h2';
foreach ($result as $key
=$value) {
echo
'br /ID:'.$value-id;
echo
'br /Username:'.$value-username;
}
}
代碼很簡單,實現了一個簡單的登陸驗證功能.其實和SQL注入相似,沒有對用戶輸入的數據做過濾,導致攻擊者可以直接注入”XPath表達式”,只要知道用戶名就能繞過密碼驗證,
http://127.0.0.1/xpath/index.php?name=admin' or
'1'='1pwd

如果用戶名沒法得知,可以用兩個”or”來繞過驗證邏輯
http://127.0.0.1/xpath/index.php?name=fake' or
'1'or'1pwd=fake

提取數據
2.xpath实列原理二
這裡用一道賽題來舉例:?php
$re=
array('and','or','count','select','from','union','group','by','limit','insert','where','order','alter','delete','having','max','min','avg','sum','sqrt','rand','concat','sleep');
setcookie('injection','c3FsaSBpcyBub3QgdGhlIG9ubHkgd2F5IGZvciBpbmplY3Rpb24=',time()+100000);
if(file_exists('t3stt3st.xml')) {
$xml=
simplexml_load_file('t3stt3st.xml');
$user=$_GET['user'];
$user=str_replace($re, ' ',
$user);
//$user=str_replace(''', 'apos', $user);
$query='user/username[@name=''.$user.'']';
$ans=$xml-xpath($query);
foreach($ans as $x=
$x_value)
{
echo $x.': ' . $x_value;
echo 'br
/';
}
}
通過訪問/download.php?file=backup.zip下載網頁源碼,如下:
首先看到他過濾了sql注入的一些關鍵字,setcookie中有一段base64加密的密文,解碼後得到的是:“sqli is not the only
way for injection”,根據提示sql不是唯一的注入方式,再結合下面對xml的一系列操作,可以確定這道題是用xpath注入,於是根據$query='user/username[@name=''.$user.'']';這一句可構造如下payload:
$query='user/username[@name='']|//*|ss['']';

這句payload的意思是閉合了“.$user.”前後的單引號同時執行三個操作,其中第二個操作//*即是關鍵點,列出文檔中的所有元素,最後拿到flag
3.xpath 实列原理三
這邊有個存放分數的xml文件:score.xml: