搜索此博客

2017年7月3日星期一

Escalating XSS in PhantomJS Image Rendering to SSRF/Local-File Read(转)

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
Escalating XSS in PhantomJS Image Rendering to SSRF/Local-File Read(转)  阅读原文»

转http://buer.haus/2017/06/29/escalating-xss-in-phantomjs-image-rendering-to-ssrflocal-file-read/

Escalating XSS in PhantomJS Image Rendering to SSRF/Local-File Read

I recently came across across a request on a bounty program that took user input and generated an image for you to download. After a little bit of a journey, I was able to escalate from XSS inside of an image all the way to arbitrary local-file read on the server. It's a private program, so I'm going to do my best to redact as much information as possible.

The original request looked something like this:

https://website/download?background=file.jpg&author=Brett&header=Test&text=&width=500&height=500

And it would output a file like this:

I initially went after the background request var because it specified a file name and I think that one looks the most interesting. After messing around with the parameters a bit, I noticed that the header request variable was vulnerable to some form of HTML injection. I have read some write-ups of XSS inside of PDFs leading to critical vulnerabilities, so I decided to chase this a bit.

https://website/download?background=file.jpg&author=Brett&header="><u>test&text=&width=500&height=500

Output:

Starting to put random HTML elements in, I noticed that almost all of them were rendering: iframe, img, script, etc. I decided to target my own server to see if I could get a bit more information on what is processing the HTML.

https://website/download?background=file.jpg&author=Brett&header=<iframe src=https://xss.buer.haus/ssrftest></iframe>&text=&width=500&height=500

Response:

[25/Jun/2017:20:31:49 -0400] "GET /ssrftest HTTP/1.1" 404 548 "-" "Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1"

The User-Agent in the request means they are using the headless browser client PhantomJS to load an HTML page and generate image data. I already had some experience with Phantom because it's often used in CTFs and I use it in my online scanner for capturing screenshots of websites. This was a good thing to pick-up on early because it explained some of the issues I encountered while trying to exploit this vulnerability.

The first problem I ran into was that JavaScript was not consistently executing using basic payloads. <script></script> would not execute properly. <img src=x onerror=> would not trigger consistently. I think I got one successful window.location redirect out of 100 attempts. In some cases, the payloads would not execute at all. On top of that, I was running into some server exceptions when trying to redirect to another page:

https://website/download?background=file.jpg&author=Brett&header=<img src="x" onerror="window.location='https://xss.buer.haus/'" />&text=&width=500&height=500

Response:

{"message": "Internal server error"}.

I tried probably 50 different types of payloads there until I realized that the problem is actually with what appeared to be some sort of race condition with PhantomJS. I ran into a similar issue writing a plugin for Phantom with my scanner where it would not wait for JavaScript to completely load when trying to capture some screenshots.

I needed to find a way to make Phantom wait for my JavaScript to load before trying to finish rendering the screenshot. After trying a few different ideas, I used document.write to completely overwrite the page contents and that seemed to fix it. I don't know why, but it worked.

https://website/download?background=file.jpg&author=Brett&header=<img src="x" onerror="document.write('test')" />&text=&width=500&height=500

Response:

At this point I had consistent JavaScript execution on every page load. The next step I needed to take was to gather more information about PhantomJS and the context of what and where we are executing.

https://website/download?background=file.jpg&author=Brett&header=<img src="x" onerror="document.write(window.location)" />&text=&width=500&height=500

Response:

Interesting enough, we are executing from the origin of file:// and it was an HTML file in /var/task/. Now I wanted to see if I could <iframe> the file just to validate that I'm in the same origin as /var/task/.

https://website/download?background=file.jpg&author=Brett&header=<img src="xasdasdasd" onerror="document.write('<iframe src=file:///var/task/[redacted].html></iframe>')"/>&text=&width=500&height=500

Now I know I can at least load files in /var/task/, so the next thing I want to do is see if I can load other files such as in /e

通过服务器日志溯源web应用攻击路径  阅读原文»

无论是我们使用的个人计算机还是服务器都为我们提供了强大的日志记录功能。例如系统日志,可以为我们记录系统硬件、软件和系统问题的信息,用户可以通过它来检查错误发生的原因,或者寻找受到攻击时攻击者留下的痕迹。
而服务器日志,则主要包括访问日志和错误日志。访问日志记录了该服务器所有的请求的过程,主要记录的是客户的各项信息,如访问时间、内容、地址等。错误日志则记录服务器出错的细节等数据。同时,这些日志记录信息也为安全事件的取证分析提供了强有力的证据和溯源的渠道。
我们以Web服务器为例。最常见的Apache HTTP Server一般会为我们提供两个主要的日志文件 – access.log和error.log。access.log记录所有文件请求。如果访问者请求www.example.com/main.php,则日志文件中将添加以下条目。
88.54.124.17 - - [16/Apr/2016:07:44:08 +0100] "GET /main.php HTTP/1.1" 200 203 "-" "Mozilla/5.0 (Windows NT 6.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"
从以上日志可以看出,一个访问者在2016年4月16日的07:44分成功请求了main.php文件。
试想该访问者请求的不是一个普通文件,而是一个转储数据库的文件例如dump_database.php。如果没有日志文件,那么我们可能永远不会发现有人或许已经将我们的重要数据窃取了。
下面让我通过一个简单的示例来为大家演示下,如何通过一个日志文件溯源web应用的攻击者。
调查
我们假设我们运行的一个最新的WordPress站点受到了黑客的攻击,并且该站点运行在没有任何补丁问题的Ubuntu服务器上。

在接到任务后,为了防止系统及其当前的日志状态发生改变,以及阻止攻击者可能的远程访问和与其他机器的网络交互,我们的分析取证小组首先对服务器进行了“离线”操作。
注:按照正常流程我们需要创建一个当前系统的副本,但由于我们是以演示为目的故跳过该步骤的操作,我们将直接以原始数据为演示对象。
寻找蛛丝马迹
在调查取证之前,我们首先要知道哪些证据是我们所需要的。通常攻击者都会直接访问一些“隐藏”或特殊的文件,或需要身份验证的管理区域,远程执行代码,SQL注入,文件包含,跨站点脚本(XSS)等异常行为,这就表明有攻击者可能利用了漏扫工具或手工对我们的站点进行了探测。
这里我们假设我们的access.log日志文件保存完好并且可用。
root@secureserver:/var/log/apache2# less access.log
access.log往往是一个相当大的文件,通常包含了数千条的请求记录。
84.55.41.57 - - [16/Apr/2016:20:21:56 +0100] "GET /john/index.php HTTP/1.1" 200 3804 "-" "Mozilla/5.0 (Windows NT 6.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"
84.55.41.57 - - [16/Apr/2016:20:21:56 +0100] "GET /john/assets/js/skel.min.js HTTP/1.1" 200 3532 "http://www.example.com/john/index.php" "Mozilla/5.0 (Windows NT 6.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"
84.55.41.57 - - [16/Apr/2016:20:21:56 +0100] "GET /john/images/pic01.jpg HTTP/1.1" 200 9501 "http://www.example.com/john/index.php" "Mozilla/5.0 (Windows NT 6.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"
84.55.41.57 - - [16/Apr/2016:20:21:56 +0100] "GET /john/images/pic03.jpg HTTP/1.1" 200 5593 "http://www.example.com/john/index.php" "Mozilla/5.0 (Windows NT 6.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"
面对数量如此庞大的记录信息,如果我们每一行都去仔细查看显然不是个明智的选择。因此,我们可以将一些没有什么太大价值的数据给去除掉,例如图像、CSSJavaScript这类文件。
由于我们的演示站点为WordPress,所以我们可以通过筛选的方式找出所有具有WordPress特征的access.log记录。
root@secureserver:~#cat /var/log/apache2/access.log | grep -E "wp-admin|wp-login|POST /"
以上命令将过滤access.log,并只显示包含wp-admin的字符串的记录,wp-admin是WordPress的默认后台管理文件夹,wp-login则是WordPress(wp-login.php)登录文件的一部分。最后的POST将筛选出所有通过POST方法发送的HTTP请求,这些请求很可能是在提交登录表单。
筛选完成后以下的日志记录引起了我们的注意:
84.55.41.57 - - [17/Apr/2016:06:52:07 +0100] "GET /wordpress/wp-admin/ HTTP/1.1" 200 12349 "http://www.example.com/wordpress/wp-login.php" "Mozilla/5.0 (Windows NT 6.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"
 我们看到IP为84.55.41.57的访问者,成功访问了WordPress的管理后台。
针对该IP我们继续筛选有关它的信息:
root@secureserver:~#cat /var/log/apache2/access.log | grep 84.55.41.57
我们得到了以下过滤内容:
84.55.41.57 - - [17/Apr/2016:06:57:24 +0100] "GET /wordpress/wp-login.php HTTP/1.1" 200 1568 "-"
84.55.41.57 - - [17/Apr/2016:06:57:31 +0100] "POST /wordpress/wp-login.php HTTP/1.1" 302 1150 "http://www.example.com/wordpress/wp-login.php"
84.55.41.57 - - [17/Apr/2016:06:57:31 +0100] "GET /wordpress/wp-admin/ HTTP/1.1" 200 12905 "http://www.example.com/wordpress/wp-login.php"

84.55.41.57 - - [17/Apr/2016:07:00:32 +0100] "POST /wordpress/wp-admin/admin-ajax.php HTTP/1.1" 200 454 "http://www.example.com/wordpress/wp-admin/"
84.55.41.57 - - [17/Apr/2016:07:00:58 +0100] "GET /wordpress/wp-admin/theme-editor.php HTTP/1.1" 200 20795 "http://www.example.com/wordpress/wp-admin/"
84.55.41.57 - - [17/Apr/2016:07:03:17 +0100] "GET /wordpress/wp-admin/theme-editor.php?file=404.php&theme=twentysixteen HTTP/1.1" 200 8092 "http://www.example.com/wordpress/wp-admin/theme-editor.php"
84.55.41.57 - - [17/Apr/2016:07:11:48 +0100] "GET /wordpress/wp-admin/plugin-install.php HTTP/1.1" 200 12459 "http://www.example.com/wordpress/wp-admin/plugin-install.php?tab=upload"
84.55.41.57 - - [17/Apr/2016:07:16:06 +0100] "GET /wordpress/wp-admin/update.php?action=install-plugin&plugin=file-manager&_wpnonce=3c6c8a7fca HTTP/1.1" 200 5698 "http://www.example.com/wordpress/wp-admin/plugin-install.php?tab=search&s=file+permission"
84.55.41.57 - - [17/Apr/2016:07:18:19 +0100] "GET /wordpress/wp-admin/plugins.php?action=activate&plugin=file-manager%2Ffile-manager.php&_wpnonce=bf932ee530 HTTP/1.1" 302 451 "http://www.example.com/wordpress/wp-admin/update.php?action=install-plugin&plugin=file-manager&_wpnonce=3c6c8a7fca"
84.55.41.57 - - [17/Apr/2016:07:21:46 +0100] "GET /wordpress/wp-admin/admin-ajax.php?action=connector&cmd=upload&target=l1_d3AtY29udGVudA&name%5B%5D=r57.php&FILES=&_=1460873968131 HTTP/1.1" 200 731 "http://www.example.com/wordpress/wp-admin/admin.php?page=file-manager_settings"
84.55.41.57 - - [17/Apr/2016:07:22:53 +0100] "GET /wordpress/wp-content/r57.php HTTP/1.1" 200 9036 "-"
84.55.41.57 - - [17/Apr/2016:07:32:24 +0100] "POST /wordpress/wp-content/r57.php?14 HTTP/1.1" 200 8030 "http://www.example.com/wordpress/wp-content/r57.php?14"
84.55.41.57 - - [17/Apr/2016:07:29:21 +0100] "GET /wordpress/wp-content/r57.php?29 HTTP/1.1" 200 8391 "http://www.example.com/wordpress/wp-content/r57.php?28"
84.55.41.57 - - [17/Apr/2016:07:57:31 +0100] "POST /wordpress/wp-admin/admin-ajax.php HTTP/1.1" 200 949 "http://www.myw ebsite.com/wordpre ss/wp-admin/admin.php?page=file-manager_settings"
让我们来分析一下这些记录。
攻击者访问登录界面。
84.55.41.57 - GET /wordpress/wp-login.php 200
攻击者提交了登录表单(使用POST方法的HTTP请求),并被重定向(302 HTTP状态代码)。
84.55.41.57 - POST /wordpress/wp-login.php 302
攻击者被成功重定向到了wp-admin(WordPress仪表盘),这意味着攻击者成功进行了身份验证。
84.55.41.57 - GET /wordpress/wp-admin/ 200
攻击者导航到了主题编辑器。
84.55.41.57 - GET /wordpress/wp-admin/theme-editor.php 200
攻击者试图通过编辑404文件将恶意代码插入到该页面,但由于缺乏写入权限最终没能成功。
84.55.41.57 - GET /wordpress/wp-admin/theme-editor.php?file=404.php&theme= twentysixteen 200
攻击者访问了插件安装程序。
84.55.41.57 - GET /wordpress/wp-admin/plugin-install.php 200
攻击者安装并激活了文件管理器插件。
84.55.41.57 - GET /wordpress/wp-admin/update.php?action=install-plugin&plugin= file-manager &_wpnonce=3c6c8a7fca 200
84.55.41.57 - GET /wordpress/wp-admin/plugins.php?action=activate&plugin=file-manager%2Ffile-manager.php&_wpnonce=bf932ee530 200
攻击者使用文件管理器插件上传了一个名为r57.php的文件,这很可能是一个PHP webshell脚本。
84.55.41.57 - GET /wordpress/wp-admin/admin-ajax.php?action=connector& cmd= upload&target=l1_d3AtY29udGVudA&name%5B%5D=r57.php&FILES=&_=1460873968131 200
日志表明攻击者运行r57 shell脚本。查询字符串?1(攻击者运行了phpinfo();)和?28(攻击者获取到了服务列表)可以看出攻击者并没有发现什么感兴趣的东西。
84.55.41.57 - GET /wordpress/wp-content/r57.php 200
84.55.41.57 - POST /wordpress/wp-content/r57.php?1 200
84.55.41.57 - GET /wordpress/wp-content/r57.php?28 200
攻击者的最后一个动作是通过文件管理器插件编辑主题的索引文件,并用“HACKED!”替换了其中的内容。
84.55.41.57 - POST /wordpress/wp-admin/admin-ajax.php 200 - http://www.
example.com/wordpress/wp-admin/admin.php?page=file-manager_settings
基于上述信息,我们可以大致判断攻击者对我们的站点做了什么操作。但这里有个非常重要的点绝对不能忽略,那就是假设我们的管理员密码并没有泄露,攻击者也没有尝试过暴破,那么攻击者又是如何获取到我们的登录凭证的呢?
当前的access.log文件并没有为我们提供任何线索。不过,我们分析的对象不仅限于这一个access.log文件。Apache HTTP Server为我们循环归档了旧的日志文件。打开/var/log/apache2/?p>阅读更多内容

没有评论: