My mortgage company had all of its customer documents (monthly statements, mortgage applications, etc.) easily available for public download with no login required, no automated monitoring, and trivial discoverability.
Although I write security-related software for a living, I'm not by any means a security engineer or hacker. Basic SQL injection and the crypto stuff covered in the Matasano cryptopals challenges are about the only "hacking"-type things I know how to do. That said, every once in a while there are sites that have security flaws so obvious that even I notice them. This is a story of one of those times.
Note: The events described below occurred in November 2017. I'm posting about them so long after-the-fact not due to any agreement or requirement to wait, but due to being busy and just not getting around to it until now.
27 November 2017
Because I loosely keep an eye on my finances, I wanted to check how much was left on my mortgage (answer: as always, a depressingly large amount). Easy enough. My mortgage servicer has a website. Log on, go to the documents section, grab my latest statement.
Quick aside for a bit of background info: There are three usual ways filenames get constructed when you download something from a website (and all of them are chosen by the website you're downloading from and not your browser). The first is to use some form of info about the document (e.g., "Statement-October-2017.pdf"). The second is to always have every document end up with the same name (e.g., "document.pdf"). The third is to use some random UUID, possibly but not necessarily related to the identifier used to track the document internally (e.g., "1af28f37-7f1f-4fde-be8f-8ab1d5bc0bee.pdf").
Anyway, back to me grabbing a mortgage statement. I download the most recent one, and immediately notice that the filename is unusual. Instead of being one of the three formats I mentioned above, it's something like 225123456.pdf (that isn't the exact number, but the length and the first 3 digits are the same). That may appear to a casual observer to be a random number, but when it comes to computers, that's nowhere near large enough to be a random number. The UUID I gave as an example above is a standardized format; that contains 3.4x10^38 possible values, whereas a 9-digit number gives you, well, 10^9 possibilities. That's far too small to use as a random number in this context, but it's also concerning for another reason.
In order to allay my fears that my mortgage company is grossly negligent, I download my previous statement. 224345678.pdf (again, not the exact number, but something like that).
That's not good. The company definitely appears to be numbering documents sequentially, which makes it really easy to get an estimate of how many mortgages they service. Although that isn't top-secret information, it's probably something that they don't want to be publicly known with as much detail. To make sure it isn't just random chance, I grab a third document, from a year or two back.
That's when I start to get very, very concerned. The filename is exactly what I was expecting (that is, a number somewhere less than 224345678), but more concerningly, the download link catches my attention due to its simplicity: https://[company website].com/[simple path]/?documentid=123456789
They can't possibly be as bad at this as I think they might be, so I grab my current statement's ID, decrement it by one, and load the URL https://[company website].com/[simple path]/?documentid=225123455.
It's someone else's mortgage statement for that month. This means that best case, they only perform an authentication check when you try to download a document, not an authorization check (basically, they make sure you're logged in, but not that you should actually have access to the given document). In order to see if they even check authentication, I grab the link for my statement and go to the command line.
wget 'https://[company website].com/[simple path]/?documentid=225123456' -O 'statement.pdf'
Open statement.pdf and it's the correct statement. Turns out that there's not even a requirement that the user be logged in. My browser has cookies that identify who I am, but wget doesn't have any of those, it's just an anonymous GET request, and it still worked. Is it doing some unexpectedly-fancy IP-based auth check? Hop up into the cloud, ensure I have a different IP address and a clean computer with no info whatsoever about my account. Still works.
Just to verify the severity before alerting the company (so that I know whether it's a "you really need to fix this ASAP"-level bug or if it's a "you will go out of business if you don't fix this ASAP"-level bug), I try downloading the document with ID 1. It's a letter to a customer from 2007 (if I remember correctly, it's informing them that their adjustable mortgage rate was getting adjusted). I check another random number. It's a mortgage application, with all of the personal information that entails.
Alright, no more wasting time. Delete everything I've downloaded. Send a message through their customer support portal asking for the contact info of their security team, and do the same for the contact us link of their parent company. Look up the WHOIS contact addresses for their domain and their parent company's domain, and email them, as well.
Nothing else I can do until I get a response, so I set up a cron job that, every minute, tries to download a selection of my statements without providing any auth info, and records a metric of whether or not it succeeded.
28 November 2017
Get the contact info for their security folks and let them know what's up. They confirm that it's a problem and 75 minutes after I sent them the details, the website is inaccessible with a message that it's "currently down for routine maintenance". Later that day, it's back up, using a seemingly secure method for downloading documents (I didn't dig all that deeply as I'm not actually a security engineer/hacker/whatever). All things considered, if you ignore the colossal mistake that let to it being necessary, that's a good response time.
A couple days later
Chat with their CIO. They don't officially have a bug bounty program, but I've now got a framed thank-you letter and check (mobile phone check depositing FTW) on the wall above my desk. He seemed a bit annoyed and requested that I donate the money to charity, but specifically said that he couldn't require it (obviously), and, importantly, specifically said that there weren't any restrictions on talking about the event.
They said that they identified the people whose records were accessed without auth and that it was just the handful that were part of my investigation, but I'm not sure if I believe them. Well, I'm unsure if I believe them when they say that they found everyone they think was impacted. I am fairly sure that even if they think they identified everyone impacted, they probably didn't.
I don't see any other mentions online of their massive security flaw, so it's possible nobody else noticed, but it's equally possible that roughly a quarter-billion mortgage documents are now floating around on the black market. It seems pretty safe to assume that they didn't have any automated system in place that would've detected someone exploiting this, as I had a cron job repeatedly downloading my own statements without logging in and yet they weren't aware of the issue until I informed them.
Had someone known about this and wanted to be malicious, and assuming the mortgage company's website has reasonable network capacity (which seems safe to assume given that they have hundreds of thousands of customers, and that I've never had any latency or similar issues with their website), an attacker could've downloaded every document in a couple days for a couple thousand dollars of cloud computer time and tens or hundreds of dollars of hard drive space. So, it's probably a good idea to assume that if your mortgage is managed by the company, all your info is now for sale on some Tor marketplace.
When assessing the severity of a vulnerability, one common tactic is to calculate a DREAD score. That stands for Damage, Reproducibility, Exploitability, Affected users, and Discoverability. This issue just about maxes out all of them. Let's go through it based on this arbitrarily-chosen rubric (it was the first one on Google that's applicable to this type of vulnerability).
The damage is that all of a customer's data is revealed. Mortgage statements are an issue, but mortgage applications, which were included, are catastrophic, as they contain literally all of the information necessary to steal someone's identity (by definition, they include everything you need to apply for a mortgage while pretending to be that person).
Let's say that's a 7. The most sensitive data the company has is compromised, but there's no direct ability to change things.
Until fixed, this could be reliably reproduced every time it was attempted. That's definitely a 10.
This can be easily exploited using preexisting command-line tools and scripting languages. In order to download everything it isn't literally point-and-click, but downloading everything only requires incredibly basic scripting (wget and a for loop) and downloading selected documents can be down trivially in a web browser. Let's give this a 9 as it is theoretically possible for them to make it easier.
This is a bit iffy. Generally these scores are calculated for issues in frameworks used by a number of different systems, and this refers to how many of those systems are vulnerable. However, in this case, it appears to be a problem with a company-specific stack. As 100% of the possible targets (that is, this one company) are affected, and it exposes the data of 100% of their users, I'm giving this a 10, but it might also be fair to exclude this category from the overall score calculation.
Before this was fixed, it was easily discoverable by any customer. However, it likely wouldn't have been discovered by any standard scanning tools (that look for publicly-known security issues). There wasn't public info detailing this specific attack against this specific website, but lack of auth for downloads is a commonly-known problem. Let's give this a 6, one point below "there's a published guide".
7 + 10 + 9 + 10 + 6 = 42/50. According to the rubric, "Findings with this risk rating, if not quickly addressed, may pose risks that could negatively impact business operations or business continuity." That sounds about right.
But wait, you never said what company it was. How can I know if I might be impacted?
Didn't want to distract from the story. The company is Specialized Loan Servicing, a subsidiary of Computershare.
How do I know this isn't all made up in an attempt to slander a well-respected and much-loved company?
I've got emails documenting all of this, but to protect the specific identities of the employees involved I'm not going to post them here. However, if it's necessary at any point in time for verification purposes, they're available.
 To give a mortgage-related-example of how big that is, it's roughly enough to provide a mortgage statement to every person on the planet, every microsecond, for the entire age of the universe. And then, for good measure, for the next 100000 ages of the universe, as well.
 Just comparing two adjacent-month statements won't give you a great estimate, because the order they process each one in a given month may vary, and there'll be other assorted documents mixed in, but by looking at when and how many non-statement documents are posting in your account (to figure out what fraction of documents are statements in a given month of the year), and taking a long-term average of the difference between statement filenames, you'll be able to get an estimate of both the number of mortgages they manage and how that number changes over time.
 The answer to this is obviously "of course not, you'd only bother with that after several other auth layers that you've already demonstrated are completely absent", but I felt the urge to check nonetheless.
 CIO guy, if you're reading this, I annually donate more money than I got from this, so if it makes you feel any better you can consider your check part of that for 2017.