To whom it may concern: A rather informal advisory on Fat Free CRM (http://fatfreecrm.com/): Timeline: Aug 27th 2013 Initial email containing the findings listed below including a note that there more vulnerabilities which just need to be verified. (Send to mike@fatfreecrm.com and security@fatfreecrm.com) Sep 16th 2013 No response so far (not even a bounce of the initial mail), re-send email of Aug. 27th. Dec 20th 2013 Still no response. Dec 24th 2013 Public Disclosure. Hint: Actually the codebase is full of Ruby on Rails worst practices. You might want to use it as a sample "Hack Me" application. --- 1. Known Session Secret In config/initialiers/secret_token.rb a static secret token is defined, with the knowledge of this token an attacker is able to execute arbitrary Ruby code server side. 2. Lack of CSRF Protection In app/controllers/application_controller.rb the protect_from_forgery statement is missing, therefore Fat Free CRM is vulnerable to CSRF attacks. 3. Default to_json for models The users controller renders JSON requests with a full JSON object: For instance when being logged in to the demo app and requesting http://demo.fatfreecrm.com/users/1.json, the response would be { "user": { "admin": true, "aim": "", "alt_email": "", "company": "example", "created_at": "2012-02-12T02:00:00+02:00", "current_login_at": "2013-08-26T22:12:05+03:00", "current_login_ip": "61.143.60.146", "deleted_at": null, "email": "aaron@example.com", "first_name": "Aaron", "google": "", "id": 1, "last_login_at": "2013-08-24T22:20:06+03:00", "last_login_ip": "122.173.185.99", "last_name": "Assembler", "last_request_at": "2013-08-26T22:13:35+03:00", "login_count": 481, "mobile": "(800)555-1211", "password_hash": "56d91c9f1a9c549304768982fd4e2d8bc2700b403b4524c0f14136dbbe2ce4cd923156ad69f9acce8305dba4e63faa884e61fb7a256cf8f5fc7c2ce176e68e8f", "password_salt": "ce6e0200c96f4dd326b91f3967115a31421a0e7dcddc9ffb63a77f598a9fcb5326fe532dbd9836a2446e46840d398fa32c81f8f4da1a0fcfe931989e9639a013", "perishable_token": "NE0n6wUCumVNdQ24ahRu", "persistence_token": "d7cdeffd3625f7cb265b21126b85da7c930d47c4a708365c20eb857560055a6b57c9775becb8a957dfdb46df8aee17eb120a011b380e9cc0882f9dfaa2b7ba26", "phone": "(800)555-1210", "single_access_token": "TarXlrOPfaokNOzls2U8", "skype": "ranzitreddy", "suspended_at": null, "title": "VP of Sales", "updated_at": "2013-08-26T22:13:35+03:00", "username": "aaron", "yahoo": "" } } A custom to_json method which sanitizes the output should be created. 4. Multiple SQL Injections In app/controllers/home_controller.rb: def timeline unless params[:type].empty? model = params[:type].camelize.constantize item = model.find(params[:id]) item.update_attribute(:state, params[:state]) else comments, emails = params[:id].split("+") Comment.update_all("state = '#{params[:state]}'", "id IN (#{comments})") unless comments.blank? Email.update_all("state = '#{params[:state]}'", "id IN (#{emails})") unless emails.blank? end render :nothing => true end Here params[:state], comments and emails are attacker controlled values which go directly into SQL statements. Therefore this piece of code exposes a SQL Injection vulnerability. --- Static URL of this text: http://www.phenoelit.org/stuff/ffcrm.txt Happy Holidays, joernchen -- joernchen ~ Phenoelit ~ C776 3F67 7B95 03BF 5344 http://www.phenoelit.de ~ A46A 7199 8B7B 756A F5AC