Saturday, February 27, 2010

Dynamic Image from text/string in Rails

Image will be generated dynamically from string or text:

Use - require 'RMagick' in your class



Pre-requisite : You must have rmagick and Imagemagick installed.
Details: http://www.simplesystems.org/RMagick/doc/draw.html

Monday, February 22, 2010

How to develop rails plugin from scratch?

Generate Plugin with command: ruby script/generate plugin hello_world
It will create file system as bellow:
- lib
    - hello_world.rb
- tasks
    - hello_world_tasks.rake
- test
    - hello_world_test.rb
- init.rb
- install.rb
- uninstall.rb
- README
- Rakefile
- MIT-LICENSE

init.rb will be executed every time when your application runs. Generally hook code is to be included here like you want to make all methods of your plugin available in your app’s models, controllers, views and helpers

Example:
#All methods in module HelloWorld will be available in all #model’s object
ActiveRecord::Base.class_eval do
    include HelloWorld
end

#All methods in module HelloWorld will be available in all controllers
ActionController::Base.class_eval do
    include HelloWorld
end

#All methods in module HelloWorld will be available in all views and all helpers
ActionView::Base.class_eval do
    include HelloWorld
end

lib/ hello_world.rb :

Example:
# All methods in this library will be available in all models, controllers, views and helpers if you write code as init.rb above

module HelloWorld
    def say_hello
        return "Hello World"
    end
    def hello_text
        return “this is text”
    end
end

Now you need to do unit test your plugin’s methods. To do so follow:
test/hello_world_test.rb:

Example:
require 'test/unit'
require File.join(File.dirname(__FILE__),'../lib/hello_world.rb')

class HelloWorldTest < Test::Unit::TestCase
    include HelloWorld # includes your library methods to test

    def test_this_plugin
        hello_world = say_hello
        assert_equal hello_world, "Hello World"
        assert_not_nil hello_world
    end

    def test_another
        assert_equal true,true
    end
end

To run these test cases, go to your plugin’s directory with command prompt and run like: ruby test/hello_world_test.rb

You are done actually with plugin!

Install.rb: It will be executed only once when the plugin is being installed.

Uninstall.rb: This will be executed when you do uninstall your plugin

README: In this file, you should write easy documentation of your plugin with examples. Also you may highlight yourself here.

Saturday, February 13, 2010

Security of rails Application on WEB

Session Fixation:
1. In the figure(http://guides.rubyonrails.org/images/session_fixation.png), suppose a hacker login to the server with his own credential

2. Server will store his information into session against client’s _session_id (server generates this id if there is no session id already created). Next time when this client requests this session information, server will response against that _session_id.

3. Now suppose hacker becomes able to execute a script like hacker wrote a comment with following script to client’s blog post: <script>document.cookie="_session_id=16d5b78abb28e3d6206b60f22a03c8d9";</script>.

4. Suppose client refreshes his blog post page. Now client’s session id becomes equal with hacker’s session id!!!.

5. Now any one from client or hacker will get client’s credential from session!!!

6. Thus hacker will get client’s credential and do all as client

Protection:
Reset all session before login and store session information for login request like:

reset_session
Session[:user] = User from DB


SQL Injection:
Suppose we have
User.first(:conditions=>["username= #{params[:username]} AND password= #{params[:password]}"])

Will generate:
SELECT * FROM users where username=params[:username] AND password=params[:password] limit 1

What if you pass params[:password]=' OR '1'='1 ???

Will generate:
SELECT * FROM users where username=‘abc’ AND password=‘’ OR ‘1’=‘1’
The query is true and now hacker is logedin!!! For the first user credential

Protection:
Use ? In string like:
User.first(:conditions=>["username=? AND pass=?",params[:username],params[:pass]])

Use place holder like
User.first(:conditions=>"username=:username AND pass=:pass",{:username=>params[:username], :pass=> params[:pass]})

Use Hash like:
User.first(:conditions => {:username => params[:username], :password => params[:pass]})

Use to_i for integer type data
User.find(params[:id].to_i)


Phishing(1):
If a hacker writes HTML code in comment like:
<img src="http://www.domain.com/projects/destroy/1" >
than this img tag will request for an image source. Actually this src will make a request to projects controller, destroy method. Generally we check when destroy anything like:

def destroy
project = Project.find(params[:id])
if(session_user && session_user.id == project.user_id)
project.destroy()
end
end

IF CONDITION will be true and hacker will be able to destroy client’s projects!!!

Protection:
Verify requested method whether it is GET or POST in controller and in view use h() method before the comment body like
<%= h blog.comments.first.body %>
[Actually don’t trust user given input data]

Phishing(2):
If hacker writes HTML code of site’s login form into his comment like:

<div class="login_form" >
<form action="http://www.hackar.com/hack">
Username: <input type="text" name="username" >
Password: <input type="password" name=”password”>
</form>
</div>

And the fool client fills out his username and password with this injected login form than hacker will be able to grab client’s credential!

Protection:
call protect_from_forgery method from ApplicationController
which will generates a hidden field with a token into all html form like

<input name=“authentecity_token" value=“d8192312u3n123123091" type=“hidden" >

When user submits this form server will check the submitted token against generated token.


Mass assignment:
Suppose we have users table with a column name role_id. If role id is 1 then the user will be Admin than our conventional registration/profile form will be like:

<form action="/users/create" method="post">
Username: <input name="[user][username]" type="text">
Password: <input name="[user][password]" type="text">
Email: <input name="[user][email]" type="text" >
First Name: <input name="[user][first_name]" type="text" >
Last Name: <input name="[user][last_name]" type="text" >
</form>

Using FIREBUG if I push <input nanme="user[role_id]" value="1" type="hidden" > into this form then any user will be able to become Admin!

Protection:
Make role_id protected in user model which will be nil when user object is created

To update this field from admin follow:
model.rol_id = 1
model.save(false)


File Upload & Download:
Do not place file in Rails/public if it is Apache’s home directory because it may be executed (like file.php) when requested

Always use send_file method for download
Check file type when upload

Log file:
All rails generated SQL, error report, responses are logged in log file

In ApplicationController use the method bellow:
filter_parameter_logging :password



Part of Log File:
Parameters: {"commit"=>"Save", "action"=>"create", "controller"=>"[FILTERED]", “user"=>{“password"=>"[FILTERED]", “username"=>“abc"}}

Don’t use eval with params:
Eval(params[:model]).find(1)
What’s happened if you pass params[:model] = “User.destroy_all”

It will become:
Eval(“User.destroy_all”).find(1) !!!!!!!

Protection:
params[:model].constantize.find(1)

Reference: http://guides.rubyonrails.org/security.html