combining django ORM with direct database access for a complex app? - mysql

Sorry, if this is a newbie question.
We're building an analytics application, with different components. The visualization and web app is in Django, backend connecting drivers are written using PHP, and various analytics are written in python (precomputed, django is only responsible for rendering).
All these components access and update the same database (mysql). The tables were created by Django ORM, but are updated by Python scripts (mysqldb) and PHP as required.
Are there any unseen downsides to this approach of mixing django ORM access and direct database access? For the python component, we could use ('from django.core.management import setup_environ'), but its more efficient to have direct control over SQL statements. Is there a better design approach that we should be aware of?
The only downside is we can think of, is the added complexity to future changes to the database/models.py, but that's something we can live with.
Thanks!

Answering this myself.
We have this working fine since several weeks. The only downside of course, is that if we make changes to models.py (using django ORM), we have to tweak PHP code by hand, which would be expected.
For authenticated users, the PHP code uses data from auth_user to authenticate incoming connections. The exact use of password + salt to generate hash is documented in other posts, see What is the format in which Django passwords are stored in the database?.
Edit: #Josh asked for the PHP snippet, here it is:
// ASSUMES YOU HAVE django username and password from web form POST request
// GET THE HASH + SALT FOR THIS USER
$query = "SELECT password FROM auth_user WHERE username = '$_POST[email]' LIMIT 1 ";
$result = mysql_query($query) or die(mysql_error());
$row = mysql_fetch_array($result);
list($algo,$salt,$pass) = explode('$',$row['password']);
// RE-HASH PASSWORD from POST request
$hash = sha1($salt . $_POST['password']);
$hash = "sha1$$salt$$hash";
// GET HASH FROM DATABASE TO COMPARE
$query = "SELECT username FROM auth_user WHERE password = '$hash' LIMIT 1";
$result = mysql_query($query) or die(mysql_error());

Related

How can I query to database from zend framework view (phtml)?

I need to access database from phtml (view) in zend. how can i do that?
$stmt = $db->query('SELECT * FROM mcommerce_cart');
Well, you should not do this (it's bad practice). Recommend way is to access DB via models. You can pass data to view from Controller, Zend_View_Helper or (also no so recommeneded) via direct call to model.
But if you really want to access DB in View than you can get Default Adapter by calling $db = Zend_Db_Table::getDefaultAdapter();

How to pass a where clause simply but safely via a console command in ZF2?

I'm creating a quick and dirty console controller to create fixtures from a database table.
I'd like to use a where clause to limit this - but would like to make the controller a little less dirty and prevent injections.
My current console command specification is:
db create fixture <table_name> [--where=]
The controller action has:
$tableName = $request->getParam('table_name');
$where = $request->getParam('where');
$queryString = "select * from `$tableName`";
if (!is_null($where)) {
$queryString .= " where $where";
}
$resultSet = $dbAdapter->query(
$queryString,
DbAdapter::QUERY_MODE_EXECUTE
);
Now, I know this is obviously wide open to SQL injection - as confirmed when I ran the following:
db create fixture hit_log --where="\`timestamp\` between '2015-01-20 00:00:00' and '2015-01-30 00:00:00'; delete from hit_log limit 1";
So, what would be a good strategy to fix this?
I'm thinking of JSON notation --where='{"timestamp":["between","2015-01-20","2015-02-30"]}' - but then I'll have to write a translator to handle different tests like "=", "LIKE", and "BETWEEN".
Edit:
I've put checks in the controller action to ensure it is a console only request, and will error out if a user somehow manages to route via the http router.
This then assumes that a developer is running the command, and would have access to the database anyway. I guess this is more trying to protect against error than malice.

Shiro - Cannot authenticate using hashed passwords

I'm attempting to use Shiro for Authentication and Authorization for a JSF Web Application I'm building. Unfortunately, I'm still having some difficulty wrapping my head around how it all fits together.
I've been successful (100% using the shiro.ini file) configuring authentication back to a JDBC realm where a test set of credentials are stored. It has worked perfectly for me when credentials are stored in plaintext.
My ultimate goal is to unify an existing credential set in a MySQL database. The passwords are stored as SHA-256 salted hashes. I've spent an entire day reading over the documentation (minus Javadocs) that is available, but I'm still having some difficulty understanding exactly how to set it up.
In an attempt to implement in stages, I've modified my shiro.ini as follows with the intention of simply using SHA-256 hashes:
[main]
dataSource = org.apache.shiro.jndi.JndiObjectFactory
dataSource.resourceName = jdbc/Communicator_dev
jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.dataSource = $dataSource
dataSource.resourceRef = true;
jdbcRealm.authenticationQuery = select password from account where site_id = ?
jdbcRealm.userRolesQuery = select user_role from web_roles where site_id = ?
# From https://stackoverflow.com/questions/20742666/shiro-with-jdbc-and-hashed-passwords.
#
passwordService = org.apache.shiro.authc.credential.DefaultPasswordService
#configure the passwordService to use the settings you desire
#...
passwordMatcher = org.apache.shiro.authc.credential.PasswordMatcher
passwordMatcher.passwordService = $passwordService
#...
# Finally, set the matcher on a realm that requires password matching for account authentication:
jdbcRealm.credentialsMatcher = $passwordMatcher
The actual login logic is programmatic in a page backing bean. Here's the simple test source I'm currently using:
// Create auth token
UsernamePasswordToken token = new UsernamePasswordToken(this.siteID, this.password);
// Get the current subject
Subject currentUser = SecurityUtils.getSubject();
// Attempt to login
try {
currentUser.login(token);
} catch (AuthenticationException e) {
System.out.println("Invalid creds.");
return "";
}
return "authenticated.xhtml?faces-redirect=true";
This code works perfectly with plaintext passwords stored in my RDBMS, but now that I've hashed them, It's failing.
From my understanding of the framework, I believe the problem lies with the AuthenticationToken. I know that I need to use a different token to ultimately implement the Salted Hashes stored in my RDBMS, but I'm confused on how to proceed.
(1) I don't want to reinvent the wheel. Does Shiro have something that does this natively? I've checked out Les' links to PasswordMatcher and PasswordService (from link shiro with jdbc and hashed passwords) but this still isn't clear. Do I need to sub-classingPasswordMatcher?
(2) An architecture question: Who actually calls the doCredentialsMatch(..) method? Is it the Realm during the execution of the login(...) method?
(3) The AuthenticationInfo parameter of the doCredentialsMap(...) method .. Is that supplied by the Realm? Since Realms encapsulate the actual security data, is this an object created from, in my case, the SQL queries that return the password from the RDBMS?
Thank you very much for your time! I'm hoping to be able to contribute to the documentation when I get my head wrapped around it all.
Item 1:
I suspect you may be running into this issue involving the "salt style" parameter of the JdbcRealm which defaults to "NO_SALT". This causes hashing to work but if you're adding a salt to your password the realm will be unable to properly match them.
Here are your steps afterwards:
The default query for a COLUMN based salt style is as follows, "select password, password_salt from users where username = ?". If you cannot use that structure you need to provide a new query via your 'shiro.ini' with a similar structure.
jdbcRealm.authenticationQuery=select password, salt_column_here from users where username = ?
Here is a related question.
Item 2: Yes, the realm calls the doCredentialsMatch(..) method.
Item 3: Yes, the realm supplies the AuthenticationInfo to the doCredentialsMatch(..) method.

Wordpress / codeigniter transfer sql database password

I am on a problem which need a quick solution. I will try to explain it.
I have the table wp_user (from WordPress), where all the members have password encrypted with a wordpress encrypting function. And I have to transfer this table to a new Mysql Database on a new web site working with Codeigniter.
For new members on the new site which works under codeigniter, I use the MD5 function in order to mask password.
But the problem is that the two functions are different, so when an older user try to connect on my new web site, that doesn't work because the passwords don't match ...
So, how I can do for translate the wordpress encrpyting in a normal MD5 password?
Or maybe it's not possible?
Unfortunately you'll have to perform both checks, or just change CI to use the same hashing scheme as WP. That's probably the easier option. If you really want to start using the default CI hashing scheme, you could store both hashes and update the new hash on successful login (when you have the plaintext password).
I'm not familiar with what kind of hashing Wordpress uses for passwords, but I assume that it is secure and irreversible. The hashed passwords cannot be converted to their MD5 equivalent because hashing is a one-way algorithm.
Here is my suggestion for you:
Add a using_md5_flag boolean column to the users table in your new website with default value 0. Copy the passwords over from Wordpress into a column wppassword and also create a column called md5password When users log into the system perform the following code (assumes Datamapper ORM, convert to Active Record if you need to):
$u = new User();
$u->where('username', $this->input->post('username'))->get();
$y = new User();
$y->where('username', $this->input->post('username'));
if($u->using_md5_flag){
/*the flag is 1*/
$y->where('md5password', md5($this->input->post('password')));
$y->get();
if($y->exists()) echo "setting cookie and redirecting to logged in area";
else echo "Wrong credentials!";
}
else{
/*the flag is 0, use wordpress's hashing algorithm (not sure what this is)*/
$y->where('wppassword', wp_hashing_algo($this->input->post('password')));
$y->get();
if($y->exists()){
/*set the using_md5_flag flag so next time they log in it will ignore wp's*/
$y->using_md5_flag = 1;
/*set the new md5 password.*/
$y->md5password = md5($this->input->post('password'));
$y->save();
echo "setting cookie and redirecting to logged in area";
}
else{
echo "Wrong credentials.";
}
}
This code hasn't been tested, I wrote it inside StackOverflow's editor... but It's the method I'd take to perform slow conversion to a more secure hash. Lastly, if you're looking for a really secure hash, check out Bcrypt (phpass), it's more resistant to rainbow table attacks.
Update 1: If you need to use the Phpass library with CodeIgniter, you can find a copy I modified here (I added a constructor). Put this in libraries/Phpass.php You can use the library in your controllers using:
$this->load->library("phpass", array("iteration_count_log2" => 8, "portable_hashes" => FALSE));
$check = $this->phpass->CheckPassword($this->input->post('password'), $u->password);
if($check) /*logged in*/
else /*wrong credentials.*/
When you download the Phpass file it comes with a test.php file which demos how the functions work. I suggest reviewing it.

MySQL Security Check

Evening all,
Before i make my site live i obviously want to ensure it's secure (or as secure as possible).
I have a search form, an opportunity for a user to upload an entry to a database, and that's about it i think.
So i just want to check what i should be doing to protect things. Firstly, my database is accessed by a dedicated user account (not admin or root), so i think i've got that part locked down.
Secondly, on all my search queries i have this sort of format:
$result = mysql_query(
"SELECT *
FROM table
WHERE fieldname = '" . mysql_real_escape_string($country) . "'
AND county = '" . mysql_real_escape_string($county) . "'
ORDER BY unique_id DESC");
Finally, on the $_POST fields from my submission form, i treat the variables with this BEFORE they are inserted into the database:
$variable = mysql_real_escape_string($variable);
$result = mysql_query(
"INSERT INTO table (columnone)
VALUES ($variable)";
Could anyone let me know what else i should be considering or whether this is acceptable enough?
Thanks in advance, as always,
Dan
The code looks fine, though you should look into using PDO prepared statements if at all possible.
Beyond that, make sure that whatever account your PHP code is using to connect to MySQL has the absolute minimum in the way of permissions. Most web-facing scripts do NOT need alter/drop/create type privileges. Most can get away with only update/insert/select/delete, and maybe even less. This way, even if something goes horribly wrong with your code-level security, a malicious user can't send you a '; drop table students -- type query (re: bobby-tables.com)
Everything you show looks fine in terms of protection against SQL injection, except for
$variable = mysql_real_escape_string($variable);
$result = mysql_query(
"INSERT INTO table (columnone)
VALUES ($variable)";
this desperately needs quotes around $variable - or as #Dan points out, a check for whether it's a number - to be secure. mysql_real_escape_string sanitizes string data only - that means, any attempt to break out of a string delimited by single or double quotes. It provides no protection if the inserted value is not surrounded by quotes.
Have you considered using like MYSQL PDO and bound parameters in your SQL?
http://php.net/manual/en/pdostatement.bindparam.php
My understanding is that this is considerably more secure that using mysql_real_escape_string.