I am not understanding the sql syntax problems I'm getting while launching an injection attack, so any help explaining them is much appreciated. I have a target php login script that takes a username/password combo and then very simply runs.
Select * FROM users WHERE username='$username' AND password='$password'
When i supply the basic
$username = ' OR '1=1
$password = ' OR '1=1
the system logs me in as admin because it evaluates to
Select * FROM users WHERE username='' OR '1=1' AND password='' OR '1=1'
and gets a match for the first user entry in the database (admin). Now I'm trying to get the script to log me in as an arbitrary user named adrian. My thought was to supply
$username = adrian
$password = ' OR (1=1 AND username='adrian') --
which I thought would evaluate to
Select * FROM users WHERE username='adrian' AND password='' OR (1=1 AND username='adrian') -- '
I thought the boolean order of operations was left to right when no parentheses are included:
Select * FROM users WHERE [[[username='adrian'] AND password=''] OR (1=1 AND username='adrian')] -- '
but this is not logging me in as anyone (and giving me no errors). Even if AND's are evaluated last, this statement would evaluate to
Select * FROM users WHERE [username='adrian'] AND [password='' OR (1=1 AND username='adrian')]
Which would still be true for the user adrian. Meanwhile
$username = adrian
$password = 'or(1=1 and username='adrian') --
is logging me in as adrian properly, which evaluates to
Select * FROM users WHERE username='adrian' AND password=''or(1=1 AND username='adrian') -- '
So why does my approach with "OR" not work while my approach with 'or' does work?
SOLVED: Thank you for the guidance. I understand sql better now, but my real problem was that autofill was removing spaces after the "--" I must've messed up the first time and then foolishly relied on autofill from then on out
The order of operations is not only left to right. In fact left to right (or positional precedence) is the very last thing considered when evaluating an expression like this. You have to understand operator precedence as well, as this is most important aspect in determining behavior of such a statement. In this case AND has higher precedence than OR.
That means your statement would behave as follows:
Select * FROM users WHERE (username='adrian' AND password='') OR (1=1 AND username='adrian')
So, you would get a row returned as long as there was a user named adrian.
Check out the MySQL documentation on operator precendence - https://dev.mysql.com/doc/refman/5.6/en/operator-precedence.html
Related
OWASP Juice Shop:
SELECT * FROM Users WHERE email = '' AND password = '' AND deletedAt IS NULL
Payload:
' OR 1=1;--
OWASP Mutillidae II:
SELECT * FROM accounts WHERE username='' AND password=''
Payload:
' OR 1=1 --
I really don't understand. There is not much of a difference in commands, but Juice Shop payload won't work in Mutillidae. It works Vice Versa.
Furthermore in Mutillidae, we have to enter payload in both username and password fields (same payload), however in JuiceShop entering random thing in Password would work.
Someone please explain WHY?
Please I really need to understand this concept before moving on.
I posted this as a comment but was the answer - so posting below
It is possible that you need a space at the end. I've read that some database comments require a whitespace after the comment indicators, whereas some others don't e.g., ' OR 1=1;-- may not work on all, but ' OR 1=1;-- should work. I'd usually put a whitespace before the -- as well, but probably isn't necessary.
im reading book is about " SQL-injection " so i defaced a title
"Incorrectly Handled Query Assembly" what does this mean? and can you give me a example code ? Thanks.
I think you might have understood SQL injection. Incorrectly Handled Query Assembly seems to mean incorrect construction of query string.
Think of a simple scenario where you have written a query to list the whole details of the (logged in) user. Let us
String part1="SELECT * FROM TRANSACTIONS WHERE TAG=' ";
part2=" ' AND ID=' ";
part3=" ';";
//Constructing query with user inputted tag and user ID
String query=part1+ user_entered_tag + part2 + user_id + part3;
//This is an unsafe construction of query.
If the user enters tag like this:
Abc' OR '2'='2' OR '1'='1
The query will become like this:
SELECT * FROM TRANSACTIONS WHERE TAG='Abc' OR '2'='2' OR '1'='1' AND ID='544678';
If the query is then executed, all the transactions will be fetched.
Thus unauthorized person will have access to data. This happens because a loophole is left in the construction of query. The developer should avoid such injection by adding type checking or using built-in features like prepared statements .
I'm currently working on Yii SQL Injection. I have the following command sql command to run:
SELECT p.email, p.email_secret, p.verificationcode, r.name
FROM personal p
JOIN profile r
ON p.email='example#example.com'
I have written the following code with yii:
$connection=Yii::app()->db;
$command=$connection->createCommand();
$command->select('p.email, p.email_secret, p.verificationcode, r.name');
$command->from('personal p');
$command->join('profile r', 'p.email = r.email');
$command->where('p.email=:email', array(':email'=>'yeoh.chan1#gmail.com'));
$rows=$command->queryAll();
I would like to know where this would be vulnerable SQL Injection and if so, what would be a better approach to deal with table joinings.
Since this has no variables in it, there is no possibility for SQL injection. However, I am guessing that you are planning to pass the email address in as a parameter, and since you have the :email parameter marker you are safe.
Just a tidbit here, you don't have to repeat $command-> on every line. You can write it like this:
$connection=Yii::app()->db;
$command=$connection->createCommand();
$command->select('p.email, p.email_secret, p.verificationcode, r.name')
->from('personal p')
->join('profile r', 'p.email = r.email')
->where('p.email=:email', array(':email'=>'yeoh.chan1#gmail.com'));
$rows=$command->queryAll();
This works because all the statement clauses (except distinct) return the command object, and can be strung together. If you need distinct, you can make ->setDistinct() the last item in the chain.
I have this site with the following parameters:
http://www.example.com.com/pagination.php?page=4&order=comment_time&sc=desc
I use the values of each of the parameters as a value in a SQL query.
I am trying to test my application and ultimately hack my own application for learning purposes.
I'm trying to inject this statement:
http://www.example.com.com/pagination.php?page=4&order=comment_time&sc=desc' or 1=1 --
But It fails, and MySQL says this:
Warning: mysql_fetch_assoc() expects parameter 1 to be resource,
boolean given in /home/dir/public_html/pagination.php on line 132
Is my application completely free from SQL injection, or is it still possible?
EDIT: Is it possible for me to find a valid sql injection statement to input into one of the parameters of the URL?
The application secured from sql injection never produces invalid queries.
So obviously you still have some issues.
Well-written application for any input produces valid and expected output.
That's completely vulnerable, and the fact that you can cause a syntax error proves it.
There is no function to escape column names or order by directions. Those functions do not exist because it is bad style to expose the DB logic directly in the URL, because it makes the URLs dependent on changes to your database logic.
I'd suggest something like an array mapping the "order" parameter values to column names:
$order_cols = array(
'time' => 'comment_time',
'popular' => 'comment_score',
... and so on ...
);
if (!isset($order_cols[$_GET['order'])) {
$_GET['order'] = 'time';
}
$order = $order_cols[$_GET['order']];
Restrict "sc" manually:
if ($_GET['sc'] == 'asc' || $_GET['sc'] == 'desc') {
$order .= ' ' . $_GET['sc'];
} else {
$order .= ' desc';
}
Then you're guaranteed safe to append that to the query, and the URL is not tied to the DB implementation.
I'm not 100% certain, but I'd say it still seems vulnerable to me -- the fact that it's accepting the single-quote (') as a delimiter and then generating an error off the subsequent injected code says to me that it's passing things it shouldn't on to MySQL.
Any data that could possibly be taken from somewhere other than your application itself should go through mysql_real_escape_string() first. This way the whole ' or 1=1 part gets passed as a value to MySQL... unless you're passing "sc" straight through for the sort order, such as
$sql = "SELECT * FROM foo WHERE page='{$_REQUEST['page']}' ORDER BY data {$_REQUEST['sc']}";
... which you also shouldn't be doing. Try something along these lines:
$page = mysql_real_escape_string($_REQUEST['page']);
if ($_REQUEST['sc'] == "desc")
$sortorder = "DESC";
else
$sortorder = "ASC";
$sql = "SELECT * FROM foo WHERE page='{$page}' ORDER BY data {$sortorder}";
I still couldn't say it's TOTALLY injection-proof, but it's definitely more robust.
I am assuming that your generated query does something like
select <some number of fields>
from <some table>
where sc=desc
order by comment_time
Now, if I were to attack the order by statement instead of the WHERE, I might be able to get some results... Imagine I added the following
comment_time; select top 5 * from sysobjects
the query being returned to your front end would be the top 5 rows from sysobjects, rather than the query you try to generated (depending a lot on the front end)...
It really depends on how PHP validates those arguments. If MySQL is giving you a warning, it means that a hacker already passes through your first line of defence, which is your PHP script.
Use if(!preg_match('/^regex_pattern$/', $your_input)) to filter all your inputs before passing them to MySQL.
I have a weird problem, when i use the query on phpmyadmin, it works. but when i use using a php script it returns an error.
Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in
I tried to troubleshoot and discovered that the problem lies with the set statement.
this is my example code.
$sql = 'set #rank=0; select * from user;';
Please help somebody.
First Run
$sql = set #rank=0;
it will store value of rank
then run:
select * from user;
In sort you need to run both queries separately .
set statement stores values. that can be used by next executing query,
like code below :
$sql ="SET #id:=0";
$Executives=$DB->exec($sql);
$sql = "SELECT #id:=#id+1 as id,pes.* FROM profile_executive_summary as pes where profile_id=".$pid;
$Executives=$DB->fetchAssoc($sql);
See what mysql_error returns after you run mysql_query('...'). That might help. In general, mysql_query only permits one query. You can't separate them by newlines or semicolons. mysqli will do it for you though.