password - Dave's Blog

Search

Application Content URI Rules wildcard syntax

2017 May 31, 4:48

Application Content URI Rules (ACUR from now on) defines the bounds of the web that make up the Microsoft Store application. Package content via the ms-appx URI scheme is automatically considered part of the app. But if you have content on the web via http or https you can use ACUR to declare to Windows that those URIs are also part of your application. When your app navigates to URIs on the web those URIs will be matched against the ACUR to determine if they are part of your app or not. The documentation for how matching is done on the wildcard URIs in the ACUR Rule elements is not very helpful on MSDN so here are some notes.

Rules

You can have up to 100 Rule XML elements per ApplicationContentUriRules element. Each has a Match attribute that can be up to 2084 characters long. The content of the Match attribute is parsed with CreateUri and when matching against URIs on the web additional wildcard processing is performed. I’ll call the URI from the ACUR Rule the rule URI and the URI we compare it to found during app navigation the navigation URI.

The rule URI is matched to a navigation URI by URI component: scheme, username, password, host, port, path, query, and fragment. If a component does not exist on the rule URI then it matches any value of that component in the navigation URI. For example, a rule URI with no fragment will match a navigation URI with no fragment, with an empty string fragment, or a fragment with any value in it.

Asterisk

Each component except the port may have up to 8 asterisks. Two asterisks in a row counts as an escape and will match 1 literal asterisk. For scheme, username, password, query and fragment the asterisk matches whatever it can within the component.

Host

For the host, if the host consists of exactly one single asterisk then it matches anything. Otherwise an asterisk in a host only matches within its domain name label. For example, http://*.example.com will match http://a.example.com/ but not http://b.a.example.com/ or http://example.com/. And http://*/ will match http://example.com, http://a.example.com/, and http://b.a.example.com/. However the Store places restrictions on submitting apps that use the http://* rule or rules with an asterisk in the second effective domain name label. For example, http://*.com is also restricted for Store submission.

Path

For the path, an asterisk matches within the path segment. For example, http://example.com/a/*/c will match http://example.com/a/b/c and http://example.com/a//c but not http://example.com/a/b/b/c or http://example.com/a/c

Additionally for the path, if the path ends with a slash then it matches any path that starts with that same path. For example, http://example.com/a/ will match http://example.com/a/b and http://example.com/a/b/c/d/e/, but not http://example.com/b/.

If the path doesn’t end with a slash then there is no suffix matching performed. For example, http://example.com/a will match only http://example.com/a and no URIs with a different path.

As a part of parsing the rule URI and the navigation URI, CreateUri will perform URI normalization and so the hostname and scheme will be made lower case (casing matters in all other parts of the URI and case sensitive comparisons will be performed), IDN normalization will be performed, ‘.’ and ‘..’ path segments will be resolved and other normalizations as described in the CreateUri documentation.

PermalinkCommentsapplication-content-uri-rules programming windows windows-store

Tweet from emily schechter

2016 Sep 8, 1:12
in Chrome 56, we'll mark HTTP pages with password or credit card form fields as "not secure". turn on HTTPS before! https://security.googleblog.com/2016/09/moving-towards-more-secure-web.html 
PermalinkComments

Tweet from David_Risney

2016 Jan 6, 10:53
Cracking passwords with neural networks https://0day.work/using-neural-networks-for-password-cracking/ …
PermalinkComments

Tweet from David_Risney

2015 Nov 11, 2:51
Hit "I forgot my password", and now staring dumbfounded at email response that contains my actual password.
PermalinkComments

Retweet of SusanArendt

2015 Jun 26, 11:32
I'm not saying I'm a genius, or anything, but I *did* remember the Netflix password, so I kinda am.
PermalinkComments

Tweet from David_Risney

2015 Apr 6, 9:21
How to decide to trust a password mgr? Have to write my own to be sure of author's intentions. But then also sure mgr will have dumb flaws.
PermalinkComments

Retweet of codinghorror

2015 Mar 26, 9:13
How Punch-Out save game passwords work, including bugs http://tomorrowcorporation.com/posts/retro-game-internals-punch-out-passwords …
PermalinkComments

The 5 Things To Do About the New Heartbleed Bug

2014 Apr 9, 9:06

Its time to get a password manager.

PermalinkCommentssecurity password technical

eclecticmethod: Hackers

2013 Apr 13, 1:57

eclecticmethod:

You don’t use the same password over and over right? Let’s be honest this is the day and age of the hacker. Eclectic Method brings you “Hackers” , Hollywood’s celebration of basement dwelling 128 bit encryption masters. They’ll shut down before you can trace them, hack into the mainframe…

Hack the planet!

PermalinkCommentshack hackers movie video mix remix mashup eclectic-method

Stripe CTF - Level 8

2012 Dec 7, 2:07
Level 8 of the Stripe CTF is a password server that returns success: true if and only if the password provided matches the password stored directly via a RESTful API and optionally indirectly via a callback URI. The solution is side channel attack like a timing attack but with ports instead of time.

(I found this in my drafts folder and had intended to post a while ago.)

Code

    def nextServerCallback(self, data):
parsed_data = json.loads(data)
# Chunk was wrong!
if not parsed_data['success']:
# Defend against timing attacks
remaining_time = self.expectedRemainingTime()
self.log_info('Going to wait %s seconds before responding' %
remaining_time)
reactor.callLater(remaining_time, self.sendResult, False)
return

self.checkNext()

Issue

The password server breaks the target password into four pieces and stores each on a different server. When a password request is sent to the main server it makes requests to the sub-servers for each part of the password request. It does this in series and if any part fails, then it stops midway through. Password requests may also be made with corresponding URI callbacks and after the server decides on the password makes an HTTP request on the provided URI callbacks saying if the password was success: true or false.
A timing attack looks at how long it took for a password to be rejected and longer times could mean a longer prefix of the password was correct allowing for a directed brute force attack. Timing attacks are prevented in this case by code on the password server that attempts to wait the same amount of time, even if the first sub-server responds with false. However, the server uses sequential outgoing port numbers shared between the requests to the sub-servers and the callback URIs. Accordingly, we can examine the port numbers on our callback URIs to direct a brute force attack.
If the password provided is totally incorrect then the password server will contact one sub-server and then your callback URI. So if you see the remote server's port number go up by two when requesting your callback URI, you know the password is totally incorrect. If by three then you know the first fourth of the password is correct and the rest is incorrect. If by four then two fourths of the password is correct. If by five then four sub-servers were contacted so you need to rely on the actual content of the callback URI request of 'success: true' or 'false' since you can't tell from the port change if the password was totally correct or not.
The trick in the real world is false positives. The port numbers are sequential over the system, so if the password server is the only thing making outgoing requests then its port numbers will also be sequential, however other things on the system can interrupt this. This means that the password server could contact three sub-servers and normally you'd see the port number increase by four, but really it could increase by four or more because of other things running on the system. To counteract this I ran in cycles: brute forcing the first fourth of the password and removing any entry that gets a two port increase and keeping all others. Eventually I could remove all but the correct first fourth of the password. And so on for the next parts of the password.
I wrote my app to brute force this in Python. This was my first time writing Python code so it is not pretty.
PermalinkCommentsbrute-force password python side-channel technical web

DSL modem hack used to infect millions with banking fraud malware | Ars Technica

2012 Oct 1, 6:33

According to the links within this article, although the root URI of the router requires authentication, the /password.cgi URI doesn’t and the resulting returned HTML contains (but does not display) the plaintext of the password, as well as an HTML FORM to modify the password that is exploitable by CSRF.

The attack… infected more than 4.5 million DSL modems… The CSRF (cross-site request forgery) vulnerability allowed attackers to use a simple script to steal passwords required to remotely log in to and control the devices. The attackers then configured the modems to use malicious domain name system servers that caused users trying to visit popular websites to instead connect to booby-trapped imposter sites.

PermalinkCommentstechnical security html router web dns csrf

PIN number analysis

2012 Sep 19, 6:03

An analysis of leaked PIN numbers.

… nearly 11% of the 3.4 million passwords are 1234 !!!

PermalinkCommentspin security technical password

Stripe CTF - Level 5

2012 Sep 11, 5:00

Level 5 of the Stripe CTF revolved around a design issue in an OpenID like protocol.

Code

    def authenticated?(body)
body =~ /[^\w]AUTHENTICATED[^\w]*$/
end

...

if authenticated?(body)
session[:auth_user] = username
session[:auth_host] = host
return "Remote server responded with: #{body}." \
" Authenticated as #{username}@#{host}!"

Issue

This level is an implementation of a federated identity protocol. You give it an endpoint URI and a username and password, it posts the username and password to the endpoint URI, and if the response is 'AUTHENTICATED' then access is allowed. It is easy to be authenticated on a server you control, but this level requires you to authenticate from the server running the level. This level only talks to stripe CTF servers so the first step is to upload a document to the level 2 server containing the text 'AUTHENTICATED' and we can now authenticate on a level 2 server. Notice that the level 5 server will dump out the content of the endpoint URI and that the regexp it uses to detect the text 'AUTHENTICATED' can match on that dump. Accordingly I uploaded an authenticated file to

https://level02-2.stripe-ctf.com/user-ajvivlehdt/uploads/authenticated
Using that as my endpoint URI means authenticating as level 2. I can then choose the following endpoint URI to authenticate as level 5.
https://level05-1.stripe-ctf.com/user-qtoyekwrod/?pingback=https%3A%2F%2Flevel02-2.stripe-ctf.com%2Fuser-ajvivlehdt%2Fuploads%2Fauthenticated&username=a&password=a
Navigating to that URI results in the level 5 server telling me I'm authenticated as level 2 and lists the text of the level 2 file 'AUTHENTICATED'. Feeding this back into the level 5 server as my endpoint URI means level 5 seeing 'AUTHENTICATED' coming back from a level 5 URI.

Notes

I didn't see any particular code review red flags, really the issue here is that the regular expression testing for 'AUTHENTICATED' is too permisive and the protocol itself doesn't do enough. The protocol requires only a set piece of common literal text to be returned which makes it easy for a server to accidentally fall into authenticating. Having the endpoint URI have to return variable text based on the input would make it much harder for a server to accidentally authenticate.

PermalinkCommentsinternet openid security stripe-ctf technical web

Stripe CTF - XSS, CSRF (Levels 4 & 6)

2012 Sep 10, 4:43

Level 4 and level 6 of the Stripe CTF had solutions around XSS.

Level 4

Code

> Registered Users 

  • <% @registered_users.each do |user| %>
    <% last_active = user[:last_active].strftime('%H:%M:%S UTC') %>
    <% if @trusts_me.include?(user[:username]) %>

  • <%= user[:username] %>
    (password: <%= user[:password] %>, last active <%= last_active %>)
  • Issue

    The level 4 web application lets you transfer karma to another user and in doing so you are also forced to expose your password to that user. The main user page displays a list of users who have transfered karma to you along with their password. The password is not HTML encoded so we can inject HTML into that user's browser. For instance, we could create an account with the following HTML as the password which will result in XSS with that HTML:

    
    
    This HTML runs script that uses jQuery to post to the transfer URI resulting in a transfer of karma from the attacked user to the attacker user, and also the attacked user's password.

    Notes

    Code review red flags in this case included lack of encoding when using user controlled content to create HTML content, storing passwords in plain text in the database, and displaying passwords generally. By design the web app shows users passwords which is a very bad idea.

    Level 6

    Code



    ...

    def self.safe_insert(table, key_values)
    key_values.each do |key, value|
    # Just in case people try to exfiltrate
    # level07-password-holder's password
    if value.kind_of?(String) &&
    (value.include?('"') || value.include?("'"))
    raise "Value has unsafe characters"
    end
    end

    conn[table].insert(key_values)
    end

    Issue

    This web app does a much better job than the level 4 app with HTML injection. They use encoding whenever creating HTML using user controlled data, however they don't use encoding when injecting JSON data into script (see post_data initialization above). This JSON data is the last five most recent messages sent on the app so we get to inject script directly. However, the system also ensures that no strings we write contains single or double quotes so we can't get out of the string in the JSON data directly. As it turns out, HTML lets you jump out of a script block using no matter where you are in script. For instance, in the middle of a value in some JSON data we can jump out of script. But we still want to run script, so we can jump right back in. So the frame so far for the message we're going to post is the following:

    
    
PermalinkCommentscsrf encoding html internet javascript percent-encoding script security stripe-ctf technical web xss

Stripe CTF - Input validation (Levels 1 & 2)

2012 Sep 6, 5:00

Stripe's web security CTF's Level 1 and level 2 of the Stripe CTF had issues with missing input validation solutions described below.

Level 1

Code

          $filename = 'secret-combination.txt';
extract($_GET);
if (isset($attempt)) {
$combination = trim(file_get_contents($filename));
if ($attempt === $combination) {

Issue

The issue here is the usage of the extract php method which extracts name value pairs from the map input parameter and creates corresponding local variables. However this code uses $_GET which contains a map of name value pairs passed in the query of the URI. The expected behavior is to get an attempt variable out, but since no input validation is done I can provide a filename variable and overwrite the value of $filename. Providing an empty string gives an empty string $combination which I can match with an empty string $attempt. So without knowing the combination I can get past the combination check.

Notes

Code review red flag in this case was the direct use of $_GET with no validation. Instead of using extract the developer could try to extract specifically the attempt variable manually without using extract.

Level 2

Code

    $dest_dir = "uploads/";
$dest = $dest_dir . basename($_FILES["dispic"]["name"]);
$src = $_FILES["dispic"]["tmp_name"];
if (move_uploaded_file($src, $dest)) {
$_SESSION["dispic_url"] = $dest;
chmod($dest, 0644);
echo "

Successfully uploaded your display picture.

";
}

Issue

This code accepts POST uploads of images but with no validation to ensure it is not an arbitrary file. And even though it uses chmod to ensure the file is not executable, things like PHP don't require a file to be executable in order to run them. Accordingly, one can upload a PHP script, then navigate to that script to run it. My PHP script dumped out the contents of the file we're interested in for this level:


Notes

Code review red flags include manual file management, chmod, and use of file and filename inputs without any kind of validation. If this code controlled the filename and ensured that the extension was one of a set of image extensions, this would solve this issue. Due to browser mime sniffing its additionally a good idea to serve a content-type that starts with "image/" for these uploads to ensure browsers treat these as images and not sniff for script or HTML.

PermalinkCommentsinput-validation php security technical

Stripe CTF - SQL injections (Levels 0 & 3)

2012 Sep 5, 9:10

Stripe's web security CTF's level 0 and level 3 had SQL injection solutions described below.

Level 0

Code

app.get('/*', function(req, res) {
var namespace = req.param('namespace');

if (namespace) {
var query = 'SELECT * FROM secrets WHERE key LIKE ? || ".%"';
db.all(query, namespace, function(err, secrets) {

Issue

There's no input validation on the namespace parameter and it is injected into the SQL query with no encoding applied. This means you can use the '%' character as the namespace which is the wildcard character matching all secrets.

Notes

Code review red flag was using strings to query the database. Additional levels made this harder to exploit by using an API with objects to construct a query rather than strings and by running a query that only returned a single row, only ran a single command, and didn't just dump out the results of the query to the caller.

Level 3

Code

@app.route('/login', methods=['POST'])
def login():
username = flask.request.form.get('username')
password = flask.request.form.get('password')

if not username:
return "Must provide username\n"

if not password:
return "Must provide password\n"

conn = sqlite3.connect(os.path.join(data_dir, 'users.db'))
cursor = conn.cursor()

query = """SELECT id, password_hash, salt FROM users
WHERE username = '{0}' LIMIT 1""".format(username)
cursor.execute(query)

res = cursor.fetchone()
if not res:
return "There's no such user {0}!\n".format(username)
user_id, password_hash, salt = res

calculated_hash = hashlib.sha256(password + salt)
if calculated_hash.hexdigest() != password_hash:
return "That's not the password for {0}!\n".format(username)

Issue

There's little input validation on username before it is used to constrcut a SQL query. There's no encoding applied when constructing the SQL query string which is used to, given a username, produce the hashed password and the associated salt. Accordingly one can make username a part of a SQL query command which ensures the original select returns nothing and provide a new SELECT via a UNION that returns some literal values for the hash and salt. For instance the following in blue is the query template and the red is the username injected SQL code:

SELECT id, password_hash, salt FROM users WHERE username = 'doesntexist' UNION SELECT id, ('5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8') AS password_hash, ('word') AS salt FROM users WHERE username = 'bob' LIMIT 1
In the above I've supplied my own salt and hash such that my salt (word) plus my password (pass) hashed produce the hash I provided above. Accordingly, by providing the above long and interesting looking username and password as 'pass' I can login as any user.

Notes

Code review red flag is again using strings to query the database. Although this level was made more difficult by using an API that returns only a single row and by using the execute method which only runs one command. I was forced to (as a SQL noob) learn the syntax of SELECT in order to figure out UNION and how to return my own literal values.

PermalinkCommentssecurity sql sql-injection technical web-security

Stripe Web Security CTF Summary

2012 Aug 30, 5:00

I was the 546th person to complete Stripe's web security CTF and again had a ton of fun applying my theoretical knowledge of web security issues to the (semi-)real world. As I went through the levels I thought about what red flags jumped out at me (or should have) that I could apply to future code reviews:

Level Issue Code Review Red Flags
0 Simple SQL injection No encoding when constructing SQL command strings. Constructing SQL command strings instead of SQL API
1 extract($_GET); No input validation.
2 Arbitrary PHP execution No input validation. Allow file uploads. File permissions modification.
3 Advanced SQL injection Constructing SQL command strings instead of SQL API.
4 HTML injection, XSS and CSRF No encoding when constructing HTML. No CSRF counter measures. Passwords stored in plain text. Password displayed on site.
5 Pingback server doesn't need to opt-in n/a - By design protocol issue.
6 Script injection and XSS No encoding while constructing script. Deny list (of dangerous characters). Passwords stored in plain text. Password displayed on site.
7 Length extension attack Custom crypto code. Constructing SQL command string instead of SQL API.
8 Side channel attack Password handling code. Timing attack mitigation too clever.

More about each level in the future.

PermalinkCommentscode-review coding csrf html internet programming script security sql stripe technical web xss

WHATWG Weekly: http+aes URL scheme, control Referer, …

2012 Mar 7, 8:08

Seems generally bad to embed sensitive info in the URI (the http+aes URI scheme’s decryption key) similar to the now deprecated password field.

Use case is covered here: http://lists.w3.org/Archives/Public/ietf-http-wg/2012JanMar/0811.html.  Also discussion including someone mentioning the issue above.

PermalinkCommentstechnical html5 html uri uri-scheme http http+aes

This is a great screenshot for IT departments to display at new...

2012 Feb 10, 8:32


This is a great screenshot for IT departments to display at new employee orientation (via FAIL Nation: Probably Bad News: loln00bs)

PermalinkCommentstechnical humor passwords

LulzSec manifesto: "We screw each other over for a jolt of satisfaction"

2011 Jun 20, 2:09"Why did the hackers at Lulz Security ("LulzSec") invade Sony Pictures websites, take down cia.gov, and release 60,000+ e-mail addresses and passwords? For the lulz, of course—but what might look lulzy to one person could certainly enrage another. In honor of its 1,000th tweet, the witty wankers of LulzSec released a manifesto of sorts, defending their actions to the angry Internets."PermalinkCommentsinternet security privacy hack technical
Older Entries Creative Commons License Some rights reserved.