نسخهٔ فعلی |
متن شما |
سطر ۱: |
سطر ۱: |
− | این نوع آسیب پذیری سمت client است و با استفاده از تزریق اسکریپت در صحفات به وجود می آید.
| |
| | | |
− | به علت اجرای اسکریپت بر روی سیستم کاربران و تفاوت بین css که برای طراحی صفحات وب است به آن xss هم گفته می شود.
| |
− |
| |
− | از عواقب این نوع حملات باعث دسترسی به مرورگر و یا حتی سیستم قربانی می شود.
| |
− |
| |
− | 3 نوع مختلف xss وجود دارد که عبارتنند از:
| |
− |
| |
− | # reflected
| |
− |
| |
− | درخواست زیر را در نظر بگیرید.
| |
− |
| |
− | <div lang="en" dir="ltr" class="mw-content-ltr">
| |
− | <pre>
| |
− | https://insecure-website.com/search?term=gift
| |
− | </pre>
| |
− | </div>
| |
− |
| |
− | درخواست پس از اجرا در صفحه وب به صورت زیر نمایش پیدا می کند.
| |
− |
| |
− | <div lang="en" dir="ltr" class="mw-content-ltr">
| |
− | <pre>
| |
− | <p>You searched for: gift</p>
| |
− | </pre>
| |
− | </div>
| |
− |
| |
− | حال اگر مهاجم مقدار پارامتر term را به صورت زیر تغییر دهیم.
| |
− |
| |
− | <div lang="en" dir="ltr" class="mw-content-ltr">
| |
− | <pre>
| |
− | https://insecure-website.com/status?message=<script>/*+Bad+stuff+here...+*/</script>
| |
− | </pre>
| |
− | </div>
| |
− |
| |
− | در صفحه وب مقدار به صورت زیر نمایش پیدا می کند.
| |
− |
| |
− | <div lang="en" dir="ltr" class="mw-content-ltr">
| |
− | <pre>
| |
− | <p>You searched for: <script>/* Bad stuff here... */</script></p>
| |
− | </pre>
| |
− | </div>
| |
− |
| |
− | # stored
| |
− |
| |
− | درخواست زیر را در نظر بگیرید.
| |
− |
| |
− | <div lang="en" dir="ltr" class="mw-content-ltr">
| |
− | <pre>
| |
− | POST /post/comment HTTP/1.1
| |
− | Host: vulnerable-website.com
| |
− | Content-Length: 100
| |
− |
| |
− | postId=3&comment=This+post+was+extremely+helpful.&name=Carlos+Montoya&email=carlos%40normal-user.net
| |
− | </pre>
| |
− | </div>
| |
− |
| |
− | پس از اجرای درخواست مقدار پارامتر comment در پایگاه داده ذخیره و بر روی صفحه به صورت زیر چاپ می شود.
| |
− |
| |
− | <div lang="en" dir="ltr" class="mw-content-ltr">
| |
− | <pre>
| |
− | <p>This post was extremely helpful.</p>
| |
− | </pre>
| |
− | </div>
| |
− |
| |
− | حال اگر مقدار پارامتر comment را به صورت زیر تغییر دهیم.
| |
− |
| |
− | <div lang="en" dir="ltr" class="mw-content-ltr">
| |
− | <pre>
| |
− | comment=%3Cscript%3E%2F*%2BBad%2Bstuff%2Bhere...%2B*%2F%3C%2Fscript%3E
| |
− | </pre>
| |
− | </div>
| |
− |
| |
− | مقدار بالا پس از ذخیره در پایگاه داده، هنگام بارگذاری صفحه به صورت زیر اجرا می شود.
| |
− |
| |
− | <div lang="en" dir="ltr" class="mw-content-ltr">
| |
− | <pre>
| |
− | <p><script>/* Bad stuff here... */</script></p>
| |
− | </pre>
| |
− | </div>
| |
− |
| |
− | # dom
| |
− |
| |
− | در جاوااسکریپت یک سری از توابع از نوع Source یا دریافت کننده و یک نوع از توابع از نوع Sink یا اجرا کننده است.
| |
− |
| |
− | برخی از توابع از نوع Source:
| |
− |
| |
− | * document.URL
| |
− | * document.documentURI
| |
− | * location.href
| |
− | * location.search
| |
− | * location.*
| |
− | * window.name
| |
− | * document.referrer
| |
− |
| |
− | برخی از توابع از نوع Sink:
| |
− |
| |
− | * document.write
| |
− | * (element).innerHTML
| |
− | * (element).src (in certain elements)
| |
− | * Eval
| |
− | * setTimout / setInterval
| |
− | * execScript
| |
− |
| |
− | با توجه به موارد بالا فرض کنید درخواستی به شکل زیر داریم.
| |
− |
| |
− | <div lang="en" dir="ltr" class="mw-content-ltr">
| |
− | <pre>
| |
− | http://www.example.com/test.html#<script>alert(1)</script>
| |
− | </pre>
| |
− | </div>
| |
− |
| |
− | محتوای صفحه اجرا کننده در خواست هم شامل کد زیر است.
| |
− |
| |
− | <div lang="en" dir="ltr" class="mw-content-ltr">
| |
− | <pre>
| |
− | <script>
| |
− | document.write("<b>Current URL</b> : " + document.baseURI);
| |
− | </script>
| |
− | </pre>
| |
− | </div>
| |
− |
| |
− | با توجه کد بالا هنگام اجرای درخواست مقدار
| |
− |
| |
− | <div lang="en" dir="ltr" class="mw-content-ltr">
| |
− | <pre>
| |
− | <script>alert(1)</script>
| |
− | </pre>
| |
− | </div>
| |
− |
| |
− | توسط document.baseURI دریافت و در document.write اجرا می شود.
| |
− |
| |
− | == روش های جلوگیری ==
| |
− |
| |
− | === روش های جلوگیری PHP ===
| |
− |
| |
− | مثال 1)
| |
− |
| |
− | <div lang="en" dir="ltr" class="mw-content-ltr">
| |
− | <pre>
| |
− | <?php
| |
− | $name=$_GET['name'];
| |
− | print $name;
| |
− | ?>
| |
− | </pre>
| |
− | </div>
| |
− |
| |
− | روش 1)
| |
− |
| |
− | <div lang="en" dir="ltr" class="mw-content-ltr">
| |
− | <pre>
| |
− | <?php
| |
− | /*
| |
− | * XSS filter
| |
− | *
| |
− | * This was built from numerous sources
| |
− | * (thanks all, sorry I didn't track to credit you)
| |
− | *
| |
− | * It was tested against *most* exploits here: http://ha.ckers.org/xss.html
| |
− | * WARNING: Some weren't tested!!!
| |
− | * Those include the Actionscript and SSI samples, or any newer than Jan 2011
| |
− | *
| |
− | *
| |
− | * TO-DO: compare to SymphonyCMS filter:
| |
− | * https://github.com/symphonycms/xssfilter/blob/master/extension.driver.php
| |
− | * (Symphony's is probably faster than my hack)
| |
− | */
| |
− |
| |
− | function xss_clean($data)
| |
− | {
| |
− | // Fix &entity\n;
| |
− | $data = str_replace(array('&','<','>'), array('&amp;','&lt;','&gt;'), $data);
| |
− | $data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data);
| |
− | $data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data);
| |
− | $data = html_entity_decode($data, ENT_COMPAT, 'UTF-8');
| |
− |
| |
− | // Remove any attribute starting with "on" or xmlns
| |
− | $data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data);
| |
− |
| |
− | // Remove javascript: and vbscript: protocols
| |
− | $data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data);
| |
− | $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data);
| |
− | $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data);
| |
− |
| |
− | // Only works in IE: <span style="width: expression(alert('Ping!'));"></span>
| |
− | $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
| |
− | $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
| |
− | $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data);
| |
− |
| |
− | // Remove namespaced elements (we do not need them)
| |
− | $data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data);
| |
− |
| |
− | do
| |
− | {
| |
− | // Remove really unwanted tags
| |
− | $old_data = $data;
| |
− | $data = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data);
| |
− | }
| |
− | while ($old_data !== $data);
| |
− |
| |
− | // we are done...
| |
− | return $data;
| |
− | }
| |
− | $name=xss_clean($_GET['name']);
| |
− | print $name;
| |
− | ?>
| |
− | </pre>
| |
− | </div>
| |
− |
| |
− | === روش های جلوگیری ASP.NET ===
| |
− |
| |
− | مثال 1)
| |
− |
| |
− | <div lang="en" dir="ltr" class="mw-content-ltr">
| |
− | <pre>
| |
− | /*
| |
− | * https://gist.github.com/DinisCruz/3fa6893bc85a9fcacdf6
| |
− | */
| |
− | public static class HtmlControls_ExtensionMethods
| |
− | {
| |
− | public static string renderControl(this Control control)
| |
− | {
| |
− | var stringBuilder = new StringBuilder();
| |
− | using (var stringWriter = new StringWriter(stringBuilder))
| |
− | using (var htmlTextWriter = new HtmlTextWriter(stringWriter))
| |
− |
| |
− | control.RenderControl(htmlTextWriter);
| |
− | return stringBuilder.str();
| |
− | }
| |
− |
| |
− | }
| |
− |
| |
− | [TestFixture]
| |
− | class XSS_Web_Controls
| |
− | {
| |
− |
| |
− | [Test]
| |
− | public void HtmlTitle()
| |
− | {
| |
− | var html_Before = "<title>\r\n\t";
| |
− | var html_After = "\r\n</title>";
| |
− |
| |
− | Func<string, string> render_Payload = (payload) =>
| |
− | {
| |
− | var htmlTitle = new HtmlTitle {Text = payload};
| |
− | return htmlTitle.renderControl();
| |
− | };
| |
− |
| |
− | Action<string> test_Payload = (payload) =>
| |
− | {
| |
− | render_Payload(payload).assert_Is(html_Before + payload + html_After);
| |
− | };
| |
− |
| |
− | test_Payload("aa '\"> bb <b1> cc ");
| |
− | test_Payload("<script>alert(42)</script>");
| |
− | test_Payload("aaa</title></head><body><img src=xxx onerror=alert(42) />");
| |
− | }
| |
− | </pre>
| |
− | </div>
| |
− |
| |
− | روش 1)
| |
− |
| |
− | <div lang="en" dir="ltr" class="mw-content-ltr">
| |
− | <pre>
| |
− | /*
| |
− | * https://gist.github.com/DinisCruz/3fa6893bc85a9fcacdf6
| |
− | */
| |
− | public static class HtmlControls_ExtensionMethods
| |
− | {
| |
− | public static string render_Control(this Control control)
| |
− | {
| |
− | var stringBuilder = new StringBuilder();
| |
− | using (var stringWriter = new StringWriter(stringBuilder))
| |
− | using (var htmlTextWriter = new HtmlTextWriter(stringWriter))
| |
− |
| |
− | control.RenderControl(htmlTextWriter);
| |
− | return stringBuilder.str();
| |
− | }
| |
− |
| |
− | public static string set_Text_and_Render_Control<T>(this T control, string text) where T : Control
| |
− | {
| |
− | control.invoke("set_Text", text);
| |
− | return control.render_Control();
| |
− | }
| |
− |
| |
− | public static T assert_Text_Render<T>(this T control, string html_Before, string html_After, string text) where T : Control
| |
− | {
| |
− | control.set_Text_and_Render_Control(text).assert_Is(html_Before + text + html_After);
| |
− | return control;
| |
− | }
| |
− | }
| |
− |
| |
− | [TestFixture]
| |
− | class XSS_Web_Controls
| |
− | {
| |
− | string payload_1 = "aa '\"> bb <b1> cc ";
| |
− | string payload_2 = "<script>alert(42)</script>";
| |
− | string payload_3 = "aaa</title></head><body><img src=xxx onerror=alert(42) />";
| |
− |
| |
− | [Test]
| |
− | public void HtmlTitle()
| |
− | {
| |
− | var html_Before = "<title>\r\n\t";
| |
− | var html_After = "\r\n</title>";
| |
− |
| |
− |
| |
− | new HtmlTitle().assert_Text_Render(html_Before, html_After, payload_1)
| |
− | .assert_Text_Render(html_Before, html_After, payload_2)
| |
− | .assert_Text_Render(html_Before, html_After, payload_3);
| |
− |
| |
− | }
| |
− |
| |
− | [Test]
| |
− | public void Literal()
| |
− | {
| |
− | var html_Before = "";
| |
− | var html_After = "";
| |
− |
| |
− | new Literal().assert_Text_Render(html_Before, html_After, payload_1)
| |
− | .assert_Text_Render(html_Before, html_After, payload_2)
| |
− | .assert_Text_Render(html_Before, html_After, payload_3);
| |
− |
| |
− | }
| |
− |
| |
− | [Test]
| |
− | public void LinkButton()
| |
− | {
| |
− | var html_Before = "<a>";
| |
− | var html_After = "</a>";
| |
− |
| |
− | new LinkButton().assert_Text_Render(html_Before, html_After, payload_1)
| |
− | .assert_Text_Render(html_Before, html_After, payload_2)
| |
− | .assert_Text_Render(html_Before, html_After, payload_3);
| |
− | }
| |
− |
| |
− | }
| |
− | </pre>
| |
− | </div>
| |
− |
| |
− |
| |
− | === روش های جلوگیری JAVA ===
| |
− |
| |
− |
| |
− | مثال 1)
| |
− |
| |
− | <div lang="en" dir="ltr" class="mw-content-ltr">
| |
− | <pre>
| |
− | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
| |
− |
| |
− | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
| |
− | <html>
| |
− | <head>
| |
− | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
| |
− | <title>XSS Vulnerable</title>
| |
− | </head>
| |
− | <body>
| |
− | <form action="xss-vuln.jsp" method="post">
| |
− | Enter your name: <input type="text" name="name"><input type="submit">
| |
− | </form>
| |
− |
| |
− | <%
| |
− | if(request.getMethod().equalsIgnoreCase("post"))
| |
− | {
| |
− | String name = request.getParameter("name");
| |
− | if(!name.isEmpty())
| |
− | {
| |
− | out.println("<br>Hi "+name+". How are you?");
| |
− | }
| |
− | }
| |
− | %>
| |
− |
| |
− | </body>
| |
− | </html>
| |
− | </pre>
| |
− | </div>
| |
− |
| |
− | روش 1)
| |
− |
| |
− | <div lang="en" dir="ltr" class="mw-content-ltr">
| |
− | <pre>
| |
− | <%@page import="org.apache.commons.lang.StringEscapeUtils"%>
| |
− | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
| |
− | Patch
| |
− | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
| |
− | <html>
| |
− | <head>
| |
− | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
| |
− | <title>XSS Patched</title>
| |
− | </head>
| |
− | <body>
| |
− | <form action="xss-patch.jsp" method="post">
| |
− | Enter your name: <input type="text" name="name"><input type="submit">
| |
− | </form>
| |
− |
| |
− | <%
| |
− | if(request.getMethod().equalsIgnoreCase("post"))
| |
− | {
| |
− | String name = StringEscapeUtils.escapeHtml(request.getParameter("name"));
| |
− | if(!name.isEmpty())
| |
− | {
| |
− | out.println("<br>Hi "+name+". How are you?");
| |
− | }
| |
− | }
| |
− | %>
| |
− | </body>
| |
− | </html>
| |
− | </pre>
| |
− | </div>
| |
− |
| |
− |
| |
− | [[category:تزریق اسکریپت(Cross Site Scripting)]]
| |
− | [[category:آسیب پذیری بر پایه DOM]]
| |