Fat Free CRM CSRF / SQL Injection / Known Secret

Type packetstorm
Reporter joernchen
Modified 2013-12-24T00:00:00


                                            `To whom it may concern:  
A rather informal advisory on Fat Free CRM (http://fatfreecrm.com/):  
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  
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": "",  
"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": "",  
"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])  
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?  
render :nothing => true  
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:  
Happy Holidays,  
joernchen ~ Phenoelit  
<joernchen@phenoelit.de> ~ C776 3F67 7B95 03BF 5344  
http://www.phenoelit.de ~ A46A 7199 8B7B 756A F5AC