How WP protects from password hijacking from random_password hook? - wordpress

I'm new to WP and looking into the source code of the wp_generate_password function is calling hook random_password.
Doesn't this introduce high-security vulnerability? What is stopping me from creating a plugin that does something useful for the user but also registers a hook that hijacks the password?
For example something like this
add_filter( 'random_password', 'my_random_password' );
function my_random_password($password) {
// send the password together with globals to my server. Global could contain the email or username of the user in which case the account is compromised.
return $password;
}

Related

Integrate API authentication to WordPress

I have a website where I have to authenticate the users registered in another system (in this case the Kayako support system).
I think I have to use the APIs to resolve this problem, but I don't really know how to get started.
Can someone please help me solve this problem? How can I send the data required for the authentication and how do I manage the response I get from Kayako.
Figure out how the API of the Kayako system looks like. In WordPress you can do something similar like this in order to authenticate the users:
// this action is executed just before the invocation of the WordPress authentication process
add_action('wp_authenticate','checkTheUserAuthentication');
function checkTheUserAuthentication() {
$username=$_POST['log'];
$password=$_POST['pwd'];
// try to log into the external service or database with username and password
$ext_auth = try2AuthenticateExternalService($username,$password);
// if external authentication was successful
if($ext_auth) {
// find a way to get the user id
$user_id = username_exists($username);
// userdata will contain all information about the user
$userdata = get_userdata($user_id);
$user = set_current_user($user_id,$username);
// this will actually make the user authenticated as soon as the cookie is in the browser
wp_set_auth_cookie($user_id);
// the wp_login action is used by a lot of plugins, just decide if you need it
do_action('wp_login',$userdata->ID);
// you can redirect the authenticated user to the "logged-in-page", define('MY_PROFILE_PAGE',1); f.e. first
header("Location:".get_page_link(MY_PROFILE_PAGE));
}
}
The try2AuthenticateExternalService() method should contain some curl-request (or similar) to the remote service.

wp_login and is_user_logged_in

I am developing an extension for a plugin and would like to run some code after every time a user logs in. Because I extend a plugin, I wanted to use the already written functions, which inside use is_user_logged_in() calls. If I register for the wp_login action and run is_user_logged_in in my action hook it returns false, which sounds really weird.
Code I was running:
add_action('wp_login', 'exhib_persist_cookies_after_login');
/*
* This method will persist the favorite posts from the cookies just after someone logs in.
*/
function exhib_persist_cookies_after_login() {
//Check if all the required functions are available
if (is_user_logged_in()) {
error_log("persist: USER LOGGED IN");
}
else {
error_log("persist: USER NOT LOGGED IN");
}
}
And in the log I see USER NOT LOGGED IN.
Anyone has a clue why is it happening? I thought is_user_logged_in is checking for the auth cookie, which is according to the doc is already set before wp_login is getting called.
Or anyone has an another idea what action should I register, which only fires once a user logged in and the is_user_logged_in returns there true?
Before you even look at why the modification isn't working, you should think about changing how you're modifying the plugin. Directly modifying a plugin is dangerous. It breaks the upgrade path preventing you from applying upgrades in the future which could resolve critical issues with the plugin itself. The same functionality could be achieved by creating a simple plugin that contains nothing but the code you want to run.

Wordpress Delete User after Success

I have a form we want users to access only once, anonymously. We hand out randomly generated usernames and passwords to allow anonymity. I would like to delete user, log off and redirect after successful submission.
I am able to delete the user with wp_delete_user($thisId); but alwyas have a "Cannot modify header information - headers already sent" error. I'm not sure how to approach this one.
I am processing in header.php
If you process in header.php it's too late because the server is already sending the page.
Try hooking your "delete_user" function in a previous action such as init or wp like this (in functions.php):
add_action('init', 'my_delete_user_process');
function my_delete_user_process(){
// Do your stuff
$user_id = get_current_user_id()
wp_delete_user($user_id);
// Do your stuff
}

Can I allow users to be logged in to symfony using a link with a secret key?

I'd like to e-mail all my users a link to a symfony site that I am writing, and have it so that when they follow that link they are logged in to the site (probably with a special role, like IS_AUTHENTICATED_REMEMBERED), and redirected to a certain page. How can I do this?
So the link would be something like:
http://example.com/?key=[some sort secret key with their account encoded in it]
i'd do something like this: generate the key with a hash function over the username.
Then send them a link to http://example.com/?user=username&hash=the-hash-result.
In the action that will recieve this url you can get the request parameter username and hash, apply the same hash funcion to the username you recived and compare the result to the hash key in the request parameters.
If match, just set the appropiate credentials to the user and log him in
Lets see some code, in your authentication class you should have a function to authenticate a user with the $user and $password parameters. Here or extending this class you can define a funciton like this:
function authenticate($user,$hash-key){
if(hashFunction($user) == $hash-key){
$user->setAuthFunction(true);//sort of
}
}
Hope it helped you!
Not so easy to implement I can tell you but you got to take a look to the UsernamePasswordFormAuthenticationListener::attemptAuthentication method...
Make your own service to atteptAuthentication automaticaly.
Inspired by this message and this code, I wrote a controller that gets the user from the database, verifies the secret key, then fakes a login token as follows:
$providerKey = 'secured_area'; // Name of firewall from security.yml - not sure this is correct.
$token = new UsernamePasswordToken($user, null, $providerKey, array('AUTO_LOGIN'));
$this->container->get('security.context')->setToken($token);
(you need this at the top of your file)
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
It seems to work, and the user has a role of AUTO_LOGIN so I can easily restrict them from accessing more sensitive stuff until they have logged in with a username and password as normal.

Drupal: customizing user registration workflow for communicating with another webapp

I'm new to Drupal6 and spent long time searching how to implement the following feature without success: I use Drupal as front-end/doc board for a web-app. I want to mirror all user account creation, update and deletion on this web-app, i.e. send user name and password.
I started coding a little module implementing hook_user (http://api.drupal.org/api/function/hook_user/6), but I am still wondering on several question concerning this hook:
1) I can't find a doc concerning the $account fields, and thus don't know how to retrieve the user name and password.
2) The insert operation informs that "The user account is being added". Is that triggered when the user query an account or when his/her pending account creation has been approved?
3) User management on the 'slave' webapp is done through a URL interface. I only know the header("Location: http://webapp/users/add?user=martin&pwd=bla") PHP primitive, but I fear this will make a redirection, instead of just hiting the target page and continue code flow. Any suggestion?
Maybe some of you already programmed such a module, or would have links for more documentation?
Thanks in advance,
Martin
Taking a step back and looking at the big picture, you have several options.
Use OpenID (there's a core Drupal module for it) for both sites
Use LDAP (there's a really good Drupal contrib module for it)
Look at other modules offer user login sharing with other apps (such as http://drupal.org/project/phpbb or http://drupal.org/project/moodle or many others) for inspiration
Have your web app use Drupal's user table. This is relatively easy as the username is there in plaintext and the password is just MD5'ed (so no salts or anything to muddy up the waters).
Basically, hook_user is wrong. What you need to do is use hook_form_alter to change the '#validate' parameter of the login form. That way, the validate is passed to your function in your module where you are getting $form_values['username'] and $form_values['password']. You pass that on to your URL via curl. If it returns correctly, return nothing. If it doesn't return, use form_set_error and it will deny the login.
Good luck!
In order to just retrieve a response from a page, you can use drupal_http_request()
And a general security note, make sure you're authenticating and validating the requests between applications. Passing passwords in plain text via GET parameters over HTTP also makes me a little queasy, but I don't know your application set up.
Here is the final piece of code that works. Note that the password is retrieved md5ified, so the slave webapp must be able to do so as well:
function mirror_registration_user($op, &$edit, &$account, $category = NULL) {
$cmd = 'http://www.example.com/register?name='.$account->name.'&pass='.$account->pass;
if($op == 'insert'){
$cmd .= '&op=insert';
drupal_http_request( $cmd );
}
else if($op == 'delete'){
$cmd .= '&op=delete';
drupal_http_request( $cmd );
}
else if($op == 'after_update'){ // 'update' is a "before update event"
$cmd .= '&op=update';
drupal_http_request( $cmd );
}
}
Remark: in our case, registration requires admin approval. In this case, there's an 'update' event. The 'insert' event is triggered as soon as the user queries an account.
Informations for other newbies:
When trying to debug the code, one can echo $cmd to have the content of $cmd writen on top left of the following page.
If you write crapy php code and get a blank page when using the hook, you may add to Drupal/index.php the following calls: error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE); that allow having debug info.

Resources