Questions about this topic? Sign up to ask in the talk tab.
Classes/Logs/2012/September/18/00-01
From NetSec
Revision as of 02:55, 18 September 2012 by Chantal21I (Talk | contribs) (moved Classes/Logs/2012/September 18 00-01 to Classes/Logs/2012/September/18/00-01)
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 http://blackhatlibrary.net/SQL_orientation 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 https://www.ietf.org/rfc/rfc2109.txt 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 http://blackhatlibrary.net/SQL_injection/Target_Environments/Mapping 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)