Защита Citrix Web Interface от brute-force атак с помощью CAPTCHA

Источник: habrahabr
EminH

Программный продукт Web Interface от Citrix используется как для XenApp так и для XenDesktop и представляет собой набор web скриптов, а также, консоль для управления.
Web Interface обеспечивает безопасный доступ к ресурсам XenApp и XenDesktop из любой точки при помощи любого устройства, оснащенного браузером.

Web Interface принимает имя пользователя и пароль на форме сайта и напрямую передает системе аутентификации, в большинстве случаев это Microsoft Active Directory. При настройках по умолчанию, после нескольких попыток с неправильно введенным паролем, учетная запись пользователя блокируется на определенный промежуток времени (обычно от 10 до 30 минут), что довольно надежно защищает от атак типа "brute-force". Проблема в другом - получается, что зная адрес Web Interface и имя пользователя, можно обычными HTTP запросами, повторяющимися каждые 10-15 минут, полностью блокировать учётную запись.

Решение проблемы очевидно - captcha, однако на данный момент стандартных способов для активации captcha на Web Interface Citrix не предоставляет и придется редактировать код скриптов ручками. К счастью, ничего сложного в этом нет.

1. Создаем скрипт для генерации картинки

имя файла: captcha-image.aspx 
папка: auth (по умолчанию C:/inetpub/wwwroot/Citrix/XenApp/auth )
<%@ page language="C#" %> <%@Import Namespace="System.Drawing" %> <script runat="server"> private void Page_Load() { Bitmap objBMP =new System.Drawing.Bitmap(60,20); Graphics objGraphics = System.Drawing.Graphics.FromImage(objBMP); objGraphics.Clear(Color.Green); Font objFont = new Font("Chiller", 11, FontStyle.Bold); string randomStr=""; int[] myIntArray = new int[5] ; int x; Random autoRand = new Random(); for (x=0;x<5;x++) { myIntArray[x] = System.Convert.ToInt32 (autoRand.Next(0,9)); randomStr+= (myIntArray[x].ToString ()); } //Save generated Rnd in a Session Session.Contents["CaptchaStr"]=randomStr; objGraphics.DrawString(randomStr, objFont, Brushes.White, 3, 3); Response.ContentType = "image/GIF"; objBMP.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Gif); objFont.Dispose(); objGraphics.Dispose(); objBMP.Dispose(); } </script>

Чтобы разрешить незалогиненным юзерам запускать этот скрипт, его надо внести в список разрешенных страниц "AUTH:UNPROTECTED_PAGES". 
Для этого:
- Откройте файл web.config в корне сайта
- Найдите строку appSettings -> add key="AUTH:UNPROTECTED_PAGES" и добавьте "captcha-image.aspx" в value. 
- Должно получиться что-то вроде этого-- value="/rade.aspx,/auth/style.aspx,/auth/captcha-image.aspx,/auth/javascript.aspx,/auth…

Далее, проверьте генерируется ли картинка, запустив скрипт посредством браузера. Должна получиться картинка вроде этой:
image

2. Редактируем код login-формы, добавляем картинку и поле ввода числа с картинки
Откройте файл loginMainForm.inc в папке include ( C:/inetpub/wwwroot/Citrix/XenApp/app_data/include) и внесите следующие изменения

Непосредственно перед строкой <table class="loginForm"
<script> document.cookie='captcha=0000'; </script>
Далее, сразу после } // End Domain 

%> <tr><td align=right>Captcha:</td><td> <img src=captcha-image.aspx border=0 width=60 height=20> <input size=6 type=text id=captcha onKeyUp="document.cookie='captcha='+document.getElementById('captcha').value;" > </td></tr> <%

После этих изменений, форма входа должна выглядеть приблизительно так:

3. Редактируем login.aspx - добавляем проверку введенного кода captcha в первую очередь

Редактируем файл login.aspx в папке auth (по умолчанию C:/inetpub/wwwroot/Citrix/XenApp/auth ) таким образом - найдите строку 
layout.PageView = "loginView.ascx"; 
и сразу после нее добавьте нижеследующий код:
string strData =Request.ServerVariables["HTTP_COOKIE"]; if (Session.Contents["CaptchaStr"] == null ) { Session.Contents["CaptchaStr"] = ""; } if ( Session.Contents["CaptchaStr"].ToString().Length != 0 && Request.ServerVariables["HTTP_REFERER"].Contains("login.aspx") ) { string captcha = "0000"; string[] separator = new string[] { ";" }; string[] strSplitArr = strData.Split( separator, StringSplitOptions.RemoveEmptyEntries); foreach (string arrStr in strSplitArr) { string[] arrFind = arrStr.Split(new Char[] {'='}, 3); if (arrFind[0].Contains("captcha") && arrFind[1].Length != 0 ) { captcha = arrFind[1]; } } if( captcha.ToString()== Session.Contents["CaptchaStr"].ToString() ) { Response.Write(captcha+"-"+Session.Contents["CaptchaStr"]); } else { Session.Remove("CaptchaStr"); Response.Redirect("~/html/serverErrorCaptcha.html"); Response.End(); } }
После редактирования login.aspx должен иметь вид 

login.aspx
<%@ Register TagPrefix="wi" TagName="Layout" Src="~/app_data/include/layout.ascx" %> <% // login.aspx // Copyright (c) 2002 - 2010 Citrix Systems, Inc. All Rights Reserved. // Web Interface 5.3.0.0 %> <%@ Import Namespace="com.citrix.wi.clientdetect" %> <!--#include file="~/app_data/serverscripts/include.aspxf"--> <script runat="server"> void Page_Load(object sender, System.EventArgs e) { layout.PageClientScript = "~/auth/clientscripts/loginClientScript.ascx"; layout.PageView = "loginView.ascx"; string strData =Request.ServerVariables["HTTP_COOKIE"]; if (Session.Contents["CaptchaStr"] == null ) { Session.Contents["CaptchaStr"] = ""; } if ( Session.Contents["CaptchaStr"].ToString().Length != 0 && Request.ServerVariables["HTTP_REFERER"].Contains("login.aspx") ) { string captcha = "0000"; string[] separator = new string[] { ";" }; string[] strSplitArr = strData.Split( separator, StringSplitOptions.RemoveEmptyEntries); foreach (string arrStr in strSplitArr) { string[] arrFind = arrStr.Split(new Char[] {'='}, 3); if (arrFind[0].Contains("captcha") && arrFind[1].Length != 0 ) { captcha = arrFind[1]; } } if( captcha.ToString()== Session.Contents["CaptchaStr"].ToString() ) { Response.Write(captcha+"-"+Session.Contents["CaptchaStr"]); } else { Session.Remove("CaptchaStr"); Response.Redirect("~/html/serverErrorCaptcha.html"); Response.End(); } } } </script> <% if(new com.citrix.wi.pages.auth.LoginASP(wiContext).perform()) { %> <wi:Layout id="layout" runat="server" /> <% } %>

4. Страница ошибки ввода
При неправильно введенном коде каптчи, скрипт перенавляет на страницу ~/html/serverErrorCaptcha.html. Не забудем создать соответсвующий файл в папке C:/inetpub/wwwroot/Citrix/XenApp/html/. Можете использовать пример 

~/html/serverErrorCaptcha.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <!-- serverError.html Copyright (c) 2002 - 2010 Citrix Systems, Inc. All Rights Reserved. Web Interface 5.3.0.0 --> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta http-equiv="REFRESH" content="2; URL=../auth/login.aspx"> <meta name="ROBOTS" content="NOINDEX, NOFOLLOW, NOARCHIVE"> <meta http-equiv="X-UA-Compatible" content="IE=7"> <title>Internal Error</title> <script> document.cookie='captcha=0000'; </script> <script type="text/javascript"> <!-- var names = new Array( 'timeoutFrameWI_', 'reconnectFrameWI_', 'retryPopulatorFrameWI_', 'launchFrameWI_' ); function getTopFrame(w) { for (var n in names) { if(w.name.indexOf(names[n]) == 0) { if(w.parent) { return w.parent; } } } return null; } function redirectTop() { var topFr = getTopFrame(window); if (topFr != null) { topFr.location.href = window.location.href; } } // --> </script> <link rel="stylesheet" type="text/css" href="../html/styles/basicStyle.css"> </head> <body onLoad="redirectTop()" dir="ltr"> <div id="overallWrapper"> <div id="leftShadow"> <div id="rightShadow"> <div id="pageContent"> <div id="header"> <img src="../media/CitrixLogoHeader.gif" alt="Heading image"> </div> <div class="mainPane"> <div id="commonBoxTop"><!-- --></div> <div id="commonBox"> <h3 class="error">Wrong security code</h3> <p>Enter the code shown on the image </p> </div> <div id="commonBoxFoot"><!-- --></div> </div> </div> </div> </div> </div> </body> </html>

Вот, в принципе и все. После всез модификации описанных выше, на вашем WI сайте, должна работать защита captcha. Обратите внимание, что captcha проверка выполняется в первую очередь, и без правильно введенного кода никаких обращений к системе аутентификации не выполняется, чем и достигается отсутсквия риска lockout-а


Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=33083