Questions about this topic? Sign up to ask in the talk tab.


From NetSec
Jump to: navigation, search
00:03:50 <hatter>	ok guys
00:03:54 <hatter>	we'll go ahead and start now
00:04:04 <hatter>	I'm going to assume everyone in here knows what an HTTP input is
00:04:19 <hatter>	For those who do not, they are GET, COOKIE, POST, and other request header parameters
00:04:26 <hatter>	We are not going to touch on those very much
00:04:39 <hatter>	If you don't understand this, the http rfc will describe it much better than I can
00:05:34 <hatter>	so - 
00:06:05 <hatter>	sql injection is classified as a format or escape sequence based vulnerability, due to formatting or type handling
00:06:26 <hatter>	However, it does actually remotely interpret SQL code
00:07:01 <hatter>	Therefore I move we refer to this as a remote code "interpretation" vulnerability triggered by a format string or escape sequence due to improper format or type handling
00:07:07 <hatter>	At any rate
00:07:15 <hatter>	Lets move onto some of the things we can do for testing
00:08:01 <hatter>	(This class also supposes that you know the basics of database navigation.  For those who don't, please see
00:08:04 <hatter>	)
00:08:25 <hatter>	THe classic type of injection is known as "where clause" injection
00:08:33 <hatter>	this is similar to
00:08:42 <hatter>	select * from table where id=?
00:08:53 <hatter>	where id is the input passed by the parameter
00:09:07 <hatter>	So, because this is an advanced session and I'd like to get the basics out of the way
00:09:20 <hatter>	suppose our url is /article.php?id=1
00:09:39 <hatter>	Yall are about to learn a hell of a lot about a sql where clause
00:10:53 *	fxm gives hatter a $_COOKIE
00:11:06 <foo>	RFC 2109 - HTTP State Management Mechanism
00:11:22 <hatter>	So
00:11:45 <hatter>	I'm going to throw out some tests that could be used to determine whether or not injection is possible
00:11:58 <hatter>	 /article.php?id=-1
00:12:02 <hatter>	 /article.php?id=1'
00:12:11 <hatter>	 /article.php?id=(3-2)
00:12:24 <hatter>	 /article.php?id=(select%0a1)
00:12:33 <hatter>	Are there any questions so far?
00:12:50 <Atlas>	Yes, what would =(3-2) and (select%0a1) return?
00:12:54 <hatter>	well
00:12:56 <Apollo>	what would the result be if it is not vulnerable?
00:12:58 <hatter>	3-2 = 1
00:12:59 <hatter>	therefore 
00:13:07 <hatter>	 3-2 would return the page as id=1
00:13:16 <hatter>	select%0a1
00:13:17 <hatter>	is actually
00:13:21 <hatter>	select\n1
00:13:33 <hatter>	\n is a valid "space" character
00:13:40 <hatter>	Any other questions?
00:14:02 <Apollo>	if injection is not possible what is returned?
00:14:29 <Apollo>	ah
00:15:21 <hatter>	If an injection is not possible
00:15:28 <hatter>	the correct page is *NOT* what get returns
00:16:01 <hatter>	If an injection is not possible
00:16:02 <hatter>	CHeck this
00:16:11 <hatter>	 /article.php?id=asidufhiawuehfiweuh
00:16:15 <hatter>	will be the same as 
00:16:25 <hatter>	 /article.php?id=(3-2)
00:16:27 <hatter>	now
00:16:43 <hatter>	Here's a trick - you can determine whether or not certain characters are sanitized
00:16:48 <hatter>	here we go - 
00:16:57 <hatter>	 /article.php?id=1
00:17:01 <hatter>	 /article.php?id=-1
00:17:07 <hatter>	the -1 may throw an error 
00:17:12 <hatter>	but not be vulnerable
00:17:15 <hatter>	does anyone know why?
00:17:35 <hatter>	-1 throws and error
00:17:38 <hatter>	so its not sanitized
00:17:43 <d4rch0n>	nothing at that index?
00:17:52 <hatter>	Well, the kicker here
00:18:01 <hatter>	is that php usually uses (int) to cast to an integer
00:18:07 <hatter>	the reason it could throw an error but not be vulnerable
00:18:13 <hatter>	is because -1 is in fact an integer
00:18:24 <hatter>	if you want to avoid this behavior doing development
00:18:29 <hatter>	just abs((int)$var)
00:18:38 <hatter>	so you get its absolute value
00:18:46 <hatter>	rather than strictly an integer, this will force a positive one
00:19:14 <Atlas>	I don't understand why it would error out
00:19:23 <hatter>	select * from table where id = -1
00:19:26 <hatter>	there is no id -1
00:19:32 <hatter>	thats why it would error out
00:20:52 <hatter>	So
00:20:54 <hatter>	moving forwards
00:21:29 <hatter>	you could do (3-2) to generate a 1 and (3-1) would give you an id of 2
00:21:53 <hatter>	so you'd be able to determine vulnerability based on 
00:22:47 <hatter>	an arithmetic test
00:22:48 <hatter>	now - 
00:22:54 <hatter>	This will work on 9/10 of your
00:22:56 <hatter>	sql backends
00:23:02 <hatter>	but there are some cases where that just won't work
00:23:08 <hatter>	for one reason or another
00:23:09 <hatter>	however
00:23:15 <hatter>	one test that is guaranteed to work
00:23:23 <hatter>	with the fewest possible syntax characters
00:23:28 <hatter>	is the between ... and ... test
00:23:59 <hatter>	many web application firewalls do not have a signature for this type of testing
00:24:11 <hatter>	 /article.php?id=1 and 2 between 1 and 5
00:24:14 <hatter>	would be true
00:24:14 <hatter>	while
00:24:20 <hatter>	 /article.php?id=1 and -2 between 1 and 5
00:24:22 <hatter>	would be false
00:24:32 <hatter>	the between ... and ... test is version independant
00:24:44 <hatter>	that is to say, it is 100% compatible with all versions of sql I've run into (that'd be a lot of them)
00:24:51 <Atlas>	Is it possible to filter out "and"?
00:24:58 <hatter>	sure
00:25:06 <hatter>	but anyone filtering out
00:25:09 <hatter>	the word "and" 
00:25:33 <hatter>	is also filtering out a bunch of other potentially legitimate traffic.
00:25:38 <d4rch0n>	would false return a 500 page? and true return the id 1?
00:26:49 <hatter>	d4rch0n: false would return likely either 500, 404, 30[12] redirect to 404
00:27:05 <hatter>	Or in some cases
00:27:09 <hatter>	it'd just be a blank page
00:27:15 <hatter>	or a page with all the layout and missing body text
00:27:54 <hatter>	essentially, missing data
00:27:57 <hatter>	now you have
00:28:06 <hatter>	4 or 5 constants we should talk about
00:28:08 <hatter>	we have "true"
00:28:14 <hatter>	we have "error"
00:28:18 <hatter>	we have "false"
00:28:22 <hatter>	we have "filtered"
00:28:25 <hatter>	and we have "404"
00:28:35 <hatter>	e.g. no data found
00:28:59 <hatter>	a lot of times its easy to confuse 404 with filtered false and error
00:29:00 <hatter>	one of those
00:29:03 <hatter>	will be constant
00:29:05 <hatter>	no matter what
00:29:14 <hatter>	e.g. false will always return the same data in some cases
00:29:16 <hatter>	or true will.
00:29:30 <hatter>	its very rare, but it can happen, that dynamic content messes up automated stuff
00:29:35 <hatter>	but any by hand inspection
00:30:33 <hatter>	should pretty much always identify the issues
00:30:45 <hatter>	now we've talked a little bit about true and false testing - 
00:31:21 <hatter>	lets talk about some more advanced stuff - moving on
00:31:27 <hatter>	suppose we've tghe following url
00:31:43 <hatter>	 /search.php?q=isearched&page=3&perpage=25
00:32:31 <hatter>	can anyone identify the clauses involved in the inputs in this url?
00:33:20 <Atlas>	Do you mean "and" and "filter"?
00:33:25 <hatter>	no
00:33:32 <Apollo>	input was isearched, formatted 25 per page, display page 3
00:33:34 <pseudo>	q,page,perpage?
00:33:38 <hatter>	i mean things lke "where" clause
00:33:55 <hatter>	which inputs get plugged into which SQL clauses?
00:34:50 <pseudo>	q: select, page: where, perpage: ?
00:35:10 <hatter>	q goes into LIKE clause
00:35:17 <hatter>	page doesn't go into any clause.
00:35:22 <hatter>	perpage goes into the limit clause
00:35:25 <hatter>	I'll explain.
00:35:31 <hatter>	In SQL we have a LIMIT and an offset
00:35:42 <hatter>	e.g. page 3 25 per page 
00:35:47 <hatter>	would be results 75 - 100
00:35:49 <hatter>	so
00:36:10 <hatter>	limit 25 offset 75
00:36:10 <hatter>	or
00:36:19 <hatter>	limit 25 offset $page*$limit
00:36:38 <hatter>	so, because that must be precalculated
00:36:47 <hatter>	the page parameter will likely never be passed directly to sql
00:36:59 <hatter>	unless sql is being used to do the math involved
00:37:11 <hatter>	e.g. select ($page * $limit)
00:37:13 <hatter>	quite bad form imo
00:37:29 <hatter>	in any case this would be something like
00:38:14 <hatter>	select * from page where thing like '%$q%' limit $perpage offset $offset
00:38:27 <hatter>	so perpage is going to be in your limit clause
00:39:13 <hatter>	because that's easily deduced, and we know limits aren't wrapped in quotes
00:39:22 <hatter>	we can test this with a simple character test
00:39:33 <hatter>	 /search.php?q=isearched&page=3&perpage=25o
00:39:46 <hatter>	this would generate an error ^ in the sql backend
00:39:52 <hatter>	however, 
00:40:22 <hatter>	you can tell easily that its casted to an integer when it still displays 25 results
00:42:25 <hatter>	you can determine the number of % in a like statement
00:42:43 <hatter>	by looking at the shortest result when searching for a % character.  You may need to urlencode this to %25
00:42:47 <hatter>	additionally, you may find that
00:42:49 <hatter>	when searching for records
00:42:56 <hatter>	%25 is a nice way to make it spill everything
00:43:13 <hatter>	if you look at the number of letters in the search results
00:43:45 <hatter>	the shortest number of characters may be 1 if there are no % characters in the like statement, 3 if you are surrounded on either side.
00:43:57 <hatter>	Usually "Begins with" searches go like 'starts with%' in sql
00:44:02 <hatter>	while ends with may look like
00:44:04 <hatter>	'%ends with'
00:44:16 <hatter>	in some cases you may get 'starts with%%ends with'
00:44:34 <hatter>	in some cases, these wildcard characters can be used for enumeration
00:44:46 <hatter>	this is pretty advanced/extreme exploitation, and usually limited in scope
00:44:48 <hatter>	but its possible.
00:45:07 <hatter>	so, last one..
00:45:19 <hatter>	say we have the following url:
00:45:53 <hatter>	   /usersview.php?category=players&sort=rank
00:46:10 <hatter>	in this particular case, it may look something like :
00:46:48 <hatter>	select * from users where category='players' order by rank desc limit 10 offset 0
00:47:20 <hatter>	This is where it gets interesting.
00:47:30 <hatter>	You've got an ORDER BY clause injection along with a where clause injection
00:47:49 <Atlas>	Sorry, "desc"?
00:47:54 <hatter>	to test for vulnerability, you can add comment notation to the end of the url to throw an error
00:48:01 <hatter>	Atlas: descending, as opposed to 'asc'
00:48:15 <hatter>	 /usersview.php?category=players&sort=rank--
00:48:18 <hatter>	would throw an error in some cases
00:48:31 <hatter>	because there is no direction defined in the order statement
00:48:32 <hatter>	additionally
00:48:38 <hatter>	you could also just add another random character there
00:48:44 <hatter>	 /usersview.php?category=players&sort=rank2387
00:48:58 <hatter>	the odds of an arbitrary sql table having a columned named such is doubtful
00:49:05 <hatter>	now, lets focus on that category input
00:49:25 <hatter>	there are 6 tests you should administer to a string
00:49:34 <hatter>	 /usersview.php?category=play'ers&sort=rank
00:49:39 <hatter>	 /usersview.php?category=play`ers&sort=rank
00:49:46 <hatter>	 /usersview.php?category=play"ers&sort=rank
00:49:53 <hatter>	 /usersview.php?category=play$$ers&sort=rank
00:50:12 <hatter>	 /usersview.php?category=play%bf'ers&sort=rank
00:50:21 <hatter>	 /usersview.php?category=play%bf"ers&sort=rank
00:50:38 <hatter>	Are there any questions at the moment?
00:50:44 <Atlas>	" ' ` $$ %bf' %bf"
00:51:13 <Atlas>	Is the injection arbitrary?
00:51:32 <d4rch0n>	would you want to sort with other guess column names to determine columns in the table?
00:51:34 <Atlas>	i.e. play ers = pla yers
00:51:46 <hatter>	d4rch0n: no
00:52:07 <hatter>	d4rch0n: only if you're on a legacy database where mysql.user etc is not possible to access
00:52:18 <hatter>	like
00:52:25 <hatter>	there are cases when that may be necessary
00:52:41 <hatter>	but most modern systems have an internal index of tables and column names
00:52:47 <hatter>	within their storage engines
00:53:49 <hatter>	if you're interested in that, check out
00:54:31 <hatter>	Next up?
00:54:52 <hatter>	Atlas: yes the injection is arbitrary
00:54:58 <hatter>	you are just trying to cause an error with those
00:55:03 <hatter>	they may not be verbose
00:55:06 <hatter>	but you'll be able to tell 
00:55:07 <hatter>	:3
00:56:44 <hatter>	at any rate
00:56:55 <hatter>	THere is one last type of injection testin for us to go over
00:57:03 <Apollo>	why would you need to test if ',`," etc produce an error, just to see if they're sanitized?
00:57:07 <hatter>	and that's full blind injection testing
00:57:12 <hatter>	Apollo: you wouldnt
00:57:20 <hatter>	Apollo: this is for if one fails, try the next.
00:58:11 <hatter>	Full blind (not partially blind) injection is usually only in logging mechanisms but can be found in other types of injection vulnerabilities
00:58:31 <hatter>	lets take our first example : 
00:58:36 <hatter>	 /article.php?id=1
00:59:13 <hatter>	in mysql, sleep() always returns null
00:59:21 <hatter>	so
00:59:22 <hatter>	you can do 
00:59:34 <hatter>	 /article.php?id=1 and sleep(30) is null
00:59:52 <hatter>	you'll get a nice
00:59:54 <hatter>	30 second page load
01:00:05 <hatter>	if the site is vulnerable
01:00:06 <hatter>	additionally
01:00:09 <hatter>	you can also do 
01:00:18 <hatter>	 /article.php?id=sleep(30)
01:00:31 <hatter>	 /article.php?id=pg_sleep(30)
01:00:35 <hatter>	(that was postgres)
01:01:00 <hatter>	 /article.php?id=1 wait for delay 00:00:30
01:01:06 <hatter>	(mssql)