Using Zend_Mail_Transport_Smtp with an MD5-Hashed value as password - zend-framework

I'd like to offer the users ob my web-application the possibility to send out emails using our smtp-server.
The password for the user accounts are md5-hased and the smtp-server is hashing the received values to check for the right username-password kobination.
Now i'm looking for a good way to set up Zend_Mail_Transport_Smtp - I obviously need the plain-text password and forward it to the smtp-server which then converts it to a md5-hash.
But that means that i have to store the users password somewhere in plaintext, which i'd like to avoid.
Are there any best practices on how to set up an webmailer using the zend framework?
The only idea i had was to save the unhashed password in a session (the user accounts in my application are linked with the mail server accounts), but there has to be a better way to handle this situation

What you can do is to store the password in a encoded format in the database and decode it in your application when you need it. Unfortunately MD5 is just a hashing function and you cannot decode to the plain password. I know three ways to accomplish this:
Substitute letters:
You can use something like ROT13 to replace letters in your plain password:
// store this in the database
$pw_rot = str_rot13( "plain_password" );
// use this in the application
$pw_plain = str_rot13( "cynva_cnffjbeq" );
I wouldn't recommend to use str_rot13() or something like this, because is easily guessed by someone who sees the password.
Decode/encode without a key:
Another way is to decode/encode the password with a function, which doesn't need a key like Base64:
// store this in the database
$pw_base64 = base64_encode( "plain_password" );
// use this in the application
$pw_plain = base64_encode( "cGxhaW5fcGFzc3dvcmQ=" );
A little bit better then the above, but I would use that only for testing purposes, because it's easily implemented and to use.
Decode/encode with a key:
A better way is to use key and a symmetric block cipher like Blowfish:
class Password {
const KEY = 'your_secret_key_for_the_cipher';
// encode the plain text with key for storing in the database
public function encode( $plain_text ) {
// set up the environment
$td = mcrypt_module_open( MCRYPT_BLOWFISH, '', MCRYPT_MODE_ECB, '' );
$key = substr( self::KEY, 0, mcrypt_enc_get_key_size( $td ) );
$iv_size = mcrypt_enc_get_iv_size( $td );
$iv = mcrypt_create_iv( $iv_size, MCRYPT_RAND );
if( mcrypt_generic_init( $td, $key, $iv ) != -1 ) {
$cipher_text = mcrypt_generic( $td, $plain_text );
// clean up the mcrypt enviroment
mcrypt_generic_deinit( $td );
mcrypt_module_close( $td );
}
// use hex value
return bin2hex( $cipher_text );
}
// decode the stored cipher text with key to use in the application
public function decode( $cipher_text ) {
// set up the environment
$td = mcrypt_module_open( MCRYPT_BLOWFISH, '', MCRYPT_MODE_ECB, '' );
$key = substr( self::KEY, 0, mcrypt_enc_get_key_size( $td ) );
$iv_size = mcrypt_enc_get_iv_size( $td );
$iv = mcrypt_create_iv( $iv_size, MCRYPT_RAND );
if( mcrypt_generic_init( $td, $key, $iv ) != -1 ) {
$plain_text = mdecrypt_generic( $td, pack( "H*" , $cipher_text ) );
// clean up the mcrypt environment
mcrypt_generic_deinit( $td );
mcrypt_module_close( $td );
}
// remove NUL which maybe added by padding the plain_text
return rtrim( $plain_text, "\0" );
}
With this way only someone who has access to the database and the source code can decode the password. On the down side you have a more complex application and little bit performance impact. Also you can other symmetric block cipher.
And the most important: Never store plain passwords.

Related

Determining the hash type I am working with for use in hashcat

I am trying to crack some hashed information because the passcode was lost to us. I have the hashed information in the database, and the code that was used to encrypt it. It goes through cryptastic which appears to use rijndael-256 and pbkdf2, as far as my ignorant self can tell:
public function encrypt($msg, $k, $base64 = false)
{
# open cipher module (do not change cipher/mode)
if (!$td = mcrypt_module_open('rijndael-256', '', 'ctr', ''))
return false;
$msg = serialize($msg); # serialize
$iv = mcrypt_create_iv(32, MCRYPT_RAND); # create iv
if (mcrypt_generic_init($td, $k, $iv) !== 0) # initialize buffers
return false;
$msg = mcrypt_generic($td, $msg); # encrypt
$msg = $iv . $msg; # prepend iv
$mac = $this->pbkdf2($msg, $k, 1000, 32, 'sha256'); # create mac
$msg .= $mac; # append mac
mcrypt_generic_deinit($td); # clear buffers
mcrypt_module_close($td); # close cipher module
if ($base64)
$msg = base64_encode($msg);# base64 encode?
return $msg; # return iv+ciphertext+mac
}
And in the end looks like this: wWTWLPvXT9YRz2Zj+Og0EwTTSEiZGdjAQ1TRhycJA9jusjQ2mTpptw3hSM1XJ9yPw+4XvsvFASe08AbLr3BT0LFnvGsYPrq87yI= (I know this to be a 3 digit number if that helps at all)
So I am trying to use hashcat to recover our information and I am not certain I am using the correct hash-type. I am checking this page here: https://hashcat.net/wiki/doku.php?id=example_hashes and searching for 'pbkdf2' and looking at all the hits.
The best match as far as I can tell is 9200/Cisco-IOS $8$ (PBKDF2-SHA256) except that that seems to have a header of $8$, and none of my information has any headers at all, and no $ characters. Everything else with PBKDF2 in it doesn't seem to be a match either so I find myself kind of lost before I've even gotten started.
I also noticed my hashed info always had == on the end, but only for the longer information being encrypted, in the list Juniper IVE seems to fit that format but the name doesn't match anything I can see in cryptastic.
I'm mostly ready to go aside from this as far as I can tell, I have my custom rules set up since I know how we create the initial passcodes and the hashes are in a file to be read, it's just this hash-type selection that is blocking me.
Any help appreciated!

Codeigniter 3 get a specific session data by id

Codeigniter 3 session table looks like the following
CREATE TABLE IF NOT EXISTS `ci_sessions` (
`id` varchar(40) NOT NULL,
`ip_address` varchar(45) NOT NULL,
`timestamp` int(10) unsigned DEFAULT 0 NOT NULL,
`data` blob NOT NULL,
KEY `ci_sessions_timestamp` (`timestamp`)
);
I can access my current session by
$this->session
But If I'd like to access a specific session how would I do that.
I can get the session like
$this->db->where('id', 'db256c0b82f8b6ba1e857d807ea613792817157a');
$res = $this->db->get('ci_sessions');
echo $res->row()->data;
I get the following
__ci_last_regenerate|i:1450694483;email|s:18:"amzadfof#gmail.com";user_code|s:7:"AAA1787";loginInId|i:8;users_id|s:11:"00000000002";active|s:1:"1";username|s:13:"amzadmojumder";fname|s:5:"Amzad";lname|s:8:"Mojumder";phone|s:11:"07900642131";title|s:1:"#";created_on|s:19:"2015-12-17 16:31:56";last_login|s:19:"0000-00-00 00:00:00";in_group|s:15:"2,1,3,4,5,6,7,8";
How could I convert this to an php object or array? I have tried to
unserialize($res->row()->data);
Also tried
session_decode($res->row()->data);
none of this worked. Any help will be appreciated.
Old question, yeah but this worked for me.
https://github.com/wikimedia/php-session-serializer
After fetching the session data from database, I just did
$array = PhpSessionSerializer::decode($session);
Firstly, the CodeIgniter sessions table should look a bit more like this:
CREATE TABLE IF NOT EXISTS `ci_sessions` (
session_id varchar(40) DEFAULT '0' NOT NULL,
ip_address varchar(45) DEFAULT '0' NOT NULL,
user_agent varchar(120) NOT NULL,
last_activity int(10) unsigned DEFAULT 0 NOT NULL,
user_data text NOT NULL,
PRIMARY KEY (session_id),
KEY `last_activity_idx` (`last_activity`)
);
You'll also need to edit your config.php to ensure the following are set properly for CI Sessions to use a table for storage
$config['sess_use_database'] = TRUE;
$config['sess_table_name'] = 'ci_sessions';
The other issue you'll face is that you aren't really using sessions how they're supposed to be used. If you want to mimic sessions of another individual through an admin switch or something like that, you're probably best off creating a new session and duplicating the information in your table. If you actually assume the session, you risk breaking it or letting it expire while another user is accessing it. So I would write your own parsing function to duplicate a specific session in the database, like so:
Your session data is broken up like this in your dB:
__ci_last_regenerate|i:1450694483;
email|s:18:"amzadfof#gmail.com";
user_code|s:7:"AAA1787";
loginInId|i:8;
users_id|s:11:"00000000002";
active|s:1:"1";
username|s:13:"amzadmojumder";
fname|s:5:"Amzad";
lname|s:8:"Mojumder";
phone|s:11:"07900642131";
title|s:1:"#";
created_on|s:19:"2015-12-17 16:31:56";
last_login|s:19:"0000-00-00 00:00:00";
in_group|s:15:"2,1,3,4,5,6,7,8";
The basic architecture is as such:
{session_key}|{information type s=string, i=int}:{length}:"{value}";
So we can grab it from the database and parse through it
<?php
duplicateSession( $id_to_duplicate ) {
// Kill any current sessions we're in to prevent conflicts
$this->session->sess_destroy();
// Get the Session we want to duplicate
$this->db->where( 'id', $id_to_duplicate );
$session = $this->db->get( 'ci_sessions' );
$data = $session->row()->data;
// Turn our data into an array so we can parse through it
$data_arr = explode( ';', $data );
// Loop through each of our items to parse it out
foreach( $data_arr as $session_key ) {
// Explode out to separate our key name from our values
$session_key_arr = explode( '|', $session_key );
$key_index = $session_key_arr[0];
// Explode out to parse our values
$session_value_arr = explode( ':', $session_key_arr[1] );
$key_value = $session_value_arr[2];
// Build our new session index
$this->session->set_userdata( $key_index, $key_value );
}
}
?>
I have solved this problem by creating helper function to update session from existing session id.
Reference : https://forum.codeigniter.com/thread-61330-post-322814.html#pid322814
function updateSession( $session_id='' ) {
$ci =& get_instance();
// Kill any current sessions we're in to prevent conflicts
$ci->session->sess_destroy();
// Get the Session we want to duplicate
$ci->db->where( 'id', $session_id );
$session = $ci->db->get( 'ci_sessions' );
$row = $session->row();
if($row){
$session_db_data = $row->data;
$session_data = array(); // array where you put your "BLOB" resolved data
$offset = 0;
while ($offset < strlen($session_db_data))
{
if (!strstr(substr($session_db_data, $offset), "|"))
{
throw new Exception("invalid data, remaining: " . substr($session_db_data, $offset));
}
$pos = strpos($session_db_data, "|", $offset);
$num = $pos - $offset;
$varname = substr($session_db_data, $offset, $num);
$offset += $num + 1;
$data = unserialize(substr($session_db_data, $offset));
$session_data[$varname] = $data;
$offset += strlen(serialize($data));
}
$ci->session->set_userdata($session_data);
}
}

Fetch all user information with Net::LDAP

Currently have an small perl script what for the given username fetch his email address from the ActiveDirectory using Net::LDAP.
The search part is the following:
my $user = "myuser";
my $mesg = $ldap->search(
base => "dc=some,dc=example,dc=com",
filter => '(&(sAMAccountName=' . $user . ')(mail=*))', #?!?
);
for my $entry ($mesg->entries) {
my $val = $entry->get_value('mail');
say "==$val==";
}
Working ok.
How i should modify the above statement to fetch all available information for the given user myuser? I'm looking to get an perl-ish data structure, such something like next:
my $alldata = search(... all info for the given $user ... );
say Dumper $alldata; #hashref with all stored informations for the $user
It is probably dead simple - but i'm an total AD & LDAP-dumb person...
Edit: When I dump out the $msg->entries (what is an LADP::Entry object) got something, but i'm not sure than it contains everything or only the part of the stored data...
I've done something similar, and I use this to query LDAP:
my $ldapResponse = $ldap->search(base => $base, filter => $filter, attrs => $attrs);
And then this to parse it:
if ($ldapResponse && $ldapResponse->count()) {
$ldapResponse->code && die $ldapResponse->error;
my %domainNames = %{$ldapResponse->as_struct};
foreach my $domainName (keys %domainNames) {
my %ldapResponse;
my %dnHash = %{$domainNames{$domainName}};
foreach my $attr (sort(keys %dnHash)) {
# Note that the value for each key of %dnHash is an array,
# so join it together into a string.
my $value = join(" ", #{$dnHash{$attr}});
$ldapResponse{$attr} = $value;
}
// Dump/use %ldapResponse
}
}
I've never tried to use the ldap->entries in your code, but the above works for me!
I explicitly specify a(long) list of attributes ($attr), but perhaps that's optional as your example shows, and you can get ALL LDAP fields by just skipping that arg to search().

Use in-memory file as argument in SFTP

I need to open an SFTP connection in Perl and I need to use a dsa key file but I can't actually store the file on the hard disk for security reasons. I am trying to use Net::SFTP.
my $sftp = Net::SFTP->new(
$host, user=>"$userid",
ssh_args => {
identity_files => [ $pathToInMemoryKeyFile ]
}
);
I think I know how to get a string represented as an in memory file handle but I don't know how to get the path of that file handle such that I can pass it in as one of the ssh_args. Does anybody have any suggestions?
Thanks!
I've looked through the various options of doing SFTP (Net::SFTP hasn't been updated since 2005, Net::SFTP::Foreign is more up to date) and they all do key authentication via a file.
Net::SFTP is backed by Net::SSH::Perl which is a pure Perl SSH implementation. You can do some patching to make it do what you want. I'm going to sketch it out for you.
Patch or put a wrapper around Net::SSH::Perl::Auth::PublicKey->authenticate to look for a new configuration key. Let's call it identity_keys.
sub authenticate {
my $auth = shift;
my $ssh = $auth->{ssh};
my $sent = 0;
if (my $agent = $auth->mgr->agent) {
do {
$sent = $auth->_auth_agent;
} until $sent || $agent->num_left <= 0;
}
return $sent if $sent;
##### This is the new bit which tries any keys passed in. ######
my $ik = $ssh->config->get('identity_keys') || [];
for my $key (#$ik) {
return 1 if $auth->_auth_key($key);
}
my $if = $ssh->config->get('identity_files') || [];
my $idx = $auth->{_identity_idx} || 0;
for my $f (#$if[$idx..$#$if]) {
$auth->{_identity_idx}++;
return 1 if $auth->_auth_identity($f);
}
}
auth_key would be a copy of _auth_identity but calling Net::SSH::Perl::Key->read_private_key which would be the guts of Net::SSH::Perl::Key->read_private_pem minus opening and reading the key from a file. read_private_pem would then be gutted to use read_private_key.
Alternatively, use an ssh-agent. It holds the decrypted private key in memory, so you can immediately wipe it from the disk.

Anti Sql injection Library C# Asp.NET

Can anyone suggest such library for Asp.NET 1.1 ?
Thanks.
There are many to choose from, but in all honesty, your best tool is education. Knowing how to prevent it yourself. The tools built into the normal Framework class library are perfectly adequate if used properly.
Simply using parameterized queries and/or stored procedures for every database call is your best prevention.
However, that said, we do use the Microsoft.Practices.EnterpriseLibrary.Data classes provided with the Microsoft Patterns and Practices library. The ones we use are a bit outdated, but still do the job nicely. They provide some injection protection and also simplify data access. But they are not the only, nor necessarily best tool for the job.
More up-to-date information about the current Patterns and Practices library can be found here.
Link to Anti-Injection SQL
<?PHP
FUNCTION anti_injection( $user, $pass ) {
// We'll first get rid of any special characters using a simple regex statement.
// After that, we'll get rid of any SQL command words using a string replacment.
$banlist = ARRAY (
"insert", "select", "update", "delete", "distinct", "having", "truncate", "replace",
"handler", "like", " as ", "or ", "procedure", "limit", "order by", "group by", "asc", "desc"
);
// ---------------------------------------------
IF ( EREGI ( "[a-zA-Z0-9]+", $user ) ) {
$user = TRIM ( STR_REPLACE ( $banlist, '', STRTOLOWER ( $user ) ) );
} ELSE {
$user = NULL;
}
// ---------------------------------------------
// Now to make sure the given password is an alphanumerical string
// devoid of any special characters. strtolower() is being used
// because unfortunately, str_ireplace() only works with PHP5.
IF ( EREGI ( "[a-zA-Z0-9]+", $pass ) ) {
$pass = TRIM ( STR_REPLACE ( $banlist, '', STRTOLOWER ( $pass ) ) );
} ELSE {
$pass = NULL;
}
// ---------------------------------------------
// Now to make an array so we can dump these variables into the SQL query.
// If either user or pass is NULL (because of inclusion of illegal characters),
// the whole script will stop dead in its tracks.
$array = ARRAY ( 'user' => $user, 'pass' => $pass );
// ---------------------------------------------
IF ( IN_ARRAY ( NULL, $array ) ) {
DIE ( 'Invalid use of login and/or password. Please use a normal method.' );
} ELSE {
RETURN $array;
}
}
[1]: http://psoug.org/snippet/PHP-Anti-SQL-Injection-Function_18.htm
[1]: http://psoug.org/snippet/PHP-Anti-SQL-Injection-Function_18.htm