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
Related
In a shortcode I can limit wp_query results by custom field values.
Example:
[my-shortcode meta_key=my-custom-field meta_value=100,200 meta_compare='IN']
And obviously it's possible to use multiple custom fields in a wp_query like WP_Query#Custom_Field_Parameters
But how can I use multiple custom fields in my shortcode? At the moment I do pass all the shortcode parameters with $atts.
On of a few different solutions might be to use a JSON encoded format for the meta values. Note that this isn't exactly user-friendly, but certainly would accomplish what you want.
You would of course need to generate the json encoded values first and ensure they are in the proper format. One way of doing that is just using PHP's built in functions:
// Set up your array of values, then json_encode them with PHP
$values = array(
array('key' => 'my_key',
'value' => 'my_value',
'operator' => 'IN'
),
array('key' => 'other_key',
'value' => 'other_value',
)
);
echo json_encode($values);
// outputs: [{"key":"my_key","value":"my_value","operator":"IN"},{"key":"other_key","value":"other_value"}]
Example usage in the shortcode:
[my-shortcode meta='[{"key":"my_key","value":"my_value","operator":"IN"},{"key":"other_key","value":"other_value"}]']
Which then you would parse out in your shortcode function, something like so:
function my_shortcode($atts ) {
$meta = $atts['meta'];
// decode it "quietly" so no errors thrown
$meta = #json_decode( $meta );
// check if $meta set in case it wasn't set or json encoded proper
if ( $meta && is_array( $meta ) ) {
foreach($meta AS $m) {
$key = $m->key;
$value = $m->value;
$op = ( ! empty($m->operator) ) ? $m->operator : '';
// put key, value, op into your meta query here....
}
}
}
Alternate Method
Another method would be to cause your shortcode to accept an arbitrary number of them, with matching numerical indexes, like so:
[my-shortcode meta-key1="my_key" meta-value1="my_value" meta-op1="IN
meta-key2="other_key" meta-value2="other_value"]
Then, in your shortcode function, "watch" for these values and glue them up yourself:
function my_shortcode( $atts ) {
foreach( $atts AS $name => $value ) {
if ( stripos($name, 'meta-key') === 0 ) {
$id = str_ireplace('meta-key', '', $name);
$key = $value;
$value = (isset($atts['meta-value' . $id])) ? $atts['meta-value' . $id] : '';
$op = (isset($atts['meta-op' . $id])) ? $atts['meta-op' . $id] : '';
// use $key, $value, and $op as needed in your meta query
}
}
}
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);
}
}
I tried to emulate this SQL in DBIx::Class against the update_or_new function.
UPDATE user SET lastseen = GREATEST( lastseen, ?::timestamp ) WHERE userid = ?
It gives an error on inflate column saying it is unable to invoke is_infinity on undef .
$schema->resultset('user')->update_or_new( {
userid => 'peter',
lastseen => \[ 'GREATEST( lastseen, ?::timestamp )', DateTime->from_epoch(epoch => 1234) ]
} );
I guess this is because the InflateColumn::DataTime does not expect a function there. Is there any clean workaround for this issue?
This is a bug in DBIx::Class ( addressed here: https://github.com/dbsrgits/dbix-class/pull/44 ) and the fix is merged. It should be fine on the next release.
That said, if you're using DBIx::Class <= 0.08270...
You're using update_or_new, but the function only makes sense if the row exists already:
GREATEST( lastseen, ?::timestamp ) lastseen is undefined if the row doesn't exist yet.
I read through the source+docs a bunch and cannot find a way to sidestep the InflateColumn code and still have bind values. You can pass in literal SQL with a scalar ref ( \'NOW()' ) but not an array ref.
Your best bet would be to use the ResultSet's update method instead, which does not 'process/deflate any of the values passed in. This is unlike the corresponding "update" in DBIx::Class::Row.'
my $dtf = $schema->storage->datetime_parser; #https://metacpan.org/pod/DBIx::Class::Storage::DBI#datetime_parser
my $user_rs = $schema->resultset('User')->search({ userid => 'peter' });
my $dt = DateTime->from_epoch(epoch => 1234);
#select count(*) where userid = 'peter';
if( $user_rs->count ) {
$user_rs->update(
lastseen => \[ 'GREATEST( lastseen, ? )', $dtf->format_datetime($dt) ]
);
} else {
$user_rs->create({ lastseen => $dt });
}
I am trying to make a simple Rose DB call:
$id = xyz;
$name = "company";
DataB::testTable::Manager->get_testTable( query =>[ id => $id, name => $name ] );
in it possible to not have the whole query written every time, and declare it like a string variable such that i can just call
DataB::testTable::Manager->get_testTable( query =>[ $query ] );
where $query = qq { id => $id , name => $name };
Please Help
By what I understood from your question, I am giving this answer.
Try this one.
my $myquery = {query =>{ id=>$id, name=>$name }} ;
TGI::testTable::Manager->get_testTable($myquery);
Hope, this gives some idea to you.
Edit for "Hash with Array reference":
my $myquery = [ id=>$id, name=>$name ] ;
TGI::testTable::Manager->get_testTable(query => $myquery);
check out this : How to pass a a string variable as "query" for get Manager call?
Well actually i figured out how to do that . Its not that complicated. Only thing is RoseDB objects expect an array reference for a query. So something like this works :
my #query = ( id => $id, name => $name );
testDB::testTable::Manager->get_testTable( query => \#query );
Just thought would answer it myself, incase someonelse is looking for a solution to this
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.