<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>The Taiji of Web Development</title>
	
	<link>http://webdeveloping.com.ua</link>
	<description>Шлях до сонця темним лісом веб-розробки</description>
	<pubDate>Wed, 20 Aug 2008 15:16:10 +0000</pubDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<language>en</language>
			<geo:lat>50.420933</geo:lat><geo:long>30.475817</geo:long><creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/webdeveloping" type="application/rss+xml" /><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2Fwebdeveloping" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fwebdeveloping" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.feedburner.com%2Fwebdeveloping" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/webdeveloping" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fwebdeveloping" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fwebdeveloping" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fwebdeveloping" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><item>
		<title>XSS: Що це таке і як правильно боротись? Частина І.</title>
		<link>http://feeds.feedburner.com/~r/webdeveloping/~3/336566654/preventing-cross-site-scripting-1</link>
		<comments>http://webdeveloping.com.ua/php/preventing-cross-site-scripting-1#comments</comments>
		<pubDate>Wed, 16 Jul 2008 00:07:31 +0000</pubDate>
		<dc:creator>MoD</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[безпека]]></category>

		<category><![CDATA[xss]]></category>

		<category><![CDATA[фільтрація]]></category>

		<guid isPermaLink="false">http://webdeveloping.com.ua/?p=36</guid>
		<description><![CDATA[Після більш ніж місяця тиші маю честь представити вам чергову статтю про веб-безпеку.  
Міжсайтовий скриптинг (XSS) - це найчастіше використовуваний тип атак на веб-сайти (нещодавню статистику можна побачити у першій замітці із серії про безпеку у PHP). Для такої атаки, зловмисник зберігає у базі даних сайта, спеціально створений CSS, HTML або JavaScript. Пізніше, коли [...]]]></description>
			<content:encoded><![CDATA[<p>Після більш ніж місяця тиші маю честь представити вам чергову статтю про веб-безпеку. <img src='http://webdeveloping.com.ua/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><strong>Міжсайтовий скриптинг</strong> (XSS) - це <em>найчастіше використовуваний</em> тип атак на веб-сайти (нещодавню статистику можна побачити у <a href="http://webdeveloping.com.ua/security/security-vs-php" >першій замітці</a> із серії про безпеку у PHP). Для такої атаки, зловмисник зберігає у базі даних сайта, спеціально створений CSS, HTML або JavaScript. Пізніше, коли цей контент виводиться користувачу, скажімо у якості коментаря у блозі чи повідомлення на форумі, він змінює відображення сторінки чи виконує код, мета якого - вкрасти дані користувача, передати конфіденційні дані на лівий сервер чи якимось чином змінити функціонування сайта.</p>
<p>XSS - дуже популярний вид атаки та його часто <em>дуже легко</em> застосувати, адже неймовірно велика кількість сайтів <strong>просто виводить ввід користувача</strong>, без будь-якої попередньої фільтрації. Фактично, вдала XSS атака є результатом <em>неякісного</em> коду програми.</p>
<p>Два основних види XSS атак це:</p>
<ol>
<li><strong>Пряма дія</strong> - вставлений контент відображується тому користувачу, який його власне вставив;</li>
<li><strong>Збережена дія</strong> - будь-яка кількість користувачів побачить (і, можливо, відчує) вставлений контент.</li>
</ol>
<p>Метою <em>прямої дії</em> зазвичай є вивчення методів фільтрації вводу програмою, якщо такий взагалі є для того, щоб сконструювати більш значиму атаку. <em>Збережена ж дія</em> є <strong>найбільш небезпечним</strong> типом XSS, адже у результаті можуть бути вкрадені конфіденційні дані користувачів чи порушене функціонування самого сайту.</p>
<p>У цій частині ми розглянемо деякі методи боротьби із XSS (інші будуть розглянуті у наступних частинах).<br />
<span id="more-36"></span></p>
<h2>Закодувати все!</h2>
<p>Отже, як же нам убезпечити увесь ввід від XSS? На щастя, PHP має <em>вдосталь</em> вбудованих функцій, які видаляють або кодують спеціальні HTML символи.</p>
<p>Перша з них - <a href="http://ua2.php.net/manual/ru/function.htmlspecialchars.php" onclick="javascript:pageTracker._trackPageview('/ua2.php.net');">htmlspecialchars</a>. Вона приймає строку із введеними даними та кодує символи &amp; (амперсанд), &lt; (менш ніж), &gt; (більш ніж), &#8221; (подвійні лапки) та (необов&#8217;язково) &#8216; (одинарні лапки). Всі вони перетворюються у відповідні HTML-сутності такі, як &amp;lt; (&lt;), &amp;amp; (&amp;) і т.п. Це <strong>змушує</strong> браузер трактувати ці символи виключно як <em>літеральні</em> (тобто такі, які не мають ніякого спеціального змісту).</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3610">
        <div class="code" id="p36code10">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="re1">$input</span> <span class="sy0">=</span> <span class="st0">'&lt;a href=&quot;very.bad.com&quot;&gt;&lt;img src=&quot;click.gif&quot; /&gt;&lt;/a&gt;'</span><span class="sy0">;</span>
    <span class="re1">$encoded</span> <span class="sy0">=</span> <span class="kw3">htmlspecialchars</span><span class="br0">&#40;</span><span class="re1">$input</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">//&amp;lt;a href=&quot;http://very.bad.com&quot;&amp;gt;&amp;lt;img src=&quot;click.gif&quot; /&amp;gt;&amp;lt;/a&amp;gt;</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p>Тож краще кодувати навіть найпростіший ввід.</p>
<h3>Вгамування атрибутів</h3>
<p>Якщо необхідність кодування теґів HTML очевидна, то не всі усвідомлюють цю необхідність і для <strong>атрибутів теґів</strong>.</p>
<p>Значна кількість користувацького вводу врешті-решт опиняється у атрибутах теґів, які можуть надавати елементу стиль чи навіть виконувати JavaScript. Для ясності розглянемо приклад. Користувач відправляє URL, щоб вказати на цікаву сторінку. Цей ввід використовується для того, щоб сформувати теґ &lt;a&gt;: &lt;a href=&#8221;http://webdeveloping.com.ua&#8221;&gt;Блоґ про веб-розробку українською&lt;/a&gt;. Наче нормальна ситуація, а тепер уявімо, що користувач вставить у свій ввід лапки. І як тільки закриваючі лапки будуть знайдені, браузер закриє цей атрибут і відкриє новий. І тут зловмисник може зробити <em>все</em>, що завгодно.</p>
<p>Також слід пам&#8217;ятати, що типово одинарні лапки <strong>не будуть закодовані</strong>, а тільки подвійні. Тож, якщо ви використовуєте одинарні лапки у вашому HTML, це <strong>треба</strong> вказати функції htmlspecialchars другим параметром таким чином: htmlspecialchars(&#8221;&#8216;&#8221;, ENT_QUOTES). Інакше можливий такий сценарій:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3611">
        <div class="code" id="p36code11">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="re1">$input</span> <span class="sy0">=</span> <span class="kw3">htmlspecialchars</span><span class="br0">&#40;</span><span class="st0">&quot;#' real_url='http://mailicious.com'
    fake_url='http://php.net'
    onmouseover='window.status=this.attributes.fake_url.value; return true'
    onclick='window.location=this.attributes.real_url.value'&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="kw3">echo</span> <span class="st0">&quot;&lt;a href='$input'&quot;</span><span class="sy0">&gt;</span>Корисне посилання<span class="sy0">&lt;/</span>a<span class="sy0">&gt;;</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p>Отже, що робить цей ввід? А він користується саме тим, що htmlspecialchars типово не кодує одинарні лапки, а сторінка їх використовує. Вводячи два атрибути real_url та fake_url, які є відповідно справжньою адресою та підробленою, цей код вставляє <em>підроблену</em> у строку статусу браузера при наведенні на посилання, та переходить на <em>справжню</em> при натисканні. Таким чином наш користувач <em>навіть не помітить</em>, що його хочуть відправити кудись не туди.</p>
<h3>HTML-сутності та фільтри</h3>
<p>Символ амперсанда часто використовується як початок HTML-сутності, але також може бути <em>задіяним для обходу</em> різних фільтрів. Нехай у нас існує фільтр, що знаходить всі строки &#8220;PERL&#8221; та видаляє їх. Користувач може легко закодувати всі символи цієї строки у їх відповідні HTML-сутності, таким чином обходячи фільтр стороною:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3612">
        <div class="code" id="p36code12">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="re1">$input</span> <span class="sy0">=</span> <span class="st0">'&amp;#80;&amp;#69;&amp;#82;&amp;#76;'</span><span class="sy0">;</span> <span class="co1">// PERL в закодованому вигляді </span>
    <span class="kw3">echo</span> str_ireplace<span class="br0">&#40;</span><span class="st0">'perl'</span><span class="sy0">,</span> <span class="st0">''</span><span class="sy0">,</span> <span class="re1">$input</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="co1">// Виведе незмінену строку, адже str_ireplace не знайде того, що треба</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p>Отже, перед фільтром нам треба закодувати ввід, щоб розбити сутності. Всі амперсанди будуть закодовані у &amp;amp;, тож спеціально створений ввід не пройде у запланованому вигляді:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3613">
        <div class="code" id="p36code13">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="re1">$input</span> <span class="sy0">=</span> <span class="st0">'&amp;#80;&amp;#69;&amp;#82;&amp;#76;'</span><span class="sy0">;</span> <span class="co1">// PERL в закодованому вигляді</span>
    <span class="re1">$input</span> <span class="sy0">=</span> <span class="kw3">htmlspecialchars</span><span class="br0">&#40;</span><span class="re1">$input</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// &amp;amp;#80;&amp;amp;#69;&amp;amp;#82;&amp;amp;#76;</span>
    <span class="kw3">echo</span> str_ireplace<span class="br0">&#40;</span><span class="st0">'perl'</span><span class="sy0">,</span> <span class="st0">''</span><span class="sy0">,</span> <span class="re1">$input</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">//Все так само нічого не відфільтрує</span>
    <span class="co1">// Тепер браузер виведе &amp;#80;&amp;#69;&amp;#82;&amp;#76;</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p>Це вже краще, але насправді, кодування амперсандів - це <strong>не завжди добре</strong> та в деяких випадках може навіть <strong>зашкодити</strong>. Це актуально наприклад для застарілих сайтів, які не використовують Unicode. Уявімо таку ситуацію (поширену на сайтах, що не думають про інтернаціоналізацію): є сторінка із формою у кодуванні ISO-8859-1 (типова латинська), а користувач вводить дані у кодуванні CP-1251 (типова кирилічна). Браузер автоматично переведе всі символи із вводу у HTML-сутності задля їх правильного виводу. Ми ж на стороні сервера кодуємо всі амперсанди із вводу, які в свою чергу втрачають початковий зміст, та в результаті отримуємо нечитабельний варіант.</p>
<p>Тож як нам передбачити цю ситуацію? Правильніше за все - використовувати Unicode <img src='http://webdeveloping.com.ua/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> Але, якщо це з деяких причин неможливо - найліпшим варіантом є задіяти регулярний вираз, щоб перевести у дійсні сутності лише подвійно-закодовані символи:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3614">
        <div class="code" id="p36code14">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="kw3">preg_replace</span><span class="br0">&#40;</span><span class="st0">'!&amp;amp;#([0-9]+);!'</span><span class="sy0">,</span> <span class="st0">'&amp;#<span class="es0">\1</span>;'</span><span class="sy0">,</span> <span class="kw3">htmlspecialchars</span><span class="br0">&#40;</span><span class="re1">$input</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p>Цим виразом ми захоплюємо подвійно-закодовані літери (адже шукаємо лише чисельні значення після &amp;amp;#) та замінюємо їх на дійсні сутності. Ми вирішуємо проблему із подвійно-закодованими літерами, але знову повертаємо попередню проблему. В такому випадку спеціально закодоване користувачем &#8220;PERL&#8221; буде <em>знову</em> виведене браузером, оминаючи фільтр.</p>
<p>Отже, нам потрібна краща логіка обробки HTML-сутностей. Для цього існує функція <a href="http://ua2.php.net/manual/ru/function.preg-replace-callback.php" onclick="javascript:pageTracker._trackPageview('/ua2.php.net');">preg_replace_callback</a> - вона задіює, передану їй функцію до <em>кожного</em> знайденого набору, що задовольняє регулярному виразу. Цій функції передається один масив, першим елементом якого є набір, що задовольняє виразу, а всіма наступними є набори, які задовольняють всім під-виразам. Тепер у нас є все, щоб дещо покращити наш фільтр:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3615">
        <div class="code" id="p36code15">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="re1">$input</span> <span class="sy0">=</span> <span class="kw3">htmlspecialchars</span><span class="br0">&#40;</span><span class="st0">'&amp;#80;&amp;#69;&amp;#82;&amp;#76;'</span><span class="br0">&#41;</span><span class="sy0">;</span> 
    <span class="kw2">function</span> decode<span class="br0">&#40;</span><span class="re1">$matches</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> 
        <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$matches</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">&gt;</span> <span class="nu0">255</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="co1">// не-ASCII</span>
                <span class="kw1">return</span> <span class="st0">'&amp;#'</span><span class="sy0">.</span><span class="re1">$matches</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="st0">';'</span><span class="sy0">;</span> <span class="co1">// переводимо у дійсну сутність</span>
        <span class="br0">&#125;</span> 
        <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="re1">$matches</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">&gt;=</span> <span class="nu0">65</span> <span class="sy0">&amp;&amp;</span> <span class="re1">$matches</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">&lt;=</span> <span class="nu0">90</span><span class="br0">&#41;</span> <span class="sy0">||</span> <span class="co1">// A - Z </span>
            <span class="br0">&#40;</span><span class="re1">$matches</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">&gt;=</span> <span class="nu0">97</span> <span class="sy0">&amp;&amp;</span> <span class="re1">$matches</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">&lt;=</span> <span class="nu0">122</span><span class="br0">&#41;</span> <span class="sy0">||</span> <span class="co1">// a - z </span>
            <span class="br0">&#40;</span><span class="re1">$matches</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">&gt;=</span> <span class="nu0">48</span> <span class="sy0">&amp;&amp;</span> <span class="re1">$matches</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">&lt;=</span> <span class="nu0">57</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="co1">// 0 - 9 </span>
                <span class="kw1">return</span> <span class="kw3">chr</span><span class="br0">&#40;</span><span class="re1">$matches</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// переводимо у літеральну форму</span>
        <span class="br0">&#125;</span> 
        <span class="kw1">return</span> <span class="re1">$matches</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">;</span> <span class="co1">// все інше залишаємо без змін</span>
    <span class="br0">&#125;</span> 
    <span class="kw3">echo</span> <span class="kw3">preg_replace_callback</span><span class="br0">&#40;</span><span class="st0">'!&amp;amp;#([0-9]+);!'</span><span class="sy0">,</span> <span class="st0">'decode'</span><span class="sy0">,</span> <span class="re1">$input</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// PERL</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p>У цьому прикладі функцію <em>decode</em> викликає preg_replace_callback та використовує під-вираз, який має чисельне значення для порівняння. Якщо це значення більше за 255 (тобто виходить за межі таблиці ASCII), то воно має бути перетворене у дійсну сутність, змінюючи &amp;amp; на &amp;. Для значень іншого діапазону ми робимо <em>додаткову</em> перевірку. Якщо це спеціальний символ (такий як &#8216; чи &lt;), то залишаємо все без змін, інакше (цифра або латинська літера) - переводимо у звичайну літеральну форму.</p>
<p>Однак навіть цього <strong>недостатньо</strong>, адже залишається декілька моментів із HTML-сутностями. Наприклад, сутність <em>не потребує</em> точки із комою в кінці. Тож &amp;#45 - цілком дійсна сутність, яку браузери чудово зрозуміють. Але в такому випадку наші регулярні вирази <em>проваляться</em> та нічого не знайдуть. Більше того, числове значення сутності може бути представлене у вигляді <em>шістнадцяткового числа</em>, тож &amp;#x05A - теж цілком дійсна сутність. А наші попередні регулярні вирази це також <em>не зрозуміють</em>. Отже, вдосконалюємо далі:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3616">
        <div class="code" id="p36code16">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="kw3">preg_replace_callback</span><span class="br0">&#40;</span><span class="st0">'!&amp;amp;#((?:[0-9]+)|(?:x(?:[0-9A-F]+)));?!i'</span><span class="sy0">,</span> <span class="st0">'decode'</span><span class="sy0">,</span> <span class="re1">$input</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p>Трошки ускладнили наш вираз. Тепер з одного під-виразу утворилось двоє: перший спрацьовує, коли ми маємо одну або більше цифру, другий - якщо є символ &#8220;x&#8221;, за яким йде одна або більше цифра чи літера латинського алфавіту з діапазону [A-F]. Окрім того, ми більше не вимагаємо символ &#8220;;&#8221; в кінці. Тут слід зазначити, що квантор &#8220;?:&#8221; означає те, що ми <em>не зберігаємо</em> результат під-запиту, таким чином у результуючому масиві буде так само два елементи. Модифікатор &#8220;i&#8221; в кінці виразу повідомляє про те, що порівняння відбувається <em>незалежно</em> від регістру символів.<br />
Тепер розглянемо відповідні доповнення до функції розкодування:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3617">
        <div class="code" id="p36code17">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="kw2">function</span> decode<span class="br0">&#40;</span><span class="re1">$matches</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> 
        <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span><span class="kw3">is_int</span><span class="br0">&#40;</span><span class="re1">$matches</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#123;</span><span class="nu0">0</span><span class="br0">&#125;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> 
                <span class="re1">$val</span> <span class="sy0">=</span> <span class="st0">'0'</span><span class="sy0">.</span><span class="re1">$matches</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">+</span> <span class="nu0">0</span><span class="sy0">;</span> 
        <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span> 
                <span class="re1">$val</span> <span class="sy0">=</span> <span class="br0">&#40;</span>int<span class="br0">&#41;</span> <span class="re1">$matches</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">;</span> 
        <span class="br0">&#125;</span> 
        <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$val</span> <span class="sy0">&gt;</span> <span class="nu0">255</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> 
                <span class="kw1">return</span> <span class="st0">'&amp;#'</span><span class="sy0">.</span><span class="re1">$matches</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="st0">';'</span><span class="sy0">;</span> 
        <span class="br0">&#125;</span> 
        <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="re1">$val</span> <span class="sy0">&gt;=</span> <span class="nu0">65</span> <span class="sy0">&amp;&amp;</span> <span class="re1">$val</span> <span class="sy0">&lt;=</span> <span class="nu0">90</span><span class="br0">&#41;</span> <span class="sy0">||</span> 
            <span class="br0">&#40;</span><span class="re1">$val</span> <span class="sy0">&gt;=</span> <span class="nu0">97</span> <span class="sy0">&amp;&amp;</span> <span class="re1">$val</span> <span class="sy0">&lt;=</span> <span class="nu0">122</span><span class="br0">&#41;</span> <span class="sy0">||</span> 
            <span class="br0">&#40;</span><span class="re1">$val</span> <span class="sy0">&gt;=</span> <span class="nu0">48</span> <span class="sy0">&amp;&amp;</span> <span class="re1">$val</span> <span class="sy0">&lt;=</span> <span class="nu0">57</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> 
                <span class="kw1">return</span> <span class="kw3">chr</span><span class="br0">&#40;</span><span class="re1">$val</span><span class="br0">&#41;</span><span class="sy0">;</span> 
        <span class="br0">&#125;</span> 
        <span class="kw1">return</span> <span class="re1">$matches</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">;</span> 
    <span class="br0">&#125;</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p>Тут ми додали перевірку і приведення для шістнадцяткових чисел. Спочатку перевіряємо чи перший символ результату є числом. Якщо це так, то маємо десяткове число, приводимо його до цілочислового типу (int), інакше (перший символ - &#8220;x&#8221;) - дописуємо 0 спочатку (таким чином PHP починає розуміти, що йому згодували шістнадцяткове число, тобто маємо щось типу 0&#215;5F) та неявно переводимо до десяткового формату, додаючи до нашого числа 0. Далі код не змінився.<br />
Ось такий буде результат:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3618">
        <div class="code" id="p36code18">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="re1">$input</span> <span class="sy0">=</span> <span class="st0">'&amp;#80&amp;#69&amp;#82&amp;#76;&amp;#60;&amp;#X041;&amp;#1103;&amp;#x30C9;'</span><span class="sy0">;</span> 
    <span class="co1">// результат обробки:</span>
    <span class="co1">// PERL&amp;amp;#60;A&amp;#1103;&amp;#x30C9;</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p>Ось тепер все добре, і після цієї обробки <em>нарешті</em> можна використовувати літеральну фільтрацію <img src='http://webdeveloping.com.ua/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>To be continued&#8230;</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/webdeveloping?a=VrGIJJ"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=VrGIJJ" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=XUvKsJ"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=XUvKsJ" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=78hJeJ"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=78hJeJ" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=I04slj"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=I04slj" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=9MA8Sj"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=9MA8Sj" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/webdeveloping/~4/336566654" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://webdeveloping.com.ua/php/preventing-cross-site-scripting-1/feed</wfw:commentRss>
		<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=webdeveloping&amp;itemurl=http%3A%2F%2Fwebdeveloping.com.ua%2Fphp%2Fpreventing-cross-site-scripting-1</feedburner:awareness><feedburner:origLink>http://webdeveloping.com.ua/php/preventing-cross-site-scripting-1</feedburner:origLink></item>
		<item>
		<title>Mozilla збирається поставити світовий рекорд</title>
		<link>http://feeds.feedburner.com/~r/webdeveloping/~3/300870252/mozilla-and-guinness-world-record</link>
		<comments>http://webdeveloping.com.ua/firefox/mozilla-and-guinness-world-record#comments</comments>
		<pubDate>Thu, 29 May 2008 23:43:24 +0000</pubDate>
		<dc:creator>MoD</dc:creator>
		
		<category><![CDATA[firefox]]></category>

		<category><![CDATA[microsoft]]></category>

		<category><![CDATA[mozilla]]></category>

		<category><![CDATA[популяризація Firefox]]></category>

		<category><![CDATA[Світовий Рекорд Гіннесса]]></category>

		<guid isPermaLink="false">http://webdeveloping.com.ua/?p=37</guid>
		<description><![CDATA[Нещодавно з&#8217;явився соціальний проект від компанії Mozilla, пов&#8217;язаний із скорим виходом нової версії браузера Firefox 3. Суть у тому, щоб зусиллями суспільства здобути Світовий Рекорд Гіннесcа самої завантажуваної програми за 24 години. Все, що потрібно зробити аби допомогти у цьому розробнику Firefox, компанії Mozilla - це зайти на сайт проекту, дати обіцянку завантажити Firefox 3 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.spreadfirefox.com/worldrecord" onclick="javascript:pageTracker._trackPageview('/www.spreadfirefox.com');"><img class="alignleft" style="border: 0pt none; float: left;" title="День Загрузки 2008" src="http://www.spreadfirefox.com/sites/all/themes/spreadfirefox_RCS/images/download-day/buttons/ru/dday_badge_fox.png" border="0" alt="День Загрузки 2008" /></a>Нещодавно з&#8217;явився соціальний проект від <a href="http://www.mozilla.com/" onclick="javascript:pageTracker._trackPageview('/www.mozilla.com');">компанії Mozilla</a>, пов&#8217;язаний із скорим виходом нової версії <a href="http://www.mozilla.com/en-US/firefox/" onclick="javascript:pageTracker._trackPageview('/www.mozilla.com');">браузера Firefox</a> 3. Суть у тому, щоб зусиллями суспільства здобути <a href="http://www.guinnessworldrecords.com/default.aspx" onclick="javascript:pageTracker._trackPageview('/www.guinnessworldrecords.com');">Світовий Рекорд Гіннесcа</a> самої завантажуваної програми за 24 години. Все, що потрібно зробити аби допомогти у цьому розробнику Firefox, компанії Mozilla - це зайти на <a title="Світовий Рекорд Гіннеса найбільш завантажуваної програми за 24 години" href="http://www.spreadfirefox.com/en-US/worldrecord" onclick="javascript:pageTracker._trackPageview('/www.spreadfirefox.com');">сайт проекту</a>, дати обіцянку завантажити Firefox 3 у День Завантаження та не забути її виконати у цей день. Точна дата поки що невідома, але в разі, якщо ви дасте обіцянку, то вам буде вчасно надіслано запрошення від проекту.</p>
<p>У цій нелегкій справі проектом прийнято на озброєння повний арсенал соціальних інструментів: створено групи присвячені цій події у популярних соціальних мережах (MySpace, Facebook та Beebo), спеціальний аккаунт у Twitter, значки для блогів, навіть <a title="Організація тематичних вечірок Mozilla" href="http://mozillaparty.com/" onclick="javascript:pageTracker._trackPageview('/mozillaparty.com');">ось такий</a> цікавий проект для організації тематичних вечірок <img src='http://webdeveloping.com.ua/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Наразі набільш багаті на обіцянки США (звичайно ж), Польща, <del>Албанія(!)</del> <ins>Італія</ins>, Бразилія, Німеччина та Японія. В Україні дано більш ніж 1,5 тисячі обіцянок, а всього близько 200 тисяч і стрімко зростає. На мою думку, це чудова ідея піарщиків Mozilla з популяризації цього вільного браузера.</p>
<p>Наостанок хочу побажати проекту успіхів у здобутті рекорду та популяризації Firefox, адже, чим більше людей користуватиметься Firefox та іншими, альтернативними до ІЕ, браузерами - тим більше буде мотивації у Microsoft робити кращі (за поточні ІЕ) баузери, та тим легше житиметься багатьом веб-розробникам <img src='http://webdeveloping.com.ua/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/webdeveloping?a=JlDa2H"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=JlDa2H" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=IoYEuH"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=IoYEuH" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=QEaRRH"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=QEaRRH" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=OaxAhh"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=OaxAhh" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=XE6ZFh"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=XE6ZFh" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/webdeveloping/~4/300870252" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://webdeveloping.com.ua/firefox/mozilla-and-guinness-world-record/feed</wfw:commentRss>
		<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=webdeveloping&amp;itemurl=http%3A%2F%2Fwebdeveloping.com.ua%2Ffirefox%2Fmozilla-and-guinness-world-record</feedburner:awareness><feedburner:origLink>http://webdeveloping.com.ua/firefox/mozilla-and-guinness-world-record</feedburner:origLink></item>
		<item>
		<title>Ви JavaScript-гуру? Тоді вам необхідний власний логотип!</title>
		<link>http://feeds.feedburner.com/~r/webdeveloping/~3/295479139/javascript-gurus-contest</link>
		<comments>http://webdeveloping.com.ua/various/javascript-gurus-contest#comments</comments>
		<pubDate>Thu, 22 May 2008 02:05:27 +0000</pubDate>
		<dc:creator>MoD</dc:creator>
		
		<category><![CDATA[різне]]></category>

		<category><![CDATA[javascript]]></category>

		<category><![CDATA[unobtrusive JavaScript]]></category>

		<category><![CDATA[гуру]]></category>

		<category><![CDATA[конкурс]]></category>

		<category><![CDATA[кросбраузерність]]></category>

		<guid isPermaLink="false">http://webdeveloping.com.ua/?p=35</guid>
		<description><![CDATA[На блозі Нікіти Селецького нещодавно почався конкурс для програмістів на JavaScript. Суть задачі не складна та цілком практична (стосується мінімальної перевірки введених у форму даних) - мені знадобилось близько півтори години на її вирішення, хоча я й ніякий не гуру  Головні вимоги:

Кросбраузерність
Універсальність - скрипт має вірно працювати навіть при зміні/додаванні нових елементів
Неможна використовувати фреймворки [...]]]></description>
			<content:encoded><![CDATA[<p>На <a title="Блоґ Нікіти Селецького" href="http://seleckis.lv/" onclick="javascript:pageTracker._trackPageview('/seleckis.lv');">блозі Нікіти Селецького</a> нещодавно <a title="Конкурс для JavaScript-гуру" href="http://seleckis.lv/journal/fun/konkurs-dlya-javascript-guru" onclick="javascript:pageTracker._trackPageview('/seleckis.lv');">почався конкурс для програмістів на JavaScript</a>. Суть задачі не складна та цілком практична (стосується мінімальної перевірки введених у форму даних) - мені знадобилось близько півтори години на її вирішення, хоча я й ніякий не гуру <img src='http://webdeveloping.com.ua/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> Головні вимоги:</p>
<ul>
<li>Кросбраузерність</li>
<li>Універсальність - скрипт має вірно працювати навіть при зміні/додаванні нових елементів</li>
<li>Неможна використовувати фреймворки та бібліотеки JavaScript</li>
<li>Неможна змінювати HTML чи CSS, всі зміни лиш у відповідному JS-файлі. Отже практикуємо підхід &#8220;unobtrusive JavaScript&#8221; (ненав&#8217;язливий JS).</li>
</ul>
<p>Сам конкурс триватиме до кінця цього місяця (травня) тож ще є вдосталь часу. Ну і найголовніше - переможець отримує логотип свого блоґу від автора. У будь-якому випадку, непогана вправа для вільного часу.</p>
<p>Тож щасти вам, якщо бажаєте спробувати!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/webdeveloping?a=6JwmkH"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=6JwmkH" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=17RUFH"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=17RUFH" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=Q3Y8LH"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=Q3Y8LH" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=aSMGxh"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=aSMGxh" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=O8Ckfh"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=O8Ckfh" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/webdeveloping/~4/295479139" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://webdeveloping.com.ua/various/javascript-gurus-contest/feed</wfw:commentRss>
		<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=webdeveloping&amp;itemurl=http%3A%2F%2Fwebdeveloping.com.ua%2Fvarious%2Fjavascript-gurus-contest</feedburner:awareness><feedburner:origLink>http://webdeveloping.com.ua/various/javascript-gurus-contest</feedburner:origLink></item>
		<item>
		<title>CakePHP 1.2 - незабаром стабільний</title>
		<link>http://feeds.feedburner.com/~r/webdeveloping/~3/289824559/cakephp-12-stable-soon</link>
		<comments>http://webdeveloping.com.ua/php/cakephp/cakephp-12-stable-soon#comments</comments>
		<pubDate>Wed, 14 May 2008 01:15:46 +0000</pubDate>
		<dc:creator>MoD</dc:creator>
		
		<category><![CDATA[cakephp]]></category>

		<category><![CDATA[framework]]></category>

		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://webdeveloping.com.ua/?p=33</guid>
		<description><![CDATA[Один з найпопулярніших фреймворків для розробки веб-програм на PHP під назвою CakePHP дуже скоро вийде у світ із новою стабільною версією! Цей довгоочікуваний момент для великого комьюніті веб-розробників незабаром настане. MVC фреймворк із відкритим кодом CakePHP 1.2 принесе розробникам багато нових корисних речей, описаних далі


Модулі поведінки моделей (Model Behavior)
Три стандартних модулі поведінки: Acl, Translate, Tree
Підтримка [...]]]></description>
			<content:encoded><![CDATA[<p>Один з <em>найпопулярніших</em> фреймворків для розробки веб-програм на PHP під назвою <a title="Веб-фреймворк CakePHP" href="http://cakephp.org/" onclick="javascript:pageTracker._trackPageview('/cakephp.org');">CakePHP</a> дуже скоро вийде у світ із новою стабільною версією! Цей довгоочікуваний момент для великого комьюніті веб-розробників незабаром настане. <a title="Опис паттерну Модель-Вид-Контроллер" href="http://uk.wikipedia.org/wiki/%D0%9C%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C-%D0%B2%D0%B8%D0%B4-%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D0%B5%D1%80" onclick="javascript:pageTracker._trackPageview('/uk.wikipedia.org');">MVC</a> фреймворк із відкритим кодом CakePHP 1.2 принесе розробникам багато нових корисних речей, описаних далі</p>
<p><span id="more-33"></span></p>
<ul>
<li>Модулі поведінки моделей (Model Behavior)</li>
<li>Три стандартних модулі поведінки: Acl, Translate, Tree</li>
<li>Підтримка DB2, Oracle та Sybase</li>
<li>Підтримка інтернаціоналізації та локалізації</li>
<li>Три нових компоненти ядра: Auth, Cookie, Email</li>
<li>Нові класи ядра: Set, Debugger, HttpSocket, Socket</li>
<li>Іменовані агрументи для дій</li>
<li>Більше можливостей для кешування - підтримка: APC, memcache, xcache, файлового та кеша, основаного на базі даних</li>
<li>Більше можливостей валідації даних</li>
<li>Чотири нових допоміжних класів: Js, Paginator, Rss, Xml</li>
<li>Підтримка тем</li>
<li>Інтегровані тести</li>
<li>Багато-багато інших нових можливостей та виправлень</li>
</ul>
<p>Я розробляю деякі проекти (серед них власна CMS для веб-студії) за допомогою цього фремворка вже близько року, всі були зроблені на нестабільних версіях гілки 1.2. Мушу сказати, що навіть <em>альфа</em> версії були <strong>стабільніші за більшість релізів</strong> іншого програмного забезпечення <img src='http://webdeveloping.com.ua/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> Реліз CakePHP 1.2 має стати чимось на стільки стабільним, наскільки стійкою та непорушною є скеля.</p>
<p>Зміни у репозиторії коду зараз відбуваються <em>кожні кілька хвилин</em>. Наразі розробники цього open source проекту шукають добровольців, які б могли допомогти із наступними речами:</p>
<ul>
<li>Долучення патчів та тестів</li>
<li>Надання інформації про відтворення багів</li>
<li>Пошук нових багів</li>
<li>Допомога команді документування</li>
</ul>
<p>Як пише один з розробників фреймворку, <a title="Маріано Іглесіас про скорий вихід CakePHP 1.2" href="http://bakery.cakephp.org/articles/view/cakephp-1-2-stable-coming-soon" onclick="javascript:pageTracker._trackPageview('/bakery.cakephp.org');">Маріано Іглесіас</a>, допомога проекту - хороший шанс долучитись до одного з найдинамічніших та найцікавіших PHP проектів із відкритим кодом.</p>
<p>Від себе хочу сказати&#8230; нарешті!:) Гілка 1.2 перебуває у нестабільній стадії вже більше року і дуже багато змінилось за цей час у кращу сторону. Думаю, багато людей чекають на цей реліз. У одній з наступних заміток чекайте на огляд фреймворку CakePHP та порівняння із іншими популярними бібліотеками. А якими фреймворками користуєтесь <strong>ви</strong>?</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/webdeveloping?a=abCFlH"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=abCFlH" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=fo1AEH"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=fo1AEH" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=Tmw3hH"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=Tmw3hH" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=3Qfush"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=3Qfush" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=5iXtrh"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=5iXtrh" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/webdeveloping/~4/289824559" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://webdeveloping.com.ua/php/cakephp/cakephp-12-stable-soon/feed</wfw:commentRss>
		<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=webdeveloping&amp;itemurl=http%3A%2F%2Fwebdeveloping.com.ua%2Fphp%2Fcakephp%2Fcakephp-12-stable-soon</feedburner:awareness><feedburner:origLink>http://webdeveloping.com.ua/php/cakephp/cakephp-12-stable-soon</feedburner:origLink></item>
		<item>
		<title>SQL Injection або як зробити вашу базу даних безпечнішою</title>
		<link>http://feeds.feedburner.com/~r/webdeveloping/~3/285032900/sql-injection-securing-your-database-2</link>
		<comments>http://webdeveloping.com.ua/php/sql-injection-securing-your-database-2#comments</comments>
		<pubDate>Wed, 07 May 2008 01:46:47 +0000</pubDate>
		<dc:creator>MoD</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[безпека]]></category>

		<category><![CDATA[caching]]></category>

		<category><![CDATA[linux]]></category>

		<category><![CDATA[MySQL]]></category>

		<category><![CDATA[PostgreSQL]]></category>

		<category><![CDATA[SQL]]></category>

		<category><![CDATA[SQL Injection]]></category>

		<guid isPermaLink="false">http://webdeveloping.com.ua/?p=31</guid>
		<description><![CDATA[SQL Injection (вставка SQL) - це одна з найпоширеніших на ряду із XSS (міжсайтовим скриптингом, про який буде мова у наступній статті) уразливостей, яка є наслідком недостаньої (чи навіть відсутньої) перевірки вводу. Ціль цього типу атак є безпосередньо база даних вашого сайту. Суть - вставка сторонніх даних (найчастіше - запиту до БД) у строку, яка [...]]]></description>
			<content:encoded><![CDATA[<p><em>SQL Injection</em> (вставка SQL) - це одна з найпоширеніших на ряду із <em>XSS</em> (міжсайтовим скриптингом, про який буде мова у наступній статті) уразливостей, яка є наслідком недостаньої (чи навіть відсутньої) перевірки вводу. Ціль цього типу атак є <strong>безпосередньо база даних</strong> вашого сайту. Суть - вставка сторонніх даних (найчастіше - запиту до БД) у строку, яка в результаті буде виконана базою даних. Такий запит може призвести до великої кількості небажаних дій: починаючи від <em>отримання</em> зловмиником будь-яких даних до їх <em>зміни</em> чи <em>видалення</em>. Тож важливо знати, як захистити свою базу даних від таких уразливостей.<br />
<span id="more-31"></span></p>
<p>Для оцінки маштабів цієї проблеми приведемо приклад:<br id="cflp0" /></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3135">
        <div class="code" id="p31code35">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="re1">$userId</span> <span class="sy0">=</span> <span class="st0">&quot;4'; DELETE FROM users;&quot;</span><span class="sy0">;</span> <span class="co1">//можливий ввід</span>
    <span class="kw3">mysql_query</span><span class="br0">&#40;</span><span class="st0">&quot;SELECT * FROM users WHERE id='$userId'&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p><br id="oykg3" />Цей шмат коду має на меті вибрати з бази даних дані користувача за переданим у скрипт ідентифікатором. І, якщо ви використовуєте MySQL, то власне так і зробить <img src='http://webdeveloping.com.ua/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> Адже ця БД не підтримує декілька запросів у одному виклику. А якщо ж ваша БД - SQLite чи PostgreSQL, то вони, не довго думаючи, спочатку виберуть потрібні дані, а потім <em>видалять</em> всі дані з таблиці &#8220;users&#8221;.<br id="z0yv0" /><br id="z0yv1" /></p>
<h3 id="z0yv2">Екранування вводу</h3>
<p>Проблемою у даному випадку є <em>недостатнє екранування</em> і <em>перевірка вводу</em>. Про це вже було достатньо сказано у статті про <a rel="nofollow" href="http://webdeveloping.com.ua/php/php-user-input-data-validation"  title="Стаття про перевірку вхідних даних">перевірку вхідних даних</a>. Давайте розглянемо це у контексті SQL Injection.  Найпростіший захист від цього надає вбудований у PHP механізм <em>magic_quotes_gpc</em>. Коли він увімкнений, перед лапками (одинарними чи подвійними) та іншими загрозливими символами автоматично буде вставлено зворотній слеш (&#8221;\&#8221;).</p>
<p>Однак це <em>недостатнє</em> рішення, оскільки не екранує деякі спеціальні до SQL символи та й не завжди цей механізм увімкнено. Тож різні розширення для роботи із БД мають свої спеціалізовані механізми екранування. У MySQL це функція <a rel="nofollow" href="http://ua2.php.net/manual/ru/function.mysql-real-escape-string.php" onclick="javascript:pageTracker._trackPageview('/ua2.php.net');">mysql_real_escape_string</a> та <a rel="nofollow" href="http://ua2.php.net/manual/ru/function.mysql-escape-string.php" onclick="javascript:pageTracker._trackPageview('/ua2.php.net');">mysql_escape_string</a>. Різниця між ними лиш у тому, що перша екранує відносно указаного їй у параметрах <em>кодування</em>, а друга до цього <em>не чутлива</em>. Приклад використання:<br id="ncap0" /></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3136">
        <div class="code" id="p31code36">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">get_magic_quotes_gpc</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="re1">$userId</span> <span class="sy0">=</span> <span class="kw3">stripslashes</span><span class="br0">&#40;</span><span class="re1">$userId</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="re1">$userId</span> <span class="sy0">=</span> <span class="kw3">mysql_real_escape_string</span><span class="br0">&#40;</span><span class="re1">$userId</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="kw3">mysql_query</span><span class="br0">&#40;</span><span class="st0">&quot;SELECT * FROM users WHERE id='$userId'&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p><br id="q53o1" />У цьому коді спочатку перевіряється наявність розширення magic_quotes_gpc, в разі чого його дія реверсується, щоб не виникло ситуації з подвійним екрануванням. Також специфічні до БД функції є незамінними при зберіганні двійкових даних. Якщо залишити їх неекранованими - вони можуть <em>конфліктувати</em> із форматом збереження даних самої БД. Функції екранування про це знають і <em>не допускають можливої втрати даних</em>.</p>
<p>У деяких БД, наприклад, PostgreSQL - окремі функції відповідають за екранування двійкових даних. Наприклад, функція <a rel="nofollow" href="http://ua2.php.net/manual/ru/function.pg-escape-bytea.php" onclick="javascript:pageTracker._trackPageview('/ua2.php.net');">pg_escape_bytea</a> застосовує Base64-подібне кодування до вхідних даних. Щоправда, таке кодування <em>накладає обмеження на пошук</em> - до них неможна застосовувати такі запити як &#8220;LIKE &#8217;str%&#8217;&#8221;, оскільки значення, збережене у БД, не обов&#8217;язково буде сходитись із тим, яке шукається за запитом. Звичайно, це не проблема для більшості веб-додатків, адже збереження у двійковому вигляді зазвичай необхідно для таких даних як картинки та зтиснені файли, а вони не є предметом глибинного пошуку.<br id="rlxc0" /><br id="rlxc1" /></p>
<h3 id="rlxc2">Підготовлені вирази</h3>
<p>На жаль, не для всіх БД існують специфічні функції екранування. Фактично, вони є лиш для: MySQL, PortgreSQL, SQLite, Sybase та MaxDB. Для інших популярних баз даних як Oracle, MS SQL Server та інших необхідно знайти альтернативу.</p>
<p>На перший погляд може підійти кодування даних у <em>Base64</em>, що ефективно екранує всі спеціальні символи. Але це створює кілька проблем: <em>розмір даних</em>, закодованих Base64 <em>зростає рівно на 33%</em> та <em>унеможливлює вибірку даних</em> за допомогою LIKE. Тож потрібен кращий метод.</p>
<p>Цей метод називається <strong>підготовленими виразами</strong> (або запитами). Такі запити фактично є <em>шаблонами</em> з визначеною структурою та місцями для реальних даних. Часто ці місця суворо типізовані для чисельних та текстових даних. Якщо тип даних <em>не збігається</em> із визначеним типом, то буде видана помилка, що додає ще один ступінь перевірки даних. Також підготовлені вирази додають швидкодію, адже вони компілюються <em>лиш один раз</em> і можуть використовуватись після цього із будь-якими даними. Наприклад, для PostgreSQL це може виглядати так:<br id="h62e0" /></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3137">
        <div class="code" id="p31code37">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="kw3">pg_query</span><span class="br0">&#40;</span><span class="re1">$db</span><span class="sy0">,</span> <span class="st0">'PREPARE stmt_id (int) AS SELECT * FROM users WHERE id=$1'</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="kw3">pg_query</span><span class="br0">&#40;</span><span class="re1">$db</span><span class="sy0">,</span> <span class="st0">&quot;EXECUTE stmt_id ($userId)&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="kw3">pg_query</span><span class="br0">&#40;</span><span class="re1">$db</span><span class="sy0">,</span> <span class="st0">'DEALLOCATE stmt_id'</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p><br id="styk1" />Якщо ви працюєте із MySQL, то підготовлені запити можна використовувати лише із розширенням mysqli чи PDO. Приклад:<br id="t:wh0" /></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3138">
        <div class="code" id="p31code38">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="re1">$stmt</span> <span class="sy0">=</span> <span class="re1">$mysqli</span><span class="sy0">-&gt;</span><span class="me1">stmt_init</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re1">$stmt</span><span class="sy0">&gt;</span>prepare<span class="br0">&#40;</span><span class="st0">'SELECT * FROM users WHERE id=?'</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">bind_param</span><span class="br0">&#40;</span><span class="st0">'i'</span><span class="sy0">,</span> <span class="re1">$userId</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">//&quot;i&quot; означає integer</span>
        <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">execute</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">bind_result</span><span class="br0">&#40;</span><span class="re1">$user</span><span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">fetch</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="re1">$stmt</span><span class="sy0">-&gt;</span><span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p><br id="yv.d0" />Використання трохи різне, але принцип однаковий. Спочатку створюється шаблон запиту, потім приєднуються реальні дані за їх типом та виконується сам запит. Підготовлені вирази - дуже класний інструмент, але дійсний не для всіх БД. У цих випадках слід використовувати екранування.<br id="evu30" /><br id="evu31" /></p>
<h3 id="r8x-0">Коли екранування не допомагає</h3>
<p>Існують випадки, коли екранування даних <em>не убезпечить</em> від зловмисних дій. Уявімо таку ситуацію:<br id="v7.i0" /></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3139">
        <div class="code" id="p31code39">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="re1">$userId</span> <span class="sy0">=</span> <span class="st0">'0; DELETE FROM users'</span><span class="sy0">;</span>
    <span class="re1">$userId</span> <span class="sy0">=</span> <span class="kw3">pg_escape_string</span><span class="br0">&#40;</span><span class="re1">$userId</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="kw3">pg_query</span><span class="br0">&#40;</span><span class="re1">$db</span><span class="sy0">,</span> <span class="st0">&quot;SELECT * FROM users WHERE id=$id&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p><br id="p:la1" />Запит у даному випадку цілком дійсний, адже ми очікуємо чисельні дані і їх не обов&#8217;язково брати у лапки. Цим і наражаємо себе на небезпеку у вигляді <em>SQL Injection</em>. Перший вихід з цієї ситуації - <em>абсолютно всі</em> вхідні дані брати у лапки при використанні у запиті, незалежно від їх типу. Але як ми зараз побачимо, це також не дуже добре:<br id="u_9e0" /></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3140">
        <div class="code" id="p31code40">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="re1">$userId</span> <span class="sy0">=</span> <span class="st0">&quot;0'; DELETE FROM users&quot;</span><span class="sy0">;</span>
    <span class="re1">$userId</span> <span class="sy0">=</span> <span class="kw3">pg_escape_string</span><span class="br0">&#40;</span><span class="re1">$userId</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="kw3">pg_query</span><span class="br0">&#40;</span><span class="re1">$db</span><span class="sy0">,</span> <span class="st0">&quot;SELECT * FROM users WHERE id='$id'&quot;</span><span class="br0">&#41;</span>
             or <span class="kw3">die</span><span class="br0">&#40;</span><span class="kw3">pg_last_error</span><span class="br0">&#40;</span><span class="re1">$db</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p><br id="bzt42" />У цьому випадку звичайно запит не буде виконано, натомість буде видана помилка і це призведе до краху вашої програми. Але ми можемо цього легко і просто уникнути звичайним приведенням типу. Таким чином запит буде вдало виконано і нічого не зупиниться:<br id="bq.e0" /></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3141">
        <div class="code" id="p31code41">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="re1">$userId</span> <span class="sy0">=</span> <span class="st0">'22; DELETE FROM users'</span><span class="sy0">;</span>
    <span class="re1">$userId</span> <span class="sy0">=</span> <span class="br0">&#40;</span>int<span class="br0">&#41;</span><span class="re1">$userId</span><span class="sy0">;</span> <span class="co1">// 22</span>
    <span class="kw3">pg_query</span><span class="br0">&#40;</span><span class="re1">$db</span><span class="sy0">,</span> <span class="st0">&quot;SELECT * FROM users WHERE id=$id&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p><br id="up6o1" />Це буде абсолютно безпечно, адже до запиту прийдуть <em>лише чисельні дані</em>. До того ж це підвищить швидкодію, оскільки приведення типу - дуже швидка операція, яка убирає необхідність виклику функції екранування.<br id="v2l60" /><br id="v2l61" /></p>
<h3 id="oc2l0">Оператор LIKE</h3>
<p>Оператор LIKE у SQL запитах є дуже корисним. Він дозволяє робити вибірку в залежності від знайдених у полі підстрок. Це робиться за допомогою його складових &#8220;<em>%</em>&#8221; та &#8220;<em>_</em>&#8220;, які дозволяють відповідно знаходити строки із 0 чи більшою кількістю будь-яких символів та один будь-який символ. Проблема ж у тому, що ані функції екранування, ані magic quotes не впливають на ці символи. Тож із деякими комбінаціями можна <em>змінити запит</em>, <em>ускладнити вибірку</em> та у багатьох випадках <em>не дозволити використання індексів</em>, що значно вповільнить запит і надасть ґрунт до запуску DoS атаки на ваш сервер БД. Ось надзвичайно простий приклад:<br id="l70j0" /></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3142">
        <div class="code" id="p31code42">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="re1">$string</span> <span class="sy0">=</span> <span class="kw3">mysql_real_escape_string</span><span class="br0">&#40;</span><span class="st0">'%substring'</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// так само %substring</span>
    <span class="kw3">mysql_query</span><span class="br0">&#40;</span><span class="st0">&quot;SELECT * FROM posts WHERE title LIKE '{$string}%'&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p><br id="ymo71" />Суть запиту у тому, щоб вибрати ті записи, у яких назва починається з деякої строки. Такий запит мав би виконатись досить швидко за наявності індексації колонки &#8220;title&#8221;. Але, якщо у строку буде вставлено ще один символ &#8220;%&#8221; на початок, то це унеможливить використання індекса і значно сповільнить запит, при чому, чим більше записів у таблиці, тим повльніше буде здійснюватись пошук.</p>
<p>Символ &#8220;_&#8221; представляє схожу але дещо іншу проблему. Використання цього символу перед закінченням строки пошуку унеможливить використання індекса, а наявність його у кінці - дасть інший результат. Окрім того, символ &#8220;_&#8221; є досить часто вживаним, тож може стати проблемним зовсім випадково без злих намірів. Тож нам потрібно <em>розширити множину екранованих символів</em>. Для цього існує вбудована функція <a rel="nofollow" href="http://ua2.php.net/manual/ru/function.addcslashes.php" onclick="javascript:pageTracker._trackPageview('/ua2.php.net');">addcslashes</a>, яка приймає строку із символами для екранування другим параметром:<br id="pmvi0" /></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3143">
        <div class="code" id="p31code43">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="re1">$str</span> <span class="sy0">=</span> <span class="kw3">addcslashes</span><span class="br0">&#40;</span><span class="kw3">mysql_real_escape_string</span><span class="br0">&#40;</span><span class="st0">'%something_'</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="st0">'%_'</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="co1">//$str = '\%something\_'</span>
    <span class="kw3">mysql_query</span><span class="br0">&#40;</span><span class="st0">&quot;SELECT * FROM posts WHERE title LIKE '{$str}%'&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p><br id="du6m1" />Тож функція addcslashes є таким собі нестандартним <a rel="nofollow" href="addslashes">addslashes</a> і є <em>досить ефективною</em> - значно швидша за str_replace чи еквівалентний регулярний вираз.<br id="odt50" /><br id="odt51" /></p>
<h3 id="ek230">Слідкуємо за помилками</h3>
<p>Один із звичайних шляхів для зловмисника при пошуку уразливого до SQL Injection коду - <em>використання інструментів розробників проти них самих</em>. Наприклад, для полегшення відлагодження SQL-запитів, розробники часто виводять запит, що призвів до помилки і власне саму помилку бази даних:<br id="pkxm0" /></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3144">
        <div class="code" id="p31code44">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="kw3">mysql_query</span><span class="br0">&#40;</span><span class="re1">$query</span><span class="br0">&#41;</span> or <span class="kw3">die</span><span class="br0">&#40;</span><span class="st0">&quot;Помилка запиту: $query&lt;br /&gt;&quot;</span><span class="sy0">.</span><span class="kw3">mysql_error</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p><br id="qhv71" />Часто після процесу розробки такий код потрапляє на робочий варіант сайту і тоді, окрім того, що звичайні користувачі бачать ваш сайт в агонії, ще й зловмисники отримують <em>купу інформації</em> про вашу програму. Наприклад, можливо проаналізувати SQL-запит на предмет колонок використаних таблиць та змайструвати GET чи POST запити, які можуть призвести до ін&#8217;єкції SQL. Більше того, помилка може стати результатом спроби SQL-вставки і послужить зловмиснику <em>інструкцією зі створення більш хитрих запитів</em>.<br id="pjmm0" />Найпростіший шлях уникнути цього - написати власний обробник помилок SQL:<br id="pjmm1" /></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3145">
        <div class="code" id="p31code45">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="kw2">function</span> sql_failure_handler<span class="br0">&#40;</span><span class="re1">$query</span><span class="sy0">,</span> <span class="re1">$error</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="re1">$msg</span> <span class="sy0">=</span> <span class="kw3">htmlspecialchars</span><span class="br0">&#40;</span><span class="st0">&quot;Невдалий запит: $query&lt;br /&gt;Помилка SQL: $error&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="kw3">error_log</span><span class="br0">&#40;</span><span class="re1">$msg</span><span class="sy0">,</span> <span class="nu0">3</span><span class="sy0">,</span> <span class="st0">'/path/to/site/logs/sql_error.log'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
        <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">defined</span><span class="br0">&#40;</span><span class="st0">'debug'</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
            <span class="kw1">return</span> <span class="re1">$msg</span><span class="sy0">;</span>
        <span class="br0">&#125;</span>
&nbsp;
        <span class="kw1">return</span> <span class="st0">'Ця сторінка тимчасово недоступна. Будь ласка, повторіть спробу пізніше.'</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw3">mysql_query</span><span class="br0">&#40;</span><span class="re1">$query</span><span class="br0">&#41;</span> or <span class="kw3">die</span><span class="br0">&#40;</span>sql_failure_handler<span class="br0">&#40;</span><span class="re1">$query</span><span class="sy0">,</span> <span class="kw3">mysql_error</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p><br id="bxuo0" />Ось і все. Обробник приймає строки із запитом і помилкою, виводить інформацію про збій у файл журналу, та, якщо увімкнено режим відлагодження - виводить повідомлення на екран. У робочому ж середовищі, користувач нічого, окрім стандартного повідомлення про недоступність ресурсу, не побачить.<br id="ohqo0" /><br id="ohqo1" /></p>
<h3 id="nr_20">Збігання даних про доступ до БД</h3>
<p>Дуже важливим у створенні безпечного середовища є те, де ви зберігаєте дані про доступ до БД, тобто <em>ваші логін та пароль</em>. Більшість веб-програм використовують маленький PHP-файл, у якому логін та пароль присвоюються деяким змінним чи константам. На цей файл часто встановлюються права на читання для будь-кого, щоб веб-сервер міг отримати до нього доступ. Але це означає, що будь-хто на цій системі чи експлоіт може прочитати цей файл та <em>вкрасти ваші дані</em> про доступ до БД. Більше того, іноді цей файл кладуть у директорії, доступній для будь-кого по ту сторону сервера та дають йому яке-небудь розширення, не асоційоване із PHP. Наприклад, популярним вибором є &#8220;<em>.inc</em>&#8220;. Такі розширення типово не налаштовані на інтерпретацію як PHP-скрипти і веб-сервер просто <strong>віддає їх як звичайний текст</strong>, який будь-хто може побачити.</p>
<p>Вирішень цієї проблеми декілька з різною ступінню безпечності. По-перше, можна використати можливості веб-сервера, такі як файл налаштування <em>.htaccess</em> у Apache для того, щоб заборонити доступ до деяких файлів. Наприклад ось директива, яка забороняє доступ до будь-яких файлів із розширенням .inc:<br id="xjfh0" /></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3146">
        <div class="code" id="p31code46">
            <pre class="apache">&lt;Files ~ <span class="st0">&quot;<span class="es0">\.</span>inc$&quot;</span>&gt;
    <span class="kw1">Order</span> <span class="kw1">allow</span>,<span class="kw1">deny</span>
    <span class="kw1">Deny</span> <span class="kw1">from</span> <span class="kw1">all</span>
&lt;/Files&gt;</pre>
        </div>
    </div>
</div>

<p><br id="xjfh6" />Або ж, наприклад, можна змусити PHP інтерпретувати .inc файли, як скрипти або змінити розширення на <em>.php</em> або <em>.inc.php</em>. Щоправда, перейменування файлів - не завжди найбезпечніший варіант. Найкращий і найпростіший спосіб - <em>не зберігати</em> такі файли у директоріях, доступних для веб-сервера. Але це все-одно <em>не убезпечує</em> від використання експоітів локальними користувачами (актуально, якщо ви на віртуальному хостингу).</p>
<p>Одне, на перший погляд, гарне вирішення проблеми - <em>шифрування</em> важливих даних. Але це робить крадіжку лиш дещо складнішою і <em>не вирішує проблеми</em>, адже ключ до шифру все-одно має бути доступним для PHP-скрипта, який запускається із користувачем веб-сервера, що означає те, що ключ все-одно є доступним для читання будь-ким. Повертаємось до того, з чого і почали.</p>
<p>Правильне вирішення має давати гарантію, що інші користувачі системи <em>не мають жодного шансу</em> побачити дані доступу до БД. На щастя, Apache надає такий інструмент. Файл налаштування Apache, <em>httpd.conf</em>, може включати в себе сторонні файли налаштування у момент запуску процесу веб-сервера, тобто доки він ще працює як <em>root</em>. Оскільки <em>root</em> має доступ до будь-яких файлів, ви можете покласти важливу інформацію у файлі в своїй домашній директорії (/home/user/) і надати права на читання лиш для себе (<em>0600</em>). Таким чином тільки ви та root зможуть читати цей файл. Робиться це таким чином:<br id="fmcn0" /></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3147">
        <div class="code" id="p31code47">
            <pre class="apache">&lt;VirtualHost webdeveloping.com.ua&gt;
    <span class="kw1">Include</span> /home/webdeveloping/sql.conf
&lt;/VirtualHost&gt;</pre>
        </div>
    </div>
</div>

<p><br id="e68q3" />Сам же <em>sql.con</em>f встановлює наступні змінні середовища:<br id="b5h00" /></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3148">
        <div class="code" id="p31code48">
            <pre class="apache"><span class="kw1">SetEnv</span> DB_LOGIN <span class="st0">&quot;login&quot;</span>
<span class="kw1">SetEnv</span> DB_PASS <span class="st0">&quot;password&quot;</span>
<span class="kw1">SetEnv</span> DB_NAME <span class="st0">&quot;my_database&quot;</span>
<span class="kw1">SetEnv</span> DB_HOST <span class="st0">&quot;127.0.0.1&quot;</span></pre>
        </div>
    </div>
</div>

<p><br id="px_o2" />Після запуску Apache, ці змінні будуть доступні PHP через суперглобальний масив <em>$_SERVER</em> або функцію <a rel="nofollow" href="http://ua2.php.net/manual/ru/function.getenv.php" onclick="javascript:pageTracker._trackPageview('/ua2.php.net');">getenv</a>:<br id="jfz60" /></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3149">
        <div class="code" id="p31code49">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="kw3">echo</span> <span class="re1">$_SERVER</span><span class="br0">&#91;</span><span class="st0">'DB_LOGIN'</span><span class="br0">&#93;</span><span class="sy0">;</span> <span class="co1">//login</span>
    <span class="kw3">echo</span> <span class="kw3">getenv</span><span class="br0">&#40;</span><span class="st0">'DB_LOGIN'</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">//login</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p><br id="jfz66" />А ще краще заховати ці дані навіть від скрипта, якому вони потрібні <img src='http://webdeveloping.com.ua/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> Можна використати директиви <em>php.ini</em> для визначення типових даних для зв&#8217;язку із БД. Це також можна встановити у захищеному файлі налаштувань Apache:<br id="w8s80" /></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3150">
        <div class="code" id="p31code50">
            <pre class="apache">php_admin_value mysql.default.host <span class="st0">&quot;127.0.0.1&quot;</span>
php_admin_value mysql.default.<span class="kw1">user</span> <span class="st0">&quot;login&quot;</span>
php_admin_value mysql.default.password <span class="st0">&quot;password&quot;</span></pre>
        </div>
    </div>
</div>

<p><br id="w8s85" />Тепер, функція <a rel="nofollow" href="http://ua2.php.net/manual/ru/function.mysql-connect.php" onclick="javascript:pageTracker._trackPageview('/ua2.php.net');">mysql_connect</a> може працювати без параметрів, адже вони будуть взяті автоматично з налаштувань. Єдине, що потрібно буде встановити - це назва бази. Але не слід використовувати цей метод, якщо ваша версія PHP &lt; 4.3.5. У цих старих версіях був глюк, який дозволяв протікати налаштуванням PHP від одного віртуального хоста до іншого, і таким чином, користувачі інших хостів могли побачити чужі налаштування.<br id="wehb0" /><br id="uk3q0" /></p>
<h3 id="jjdl0">Вказівки до швидкодії</h3>
<p>На останок хочу надати кілька вказівок, які можуть <em>поліпшити швидкодію</em> ваших веб-проектів. Це має безпосереднє відношення і до безпеки, адже повільні запити можуть призвести до інших типів атак, як це було показано із оператором LIKE. Ось кілька простих правил, які слід пам&#8217;ятати:<br id="luws0" /></p>
<ol id="luws1">
<li id="luws2"><strong>Отримуйте лише ті дані, які вам необхідні</strong>. Часто розробники використовують символ &#8220;*&#8221; у запитах для того, щоб дістати всі колонки результату, що може бути величезною кількістю даних, особливо, якщо запит складається з багатьох приєднаних таблиць. Це означає більше використання пам&#8217;яті для сортування у БД, більше часу для передачі до PHP, більше часу і пам&#8217;яті для обробки даних. <br id="vj4k0" /></li>
<li id="luws2">Спробуйте використовувати <strong>небуферизовані запити</strong>, які отримують дані невеличкими порціями. Але їх треба використовувати обережно, адже одночасно ви можете працювати лише із одним запитом. У випадку MySQL, ви не зможете навіть виконати INSERT чи UPDATE, доки всі дані поточного запиту не будуть отримані.</li>
<li id="luws2">Створення з&#8217;єднання із БД - повільна операція, особливо у випадку &#8220;тяжких&#8221; систем, як Oracle, PostgreSQL чи MSSQL. Пришвидшити це можна використовуючи <strong>постійне з&#8217;єднання</strong>, яке дозволяє ресурсу залишатись дійсним навіть після припинення роботи скрипта, що дозволяє використовувати одне і те саме з&#8217;єднання для багатьох процесів веб-сервера. Для цього існує функція <a rel="nofollow" href="http://ua2.php.net/manual/ru/function.mysql-pconnect.php" onclick="javascript:pageTracker._trackPageview('/ua2.php.net');">mysql_pconnect</a> (у випадку MySQL, інші БД мають схожі функції). Але це має свої мінуси. Пул з&#8217;єднань у PHP працює на основі процесів, а не веб-серверів, тому кожен процес веб-сервера <em>має свій пул з&#8217;єднань</em>. Це означає, що 50 запущених процесів Apache призведуть до 50 відкритих з&#8217;єднань із БД. Якщо БД не налаштована на те, щоб приймати одночасно стільки з&#8217;єднань, то зайві будуть відкинуті, що призведе до збою вашої програми.</li>
<li id="luws2">Часто веб-сервер та сервер БД працюють на одній і тій самій машині, що дозволяє оптимізувати передачу даних. Навіщо використовувати повільний і громіздкий TCP/IP, коли ви можете використати <strong>Unix Domain Sockets</strong> (UDG) - <em>найвшидший</em> засіб передачі даних після Inter Process Communication (IPC). Цим ви можете значно пришвидшити зв&#8217;язок між двома серверами. Для цього потрібно змінити хост у налаштуваннях з&#8217;єднання: &lt;?php mysql_connect(&#8217;:/tmp/mysql.sock&#8217;, &#8216;login&#8217;, &#8216;password&#8217;); ?&gt;</li>
<li id="luws2">Використовуйте <strong>кешування запитів</strong>. Це збереже результат запиту на деякий час, продовж якого можна не повторювати запит, а натомість - брати готові дані із кешу. Після того, як кеш стане недійсним - повторити запит і зберегти у кеш.</li>
</ol>
<p><br id="ycep0" />Сподіваюсь, стаття була вам цікава і допоможе зробити вашу роботу із базами даних швидшою і безпечнішою.
</pre>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/webdeveloping?a=nfdWQH"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=nfdWQH" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=v8VXoH"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=v8VXoH" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=z0hrJH"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=z0hrJH" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=FUgrdh"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=FUgrdh" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=iUKSQh"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=iUKSQh" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/webdeveloping/~4/285032900" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://webdeveloping.com.ua/php/sql-injection-securing-your-database-2/feed</wfw:commentRss>
		<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=webdeveloping&amp;itemurl=http%3A%2F%2Fwebdeveloping.com.ua%2Fphp%2Fsql-injection-securing-your-database-2</feedburner:awareness><feedburner:origLink>http://webdeveloping.com.ua/php/sql-injection-securing-your-database-2</feedburner:origLink></item>
		<item>
		<title>Firebug та Firefox 3 beta 5</title>
		<link>http://feeds.feedburner.com/~r/webdeveloping/~3/283838262/firebug-and-firefox-3-beta-5</link>
		<comments>http://webdeveloping.com.ua/firefox/firebug-and-firefox-3-beta-5#comments</comments>
		<pubDate>Mon, 05 May 2008 10:14:45 +0000</pubDate>
		<dc:creator>MoD</dc:creator>
		
		<category><![CDATA[firefox]]></category>

		<category><![CDATA[beta]]></category>

		<category><![CDATA[debug]]></category>

		<category><![CDATA[firebug]]></category>

		<guid isPermaLink="false">http://webdeveloping.com.ua/?p=28</guid>
		<description><![CDATA[Нова версія популярного браузера Firefox 3 є надзвичайно швидкою та приносить багато змін і виправлень (як наприклад, часті витоки пам&#8217;яті). Нажаль, поки що із новою версією працюють далеко не всі розширення - це і не дивно, адже Firefox 3 досі має статус beta. У цій замітці зайде мова про встановлення популярного серед веб-розробників додатку Firebug. [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone size-medium wp-image-29" style="float:left;" title="firebug" src="http://webdeveloping.com.ua/wp-content/uploads/2008/05/firebug.png" alt="" width="152" height="154" />Нова версія популярного браузера <a title="Завантажити Firefox 3" href="http://www.mozilla.com/en-US/firefox/all-beta.html" onclick="javascript:pageTracker._trackPageview('/www.mozilla.com');">Firefox 3</a> є надзвичайно швидкою та приносить багато змін і виправлень (як наприклад, <em>часті витоки пам&#8217;яті</em>). Нажаль, поки що із новою версією працюють далеко не всі розширення - це і не дивно, адже Firefox 3 досі має статус <strong>beta</strong>. У цій замітці зайде мова про встановлення популярного серед веб-розробників додатку <a title="Додаток Firebug до Firefox" href="http://www.getfirebug.com" onclick="javascript:pageTracker._trackPageview('/www.getfirebug.com');">Firebug</a>. Цей додаток дозволяє <em>на ходу </em>змінювати параметри CSS, вносити зміни у DOM документа, відлагоджувати JavaScript та спостерігати за часом завантаження веб-сторінки та її складових. Незамінна річ для тих, хто займається розробкою із використанням AJAX. Сергій Винниченко написав <a title="Огляд додатку Firebug" href="http://www.sergiy.vynnychenko.com/blog/?p=20" onclick="javascript:pageTracker._trackPageview('/www.sergiy.vynnychenko.com');">невеликий огляд Firebug</a> у своєму блозі.</p>
<p>Отже, до 5ої бети браузера можна було використовувати версію Firebug 1.1beta. Але, не всім відомо, що існує також версія 1.2alpha. Так, судячи із статусу, вона ще має достатньо проблем, але є цілком придатною до використання із новим браузером. Також вона вводить ряд нових можливостей, серед них:</p>
<ol>
<li>Програмне вимкнення журналу Firebug через JavaScript</li>
<li>Відображення HTTP статуса у вкладці Net (мережа)</li>
<li>Нова можливість відлагоджування JavaScript: перервати виконання через один брейпоінт.</li>
<li>Вдосконалений монітор заванаження мережі з урахуванням часу оброки запиту на стороні сервера</li>
<li>Новий API консолі</li>
</ol>
<p>Firebug 1.2 можна скачати <a href="http://getfirebug.com/releases/firebug/1.2/" onclick="javascript:pageTracker._trackPageview('/getfirebug.com');">звідси</a> - просто оберіть останній за номером реліз. Або можна взяти свіжий код з <a href="http://code.google.com/p/fbug/source/browse/branches/firebug1.2/" onclick="javascript:pageTracker._trackPageview('/code.google.com');">SVN</a>. Приємного використання!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/webdeveloping?a=UDJHzH"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=UDJHzH" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=vCJEUH"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=vCJEUH" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=G9gLcH"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=G9gLcH" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=T1wUth"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=T1wUth" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=YbHRnh"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=YbHRnh" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/webdeveloping/~4/283838262" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://webdeveloping.com.ua/firefox/firebug-and-firefox-3-beta-5/feed</wfw:commentRss>
		<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=webdeveloping&amp;itemurl=http%3A%2F%2Fwebdeveloping.com.ua%2Ffirefox%2Ffirebug-and-firefox-3-beta-5</feedburner:awareness><feedburner:origLink>http://webdeveloping.com.ua/firefox/firebug-and-firefox-3-beta-5</feedburner:origLink></item>
		<item>
		<title>Експерименти із Kubuntu 8.04 Hardy Heron</title>
		<link>http://feeds.feedburner.com/~r/webdeveloping/~3/274755850/kubuntu-hardy-heron-experiments</link>
		<comments>http://webdeveloping.com.ua/linux/kubuntu-hardy-heron-experiments#comments</comments>
		<pubDate>Mon, 21 Apr 2008 15:03:12 +0000</pubDate>
		<dc:creator>MoD</dc:creator>
		
		<category><![CDATA[linux]]></category>

		<category><![CDATA[adept]]></category>

		<category><![CDATA[firefox]]></category>

		<category><![CDATA[kde]]></category>

		<category><![CDATA[kubuntu]]></category>

		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://webdeveloping.com.ua/?p=22</guid>
		<description><![CDATA[Kubuntu Linux є одним із дистрибутивів родини Ubuntu. Його основною відмінністю є орієнтованість на графічне середовище KDE, замість GNOME (на який орієнтовано Ubuntu). Я користуюсь Kubuntu Linux вже досить давно (більше року) і вважаю його одним із найкращих дистрибутивів Linux, користувачем котрого я є вже більше 5 років. Офіційний випуск нової версії 8.04 з кодовою [...]]]></description>
			<content:encoded><![CDATA[<div id="ggww" style="text-align: left;"><a title="Kubuntu Linux" href="http://www.kubuntu.org/" onclick="javascript:pageTracker._trackPageview('/www.kubuntu.org');">Kubuntu</a> Linux є одним із дистрибутивів родини <a title="Ubuntu Linux" href="http://ubuntu.com/" onclick="javascript:pageTracker._trackPageview('/ubuntu.com');">Ubuntu</a>. Його основною відмінністю є орієнтованість на графічне середовище <a title="Про середовище KDE4" href="http://ru.wikipedia.org/wiki/KDE" onclick="javascript:pageTracker._trackPageview('/ru.wikipedia.org');"><strong>KDE</strong></a>, замість <a title="Про середовище GNOME" href="http://ru.wikipedia.org/wiki/GNOME" onclick="javascript:pageTracker._trackPageview('/ru.wikipedia.org');">GNOME</a> (на який орієнтовано Ubuntu). Я користуюсь Kubuntu Linux вже досить давно (більше року) і вважаю його одним із найкращих дистрибутивів Linux, користувачем котрого я є вже більше 5 років. Офіційний випуск нової версії 8.04 з кодовою назвою <em>Hardy Heron</em> (у перекладі &#8220;стійка чапля&#8221;) назначений на 24 квітня. Але я не витримав чекати ще кілька днів і вирішив спробувати <em>release candidate</em> <img src='http://webdeveloping.com.ua/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> Отже, у цій замітці буде мій досвід з встановлення і користування новою версією.</div>
<p><span id="more-22"></span></p>
<h2 id="mwra">Що нового?</h2>
<p><strong>Kubuntu</strong>:</p>
<ul id="oqn1">
<li id="iof:">KDE 4.0.3 (на вибір)</li>
<li id="i9td">KDE 3.5.9</li>
<li id="p_h4">Ефекти стільниці для KDE 3.5.9<br />
<h2 id="mwra"><a href="http://webdeveloping.com.ua/wp-content/uploads/2008/04/desktopeffects.png" ><img class="alignright size-thumbnail wp-image-25" style="float: right;" title="desktopeffects" src="http://webdeveloping.com.ua/wp-content/uploads/2008/04/desktopeffects-150x150.png" alt="Налаштування ефектів стільниці" width="150" height="150" /></a></h2>
</li>
<li>Amarok 1.4.9.1</li>
<li>Автоматичне встановлення кодеків (в тому числи DVD) при відкритті відео за допомогою Kaffeine</li>
<li>Налашування шифрування файлової системи при встановленні</li>
<li> Монтування NTFS-розділів користувачем</li>
<li>Безпечне налаштування X-сервера та дисплея збереже від несправного налаштування</li>
<li>Відображення споживання електроенергії при використанні акамулятора</li>
</ul>
<p><br id="pc7u" />Загальне для <strong>Ubuntu</strong>:<br id="ygs1" /></p>
<ul id="lv7s">
<li>Ядро Linux 2.6.24</li>
<li>Xorg 7.3</li>
<li>Firefox 3 beta 5</li>
<li>OpenOffice 2.4<br id="ruqo" /></li>
<li>ufw - простий у налаштуванні фаєрвол</li>
<li>Inkscape 0.46</li>
<li>Інтеграція у ActiveDirectory через Likewise Open</li>
<li>Підтримка iSCSI</li>
<li>Покращений захист пам&#8217;яті</li>
<li>Підтримка SELinux</li>
<li>Віртуалізація через KVM</li>
<li>Інтеграція драйверів бездротових пристроїв серії Rt2&#215;00<br id="tptz" /></li>
<li>Wubi - інсталяція Linux у Windows з використанням завантажувача останньої</li>
</ul>
<p><br id="f7ef" /></p>
<h2 id="x7_b">Встановлення</h2>
<p>Оскільки у мене вже стояв Kubuntu 7.10 я спробував оновитись через мережу. Для цього необхідно виконати наступну команду (у консолі чи через Alt-F2):<br id="nxli" /></p>
<pre style="font-size:120%;">kdesu "adept_manager --dist-upgrade-devel"</pre>
<p>Звичайно, у фінальній версії <em>не потрібно</em> буде цього робити, адже Adept <em>сам</em> запропонує вам оновити дистрибутив, як тільки вийде реліз. Але перед тим як продовжувати зауважте, якщо ви використовували <strong>PPA-репозиторій</strong> для KDE4, то вам треба буде його вимкнути та <em>видалити все</em>, що відноситься до KDE4.</p>
<p><a href="http://webdeveloping.com.ua/wp-content/uploads/2008/04/adept.jpeg" ><img class="alignleft size-thumbnail wp-image-27" style="float: left;" title="Adept" src="http://webdeveloping.com.ua/wp-content/uploads/2008/04/adept-150x150.jpg" alt="Менеджер пакунків Adept" width="150" height="150" /></a>Далі, переконайтесь, що у вас встановлені <em>всі оновлення</em> до поточної версії, якщо ні, то самий час це зробити. Також, переконайтесь, що у вас встановлений один із наступних мета-пакунків: kubuntu-desktop, ubuntu-desktop, edubuntu-desktop, edubuntu-desktop-kde, xubuntu-desktop. Інакше, оновлювач <em>не зможе</em> визначити начинку дистрибутиву.</p>
<p>Отже, у меню Adept має з&#8217;явитись додаткова кнопка для оновлення дистрибутиву. Після її натиснення все має пройти гладко (принаймні у мене все було OK). Можете піти погуляти кілька годинок (в залежності від швидкості вашого з&#8217;єднання із Мережею), адже будуть завантажені пакунки загальним розміром приблизно у 800-900Мб. Якщо трафік вам дорогий, то краще подумайте про альтернативу - диск Kubuntu 8.04 Alternative для оновлення з нього.</p>
<p>Якщо ви не маєте встановленого Kubuntu Linux, то використайте <a title="Сторінка з посиланнями на встановлювачі Kubuntu 8.04 RC" href="https://wiki.kubuntu.org/HardyHeron/RC/Kubuntu#head-7278e1b8b1ee7a1bfff91a03418e4ee371ddbcdb" onclick="javascript:pageTracker._trackPageview('/wiki.kubuntu.org');">диск для встановлення</a> - процедура буде простою та інтуїтивною. В разі, якщо хочете використовувати новий (але поки що не дуже стабільний) KDE4 - вам потрібен диск <em>Kubuntu 8.04 KDE4 Remix</em>.</p>
<p>Отже, якщо все пройшло добре і ви оновили свою ОС, то після перезавантаження у Adept побачите новий мета-пакунок <strong>kubuntu-kde4-desktop</strong>. Саме його необхідно встановити, якщо вам цікавий <em>новий</em> KDE. Це одним махом встановить <em>всі</em> необхідні пакунки для базової функціональності нового графічного середовища. Всі інші ви можете знайти та встановити самотужки, набравши у полі пошуку &#8220;kde4&#8243;.<br id="n2oy" /><br id="osfl" /></p>
<h2 id="g8su">Огляд</h2>
<p>В плані графічного інтерфейсу нічого нового, окрім дещо змінених тем я не помітив. Тут слід зазначити, що всі налаштування повністю зберіглись і запрацювало все без проблем. З позитивного, у KDE4 перестали пропадати деякі іконки з системного лотка (system tray) <img src='http://webdeveloping.com.ua/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> Але, що дійсно сподобалось, то це нова <strong>бета Firefox 3</strong>. Вона тут встановлюється <em>автоматично</em>, тобто є типово обраним браузером. Не дивлячись на статус &#8220;<em>бета</em>&#8220;, працює досить стабільно. А головне, значно, значно, швидше та використовуючи менше пам&#8217;яті ніж 2га версія - я думаю, тепер є ще один аргумент на користь цього браузера. З мінусів - поки що підтримуються не всі розширення. <br id="lcue" />Серед моїх <strong>працюють</strong>:<br id="na2n" /></p>
<ul id="q6j9">
<li id="w5c0">ColorZilla</li>
<li id="h4v4">Download Statusbar</li>
<li id="bu_6">DownThemAll!</li>
<li id="bu_6">Live HTTP Headers</li>
<li id="bu_6">Operator</li>
<li id="bu_6">Web Developer</li>
</ul>
<p>А <strong>не працюють</strong> дуже корисні:<br id="es10" /></p>
<ul id="z48i">
<li id="b.lm">Fasterfox</li>
<li id="hbxu">Firebug</li>
<li id="qtb-">Google Toolbar</li>
<li id="tpcf">HTML Validator</li>
<li id="lacx">Locationbar</li>
</ul>
<p>Сподіваємось, що скоро вийдуть оновлення для цих розширень. А поки, є можливість використовувати поруч 2гу версію Firefox. У Adept ці пакунки називаються відповідно <em>firefox-3.0</em> та <em>firefox-2</em>.<a href="http://webdeveloping.com.ua/wp-content/uploads/2008/04/amarok.png" ><img class="alignright size-thumbnail wp-image-24" style="float: right;" title="amarok" src="http://webdeveloping.com.ua/wp-content/uploads/2008/04/amarok-150x150.png" alt="Програвач звуку Amarok" width="150" height="150" /></a><br id="jmkg" />Окрім Вогнелиса, корисна для поціновувачів продукції Apple фіча у новому програвачі <a title="Вільний програвач Amarok" href="http://amarok.kde.org/" onclick="javascript:pageTracker._trackPageview('/amarok.kde.org');"><strong>Amarok</strong></a> - тепер є підтримка iPhone та iPod Touch плюс оновлений сервіс отримання картинок альбомів з Amazon. А користувачі KDE3 тепер без зайвих танців із бубном можуть вмикати <strong>ефекти стільниці</strong> через спеціальну секцію у системних налаштуваннях. <strong>OpenOffice</strong> тепер може порадувати підтримкою баз даних у форматі MS Access.</p>
<p>Звичайно, дуже багато нових речей всередині ОС. Більшість оновлень стосуються <strong>стабільн</strong><strong>ості та безпеки</strong> системи - це і не дивно, адже цей реліз Ubuntu (не Kubuntu) є <em>LTS</em>, тобто має довгий термін офіційної підтримки (3 роки для desktop-версії та 5 років для серверної) і цим розрахований на корпоративних користувачів. Хоча Kubuntu це і не стосується (через нестабільність KDE4), але ці оновлення звичайно ж присутні. <br id="y9r-" /><br id="lokq" />У висновок скажу, що чергове оновлення приносить велику кількість внутрішніх змін (не надто помітних користувачу), нові версії софта і підтримку KDE4 з основних репозиторіїв. Вже зараз встановлення проходить гладко і без проблем. Тому, не бачу змісту не оновитись, коли вийде реліз <img src='http://webdeveloping.com.ua/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<div style="text-align:center;"><a href="http://webdeveloping.com.ua/wp-content/uploads/2008/04/mydesktop.jpg" ><img class="size-thumbnail wp-image-26" style="float:none;" title="Моя стільниця" src="http://webdeveloping.com.ua/wp-content/uploads/2008/04/mydesktop-150x150.jpg" alt="Моя стільниця" width="150" height="150" /></a></div>
<p><strong>UPD: </strong>Якщо ви маєте проблеми із звуком у KDE4 - спробуйте перевстановити всі пакунки, які відносяться до звуку (alsa, phonon, kmix і т.п.), після чого у &#8220;Системних параметрах&#8221; -&gt; &#8220;Звук&#8221; видаліть ваш звуковий пристрій. Далі перейдіть до вкладки &#8220;Серверна програма&#8221; і позначте пункт &#8220;Показати пристрої OSS&#8221;, натисність &#8220;Застосувати&#8221;. Вийдіть з графічного середовища і увійдіть у нього знов. Тепер звук має з&#8217;явитись. Але будуть також з&#8217;являтись повідомлення про перехід до іншого пристрою при кожній спробі використати звук. Для того, щоб позбавитись цього пересуньте ваші пристрої догори у системних параметрах. Поекспериментуйте, який саме пристрій підходить.</p>
<p>Сподіваємось, що до релізу це виправлять.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/webdeveloping?a=iPn0HuG"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=iPn0HuG" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=MtRNgUG"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=MtRNgUG" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=GHeVXRG"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=GHeVXRG" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=mTkCkcg"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=mTkCkcg" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/webdeveloping?a=ct1x2hg"><img src="http://feeds.feedburner.com/~f/webdeveloping?i=ct1x2hg" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/webdeveloping/~4/274755850" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://webdeveloping.com.ua/linux/kubuntu-hardy-heron-experiments/feed</wfw:commentRss>
		<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=webdeveloping&amp;itemurl=http%3A%2F%2Fwebdeveloping.com.ua%2Flinux%2Fkubuntu-hardy-heron-experiments</feedburner:awareness><feedburner:origLink>http://webdeveloping.com.ua/linux/kubuntu-hardy-heron-experiments</feedburner:origLink></item>
		<item>
		<title>Обробка зовнішніх даних. Частина ІІ: Валідація</title>
		<link>http://feeds.feedburner.com/~r/webdeveloping/~3/272546893/php-user-input-data-validation</link>
		<comments>http://webdeveloping.com.ua/php/php-user-input-data-validation#comments</comments>
		<pubDate>Fri, 18 Apr 2008 01:18:04 +0000</pubDate>
		<dc:creator>MoD</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[безпека]]></category>

		<category><![CDATA[pcre]]></category>

		<category><![CDATA[валідація]]></category>

		<category><![CDATA[зовнішні дані]]></category>

		<guid isPermaLink="false">http://webdeveloping.com.ua/?p=21</guid>
		<description><![CDATA[У попередньому записі я розповідав про джерела вводу і їх убезпечення. У цій статті я хочу показати як можна перевірити на дійсність дані, що вже потрапили у скрипт. Якщо ви не будете перевіряти дані, то рівень безпеки ані трохи не підвищиться, навіть, якщо ви зробили сам ввід даних більш безпечним.У минулій статті було згадано, що [...]]]></description>
			<content:encoded><![CDATA[<p>У <a title="Обробка зовнішніх даних. Частина І: Ввід" href="http://webdeveloping.com.ua/php/php-user-input-data-processing" >попередньому записі</a> я розповідав про джерела вводу і їх убезпечення. У цій статті я хочу показати як можна <strong>перевірити на дійсність</strong> дані, що вже потрапили у скрипт. Якщо ви не будете перевіряти дані, то рівень безпеки ані трохи <em>не підвищиться</em>, навіть, якщо ви зробили сам ввід даних більш безпечним.<br id="n53a" />У минулій статті було згадано, що всі дані приходять як строки чи масиви строк, але у різних ситуаціях ми можемо очікувати різні види даних, наприклад, числа  чи які-небудь шаблонні дані (e-mail&#8217;и, URL&#8217;и, телефонні номери і т.п.). Тож розглянемо ці види даних і методи їх перевірки.<span id="more-21"></span></p>
<h3 id="k56-">Чисельні дані</h3>
<p>Найшвидший і найпростіший метод валідації чисельних даних - <strong>приведення типу</strong> до необхідного чисельного типу (<em>int</em>, <em>float):</em></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p2170">
        <div class="code" id="p21code70">
            <pre class="php"><span class="kw2">&lt;?php</span>
    <span class="re1">$_GET</span><span class="br0">&#91;</span><span class="st0">'id'</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="br0">&#40;</span>int<span class="br0">&#41;</span><span class="re1">$_GET</span><span class="br0">&#91;</span><span class="st0">'id'</span><span class="br0">&#93;</span><span class="sy0">;</span>
    <span class="re1">$_POST</span><span class="br0">&#91;</span><span class="st0">'price'</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="br0">&#40;</span>float<span class="br0">&#41;</span><span class="re1">$_POST</span><span class="br0">&#91;</span><span class="st0">'price'</span><span class="br0">&#93;</span><span class="sy0">;</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p><br id="ojl3" /> Приведення типу переводить чисельні дані у строках - це дає впевненість, що у скрипт потраплять <strong>лише чисельні дані</strong>, незалежно від того, що було введено. Якщо введена строка містить лише нечисельні дані, то приведення поверне число 0. У більшості випадків це буде <em>небажаним</em>, тож проста умова після приведення типу дасть змогу ефективно перевірити дані, і у разі необхідності видати помилку:<br id="p5n7" /> <br id="r7m:" /></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p2171">
        <div class="code" id="p21code71">
            <pre class="php"><span class="kw2">&lt;?php</span>
   <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span><span class="re1">$value</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
       <span class="co1">//Помилка</span>
   <span class="br0">&#125;</span>
<span class="kw2">?&gt;</span></pre>
        </div>
    </div>
</div>

<p>Пам&#8217;ятайте, що при можливості введення занадто великого числа, краще приводити до типу із <strong>плаваючою точкою</strong> (float). Наприклад, на 32-бітних системах розмір цілочисленого типу (int) сягає 4 байт, окрім того він є знаковим, тобто <em>максимальне</em> число для змінної такого типу - 2 147 483 647 ((2^4^8)/2). Якщо більше число буде введено, то станеться переповнення і <em>втрата даних</em> як наслідок. Приведення до типу із плаваючою точкою збереже дані у форматі &#8220;знак * 2^експонента * мантиса&#8221;, таким чином ті ж 4 байт дозволяють зберігати <em>значно більші</em> числа.</p>
<p>Щоправда, таким чином можна пререводити лише десяткові числа, а наприклад, шістнадцяткові та вісімкові вже - ні. Для цього існує більш гнучка функція PHP <a href="http://ua.php.net/manual/ru/function.is-numeric.php" onclick="javascript:pageTracker._trackPageview('/ua.php.net');" rel="nofollow">is_numeric</a>. Вона приймає <em>всі</em> формати даних і повертає булеве t