postfix-mysql regexp for partial catch-all - mysql

I just trying to make a partially catch-all email on my Postfix-mysql config.
I think have problem on the regexp.
I want to send all notify-*#domain.com to notify#domain.com
I use the following email request (letters and numbers are valid):
notify-([a-zA-Z0-9])#domain.com
But all times, Postfix tell me that User unknown in virtual mailbox table.
This is my Postfix config
virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf,
mysql:/etc/postfix/mysql_virtual_alias_maps_regexp.cf,
mysql:/etc/postfix/mysql_alias_domain_maps.cf
/etc/postfix/mysql_virtual_alias_maps_regexp.cf
user = postfixadmin
password = XXXXXXXXXXXX
hosts = 127.0.0.1
dbname = postfixadmin
query = SELECT goto FROM alias WHERE '%s' REGEXP CONCAT('^',address,'$') AND SUBSTRING(address,1,1) != '#' AND x_regexp = '1'
I think the problem is in the email regexp, due not errors in the log file, and the mysql database have the corrected values.

I'm bot sure to fully understand your issue, but if you want to select email starting with notify-, followed by any number of letters/digits, you need to use:
notify-[a-zA-Z0-9]+#domain.com
[...] is a character class, it means "one character, one that's inside the list". So you need to allow repetition with +.

Related

MySQL database responding strangely to update statement

I am using a MySQL db, when i run the below script it behaves very strangely. the current behaviour is...
if password is something normal it changes password to 0 but ignores the token value.
if the password is already 0 it just runs, doesn't do anything, and says 0 rows affected.
If someone could give me a clue as to why this is happening that would be great. My SQL is...
UPDATE travisor_tradesperson SET password='123456789' AND token = '' WHERE email='rhamilton469#qub.ac.uk'
The syntax is wrong. You separate columns in the set clause with a comma (,), not with (and):
UPDATE travisor_tradesperson
SET password = '123456789', token = ''
-- Here ---------------------^
WHERE email='rhamilton469#qub.ac.uk'
As to why does it do that, since you had the syntax wrong (as per other answer), the whole part after SET
password='123456789' AND token = ''
was probably interpreted as a single assignment of '123456789' AND token = '' into password. This was likely understood by MySQL as applying an boolean AND on a string converted to boolean and the result of the comparison token = ''.
Use commas to separate column and is an operator which for conditional statement, we can use it after where clause.
UPDATE travisor_tradesperson
SET password = '123456789', token = 'xyz'
WHERE email='rhamilton469#qub.ac.uk'

SQL Injections - Web for Pentester (Pentesterlab)

I am attending a free online course at Pentesterlab and today I am getting comfortable with SQL Injections.
However I don't get the instructions and as it could be a huge (technical) difference I would want to know how it works.
The stuff I am talking about:
https://www.pentesterlab.com/exercises/web_for_pentester/course
Please scroll down more than the half to "SQL Injections" --> "Example 1".
In the example we found out, that the (My)SQL-Table should work like this pattern:
SELECT * FROM users WHERE name='[INPUT]';
As I understand this, all I am providing through the URL is the "INPUT", the quotes (') before and after the input, and the semicolon (;) is added by SQL automatically.
However, the instruction says:
?name=root' and '1'='1: the quote in the initial query will close the
one at the end of our injection.
I don't get it. I thought the quote (') after root ends the first part, but there's still the other part '1'='1 , isn't it?
Maybe it's a misunderstanding of the language, however I am not sure if I understood it .
Imo the SQL should look like this (for example 1, first "code"):
SELECT * FROM users WHERE name=' root' and '1'='1 ';
At the second try at Example 1 it's getting stranger:
?name=root' and '1'='1' # (don't forget to encode #): the quote in the initial query will be commented out.
Wait what? I thought the quote provided by SQL automatically gets commented out.
Imo the SQL should look like this (for example 1, second "code"):
SELECT * FROM users WHERE name=' root' and '1'='1' # ';
Hope someone can clear it out, if I understand it right and it's just to hard for me explained or if I am messing up something.
Thank you guys :)
Mysql does not addanything automatically to your query. If you are not providing a single quote, then it will not be there. Period.
SELECT * FROM users WHERE name='[INPUT]';
The application will contain the above sql statement template in its own code and will substitute the parameter received from the user in place of the [INPUT] placeholder.
If you provide a single name, as you are supposed to, then the query executed will be:
SELECT * FROM users WHERE name='root';
However, if you provide root' and '1'='1 as an input, then the sql code being executed will be
SELECT * FROM users WHERE name='root' and '1'='1';
The single quote before root and after the 2nd 1 are part of the sql statement template within the application.
I haven't read the course, so let's assume the logic will check the user exists in database only.
Original SQL
SELECT * FROM users WHERE name = 'admin'
(1 row affected)
By SQL injection, you can input something after that to make this SQL always return records
by input user name as [root' and '1' = '1]
SELECT * FROM users WHERE name = 'root' and '1' = '1'
(20 rows affected)
However, let's assume this SQL will also check the password
SELECT * FROM users WHERE name = 'admin' and pwd = 'abc'
(1 row affected)
by input user name as [root' and '1' = '1]
SELECT * FROM users WHERE name = 'root' and '1' = '1' and pwd = 'invalid'
(0 row affected)
We need to bypass the password, what need to do is comment out the rest of SQL
by input user name as [root' and '1' = '1'#]
SELECT * FROM users WHERE name = 'root' and '1' = '1'#' and pwd = 'abc'
(20 rows affected)
With this SQL, it will comment out the password checking, and it will grant access even you don't have the correct user name and password

Login Server Side Logic

This question has more to do with how I am setting up my server side code for a simple login script. I'm interested in the best way to achieve my goal, which is of course to verify a users username and password against a database and present them with either a successful login, a registration page, or a username or password found, but the alternative is wrong.
Right now, I have it set up where my sql query scans the database for both the user and pass:
SELECT * FROM test WHERE userName='" + userName + "' AND pass='" + password + "'"
Problem with this approach is it either returns a true or false...I cannot tell if one of the inputs was correct and the other wasn't. It either finds the record, or it doesn't.
So I could query based on the username alone, and if found check the record for the correct password before passing the user onto a successful login. That way I know if the password is wrong, but I have no idea if the password is right and the user simply types the wrong username.
Alternatively, I could extend on that, and if the user isn't found, requery the database based on the password and determine if I can find a record but the username doesn't match. It seems like a lot of back and forth with the database, which is fine. But i'd like to hear from some experts on whether or not this is a proper approach.
I have not much idea wether stored procedure is supported in my sql or not. If it is supported then you can make SP like this way to check all cases. Below is code for MSSQL, you can check it with my sql :
IF EXISTS(SELECT [id] FROM [dbo].[users] WHERE [user_name] = #user_name AND [password] = #password)
BEGIN
SELECT 1 AS RETURNVAL --Valid User
END
ELSE IF NOT EXISTS(SELECT [id] FROM [dbo].[users] WHERE [user_name] = #user_name)
BEGIN
SELECT 0 AS RETURNVAL -- User doesn't exist
END
ELSE
BEGIN
SELECT -1 AS RETURNVAL -- Password Not Correct
END
You don't want to disclose too many information to people with bad intents trying to probe your system for available usernames (or even – god forbid – passwords that are in use).
When a login attempt failed, simply display a message stating:
Username and/or password mismatch.
As an aside, use prepared statements, rather than string concatenation when working with your database; it protects you from SQL injection attacks.
Plus – although it's not entirely clear from your code snippet – don't store plain passwords or plain password hashes. Rely on one of the many available and well tested encryption/hashing libraries e.g. PHP's crypt function (make sure you select a proper hashing function such as SHA512).
Your code in the most simplest form would then look like this:
// coming from your login page
$dbh = new PDO(…);
$sth = $dbh->prepare('SELECT `digest` FROM `users` WHERE `name` = :name LIMIT 1');
$sth->prepare(array( ':name' => $_POST['username'] ));
$result = $sth->fetch();
if($result !== FALSE && crypt($_POST['password'], $result['digest']) === $result['digest']) {
printf('You logged in successfully as %s', htmlspecialchars($_POST['username']));
} else {
echo 'Sorry, username and/or password did not match! Please try again.';
sleep(1);
exit;
}

Postfix + MySQL ENCRYPT(), How does it verify the password with randomizing salt?

I've implemented my mail server as dictated here.
It works perfectly fine. My curiousity revolves around entering users into the database and authenticating them
Running:
INSERT INTO users (email, password) VALUES ('sales#example.com', ENCRYPT('password'));
Multiple times will give a different hash for the encrypted password as its utilizing a random salt. I.e. If I enter sales#example.com three times with the same password each hash is different...
My question to this is, how is it that the Postfix server can actually authenticate the password when a user logs in via a mail client?
There isn't any problem per say as it works fine, more just to satisfy my curiosity so I can fully understand whats going on behind the scenes to properly authenticate the encrypted password.
Postfix compares the password from the database to a new encrypt done with the salt(password from db).
to encrypt:
update user set password = ENCRYPT('1234') where id = 1
to check password:
SELECT u.* FROM user u where u.email ='admin#dominio.com'
and ENCRYPT('1234', u.password) = u.password
Read man crypt: it returns the salt in the first two chars of the return value.
So the salt is not lost, you can compare the encrypted string to the result of crypt( 'pass', $first_two_chars_of_encrypted_value ).
You must use ENCRYPT('pass','salt') to force a salt, otherwise the salt is lost forever and you have no way of recovering it. Fairly pointless function without it. It's a terrible function to use, though, because the security is so minimal; use PASSWORD() or OLD_PASSWORD() instead.
ENCRYPT() uses the system crypt(), which may use all or only the first 8 characters, must be printable 7-bit ascii, generally uses 1 round of a DES-based hash, and is completely unportable. Avoid it.

problem with mysql query when password like \/'

In mysql table name (user_login) and i having field like login_name and password . I entered in login_name as abc and password as /'(Special symbols like \ / ') .And my query is
select password from user_login where password like '/'' and
I got sql syntax error
You should use parameterised queries in what ever language you are implementing the call in. Beware SQL Injection attack
you should use parameters instead of putting varibles directly into the query. i think it's aproblem with the escaping symbol.
check out this link How to set query parameters in MySQL Query Browser?
If you ever use LIKE in a login system you have thrown ALL SECURITY OUT THE WINDOW. Try this on your login to see what I mean:
Username: %
Password: %
ACCESS GRANTED FOR FIRST USER IN DATABASE. ( pray that isn't an admin user )
If the username is known then % as a password will give full access.
If you want a friendlier system that is not case sensitive ( yes this reduces the possible number of passwords - but is likely appropriate for usernames ) then force the case to lower ( or upper or ucwords or whatever you prefer ) - but DO NOT use the LIKE operator in ANY QUERY involving a login or unscreened user input ( such as search boxes ). Anytime you must use the LIKE operator BE SURE TO STRIP OUT OR MANUALLY ESCAPE % and _ (and if you're using MS SQL then escape all the REGEX operators too - []^$()*. ).
A lot of escaping functions for mysql will not escape the % _ characters, which - when used with LIKE - allows any visitor the ability to do wildcard searches ( can severely bog down the server and cause DoS issues ) and worse grant themselves undue privileges using %:% to login.