I kept all logs from visitors with mySQL. Where it from URL and which URL visit. I found this one.
myweb.com/read.php?id=2349 and(SeLeCt 1 FrOm(SeLeCt count(*),CoNcAt((SeLeCt(SeLeCt UnHeX(HeX(CoNcAt(char(33,126,33),0x4142433134355a5136324457514146504f4959434644,char(33,126,33))))) FrOm information_schema.TaBlEs LiMiT 0,1),floor(rand(0)*2))x FrOm information_schema.TaBlEs GrOuP By x)a) and 1=1&aid=3&bid=18
What does it means ? and What is it doing with my website ?
A simple SQL-Injection attempt. Do the following things:
check your webserver and application configuration if you are vulnarable to this kind of attempt. (e.g. your application parses the SQL and it is executed using your database, that would be bad)
Fix your configuration
Check if this attempt caused any harm.
At least the attacker now knows, that you own this system, because you published this very specific value here.
SeLeCt
UnHeX(
HeX(
CoNcAt(
char(33,126,33)
,0x414...4644
,char(33,126,33)
)
)
);
Will return something like
!~!ABC145...!~!
Is this in the combination with the rest of the statement an issue on your database?
Related
I was solving one of TryHackMe's rooms about SQL injection.But I couldn't figured out one thing that came to my mind and after spending lots of time I thought it's best to ask that question here. In the room there is a machine to deploy, after deployed machine it gave me an interface(webapp) that takes inputs from me like so :
And if you give it a value like test. It returns following output:
When I saw it, I thought it was an easy SQLi question so I tried most basic SQLi payloads for common dbms like so:
' ; sleep(1) --
' or 1=1 -- ...
But none of them worked and returned me an error message like that:
After that failure, I run sqlmap and it found 2 types of SQLi payload with following payloads:
Then I realized that in time based SQLi, sqlmap used ||. Then I tried to send '|| (select sleep(2)) -- . And it worked. Now my question is why my first payload(' ; select sleep(2) -- ) didn't work, but this one worked ?
By default, MySQL query interfaces do not support multiple queries separated by semicolon. To get that, the application would have to explicitly request this feature to be enabled when it connects to the database. There's a connect option for that.
So by default, any type of SQL injection that works by trying to append a malicious query after a semicolon doesn't work.
But an SQL injection that works by modifying an expression in the single query can still work.
I am creating a php page with a small and simple database.
when I visit it online and try to pass the parameter "length" in the url like: index.php/?length=1 it works fine and fetches the data.
If I add the single quote like index.php/?length=1' I have no SQL error on the page...
but if I use index.php/?length=-1 I see the SQL error in my page.
Does this mean that my page is vulnerable?
How can I further test it and fix the problem?
Edit: added the code
$length = $wpdb->get_results( $wpdb->prepare("SELECT `title`, `website`, `material`, `color`, `width`, `height`, `group`, `category`, `numbers_positive`, `numbers_negative`, `custom` FROM {$wpdb->shirts} WHERE `id` = '%d' ORDER BY `rank` ASC, `id` ASC", intval($shirt_id)) );
if (!isset($shirt[0])) return false;
$shirt= $shirt[0];
$shirt->title = htmlspecialchars(stripslashes($shirt->title), ENT_QUOTES);
$shirt->custom = maybe_unserialize($shirt->custom);
$shirt->color = maybe_unserialize($shirt->color);
if ( $this->hasBridge() ) {
global $lmBridge;
$shirt->shirtColor = $lmBridge->getShirtColor($shirt->color);
}
$shirt = (object)array_merge((array)$shirt,(array)$shirt->custom);
unset($shirt->custom);
return $shirt;
Yes, from the URL examples you have given, it seems like you take user input and directly insert it into your MySQL statement. That is the absolute worst. You should always parse user input because direct input from a user can result in the string being escaped and them deleting every table in your DB. This is a great example: Bobby Tables
Also, this is been a topic of great discussion. There is a great answer here
Edit* Using the WordPress framework and looking at your code, its not as bad as it seemed.
accepting, but generating an error on -1 does not nessicarily mean you are suseptable to an injection attack. As long as you are varifying that the input is an integer and only using the integer compontent, you're fairly safe.
Prepared statements make it even more secure, by seperating the data from the query. Doing that means someone can never 'break out' of what you are supposed to be working on. It's absolutely the right way to use SQL.
We can even take it another step farther, by limiting the abilty of the account to do anything other that run stored queries, and storing your queries on the SQL server side, rather then in your PHP. At that point, even IF they broke out (which they can't), they would only be able to access those defined queries.
I'm using Cakephp 3 using sqlserver as datasource server. I am sure there's no problem with my database connection.. as home.ctp prompts that I am connected to my database.. and I'm as well using migrations plugin to create my tables.. it seems like there is no problem working with these tools. but after I bake my MVC, I only got page full of errors..
for example
$bin\cake bake all tests
there are no errors I found and MVC are in its specific folder, testController.php, testTable, etc.
and in browsers
localhost:8765\tests
but all I got is page of different errors.. Im seeing
Error: SQLSTATE[42000]: [Microsoft][SQL Server Native Client 11.0][SQL Server]Incorrect syntax near the keyword 'desc'.
SELECT * FROM (SELECT Tests.id AS [Tests__id], Tests.desc AS [Tests__desc], (ROW_NUMBER() OVER (ORDER BY (SELECT NULL))) AS [_cake_page_rownum_] FROM tests Tests) _cake_paging_ WHERE _cake_paging_._cake_page_rownum_ <= :c0
and more errors on the left side.
I assume this is because of controllers with wrong queries or queries generated by bake is for mysql only. I just wanna know how to deal with this. is there a setting I forgot to do? please advice. I am new to Cakephp, and English is not my native language, sorry if I can't explain my question properly. thanks in advance.
As already mentioned by Vishal Gajjar in the comments, you are using the reserved keyword desc for your column name, hence the error, it's not bakes fault, it's yours.
In order to be able to use such reserved words, the column name needs to be quoted properly, however CakePHP 3 doesn't auto-quote by default anymore, as it's an expensive operation.
If you insist on using reserved words, enable identifier quoting via the quoteIdentifiers option in your app.php config, or enable it manually using the autoQuoting() (enableAutoQuoting() as of CakePHP 3.4) method of the DB driver.
See also
Cookbook > Database Access & ORM > Database Basics > Identifier Quoting
Cookbook > 3.x Migration Guide > New ORM Upgrade Guide > Identifier Quoting Disabled by Default
API > \Cake\Database\Driver::autoQuoting()
API > \Cake\Database\Driver::enableAutoQuoting()
You can use this code before problematic query:
$this->Tests->connection()->driver()->autoQuoting(true);
and when you are finished you can turn auto quoting off:
$this->Tests->connection()->driver()->autoQuoting(false);
So bad performance would be only on problematic query.
Use this :
SELECT * FROM (SELECT Tests.id AS [Tests__id], Tests.[desc] AS [Tests__desc],
(ROW_NUMBER() OVER (ORDER BY (SELECT NULL))) AS [_cake_page_rownum_] FROM tests Tests) _cake_paging_
WHERE _cake_paging_._cake_page_rownum_ <= :c0
If you do use a keyword, use it in square braces [ ]
I am working on a big project with a lot of forms using BDE and ODBC to connect to MySQL Database.
I can compile it in Delphi 2009 and it works fine.
When i compile it in Delphi 2010, nothing works because TQuery can not pass parameter values correctly.
Here is an example :
txtUsername.Text = 'Admin';
Query1.Close;
Query1.SQL.Text = 'Select Count(*) From Tbl_User where Username = :username';
Query1.ParamByName('username').AsString = txtUsername.Text;
Query.Open();
The SQL will be sent to MySQL , looks like this :
Select Count(*) From Tbl_User where Username = 'A'
Only first character of parameter will be sent to the server : 'A' instead of 'Admin'
But if i use
Query1.ParamByName('username').AsAnsiString , then
it will works fine and parameter will be sent completely:
Select Count(*) From Tbl_User where Username = 'Admin'
There are huge number of TQuery and TTable in project and its not possible to change all calls of AsString to AsAnsiString.
Is there any solution for this? any settings to make it working fine? probably by making it to use Ansi as default instead of Unicode?
I tried finding some setting in compiling option, and changing ODBC parameters but none of them worked.
Any help would be appreciated.
Thanks
I understand the pressure for quick and cheap solutions, but sometimes they will be quick and cheap only at the first moment, and then will turn (in a near future) into a monster problem with no solution at all.
So, for the first move, I recomend you to read a post on Regex Replace. Use this to replace all your .AsString by .AsAnsiString and quickly get you application running as expected again.
But donĀ“t get too comfortable with this, you have a long term work ahead of you. My suggestion to give your application a better design is:
Remove your datasets from your forms and put them in a DataModule, so you will not mix persistence and business code with presentation code;
Stop working with specific dataset on your business code, go for TClientDataset, which is better than any other dataset and will give you a better application design and complete database and middleware independence;
Create a new database layer, putting all the database and middleware specifics behind an interface, what will give you a incredible level of database abstraction.
This is a time consuming work, of course, so, not a quick and certainly not a cheap solution, but it will give you a lot of insights and improve your techniques. During the process, your application will evolve as never before.
We have a lot of queries
select * from tbl_message
that get stuck on the state "Writing to net". The table has 98k rows.
The thing is... we aren't even executing any query like that from our application, so I guess the question is:
What might be generating the query?
...and why does it get stuck on the state "writing to net"
I feel stupid asking this question, but I'm 99,99% sure that our application is not executing a query like that to our database... we are however executing a couple of querys to that table using WHERE statement:
SELECT Count(*) as StrCount FROM tbl_message WHERE m_to=1960412 AND m_restid=948
SELECT Count(m_id) AS NrUnreadMail FROM tbl_message WHERE m_to=2019422 AND m_restid=440 AND m_read=1
SELECT * FROM tbl_message WHERE m_to=2036390 AND m_restid=994 ORDER BY m_id DESC
I have searched our application several times for select * from tbl_message but haven't found anything... But still our query-log on our mysql server is full of Select * from tbl_message queries
Since applications don't magically generate queries as they like, I think that it's rather likely that there's a misstake somewhere in your application that's causing this. Here's a few suggestions that you can use to track it down. I'm guessing that your using PHP, since your using MySQL, so I'll use that for my examples.
Try adding comments in front of all your queries in the application, like this:
$sqlSelect = "/* file.php, class::method() */";
$sqlSelect .= "SELECT * FROM foo ";
$sqlSelect .= "WHERE criteria";
The comment will show up in your query log. If you're using some kind database api wrapper, you could potentially add these messages automatically:
function query($sql)
{
$backtrace = debug_backtrace();
// The function that executed the query
$prev = $backtrace[1];
$newSql = sprintf("/* %s */ ", $prev["function"]);
$newSql .= $sql;
mysql_query($newSql) or handle_error();
}
In case you're not using a wrapper, but rather executing the queries directly, you could use the runkit extension and the function runkit_function_rename to rename mysql_query (or whatever you're using) and intercept the queries.
There are (at least) two data retrieval modes for mysql. With the c api you either call mysql_store_result() or mysql_use_result().
mysql_store_result() returns when all result data is transferred from the MySQL server to your process' memory, i.e. no data has to be transferred for further calls to mysql_fetch_row().
However, by using mysql_use_result() each record has to be fetched individually if and when mysql_fetch_row() is called. If your application does some computing that takes longer than the time period specified in net_write_timeout between two calls to mysql_fetch_row() the MySQL server considers your connection to be timed out.
Temporarily enable the query log by putting
log=
into your my.cnf file, restart mysql and watch the query log for those mystery queries (you don't have to give the log a name, it'll assume one from the host value).