October 11, 2026
How I Broke An Invoicing App: The Story of My First CVE
Finding your first vulnerability is a rush, but turning it into a valid, impactful report is a whole different game. This is the story of…
By Udaypali
3 min read
Finding your first vulnerability is a rush, but turning it into a valid, impactful report is a whole different game. This is the story of how I discovered an authenticated SQL Injection (specifically DDL Injection) in InvoicePlane, and how a tiny dropdown menu led to total database destruction.
Finding your first vulnerability is a rush, but turning it into a valid, impactful report is a whole different game. This is the story of how I discovered an authenticated SQL Injection (specifically DDL Injection) in InvoicePlane, and how a tiny dropdown menu led to total database destruction.
The Curiosity Phase
It all started with a simple setting. I was poking around the Settings module of InvoicePlane, an open-source tool used by thousands of people to manage their money. In the "Tax" section, I noticed a small dropdown labelled tax_rate_decimal_places. It only let me choose between 2 and 3.
Most people would see a dropdown and move on. But in security, we have a rule: The frontend is a lie. Just because a website gives you a list of choices doesn't mean the server won't accept something else if you force-feed it.
Digging into the Code
I decided to see how the server handled that number. When I looked at the backend code, I found something that made my heart jump. It looked like this:
PHP
ALTER TABLE `ip_tax_rates` CHANGE `tax_rate_percent` ... DECIMAL( 5, {$settings['tax_rate_decimal_places']} )ALTER TABLE `ip_tax_rates` CHANGE `tax_rate_percent` ... DECIMAL( 5, {$settings['tax_rate_decimal_places']} )The app was taking that little number from the dropdown and plugging it directly into a command that changes the actual structure of the database. There was no validation, no double-checking, and no safety net.
The "Aha!" Moment
This wasn't just a normal SQL Injection where you steal data. This was DDL (Data Definition Language) Injection. Instead of just reading the tables, I could literally rewrite them.
I fired up Burp Suite to catch the request before it hit the server. I took that simple "2" from the dropdown and swapped it for something much more aggressive: 2) NOT NULL, DROP COLUMN tax_rate_name --
The Result: Total Chaos
When I clicked "Save," the server didn't complain. It just did exactly what I told it to do. It ran a command that said: "Change the decimal places to 2, and while you're at it, delete the column that stores the names of all the tax rates."
The result was catastrophic.
- The
tax_rate_namecolumn vanished. - The database was permanently broken.
- The entire application started throwing fatal errors and crashed.
I had achieved a Persistent Denial of Service. The only way to fix it was for a developer to go into the database manually and rebuild the table from scratch. Even though I needed admin access to do it, the fact that one single request could destroy the entire system was a huge deal.
The Lesson
Most people think SQL Injection is just for stealing passwords. This bug taught me that some injections are about destruction. By simply forgetting to turn a piece of text into a number (like using $decimal_places = (int) $input), the developers had left the keys to the kingdom under the doormat.
Final Thoughts
Technical Resources & Official Tracking
If you want to see the full exploit code, the reproduction steps, or the official status of this vulnerability, you can find them here:
- Proof of Concept (PoC) Repo: github.com/udaypali/CVE-2026–33639
- MITRE CVE Database: CVE-2026–33639
- NIST National Vulnerability Database: NVD Details
This journey from a boring settings page to a High CVE taught me to look beyond the obvious. Your first big bug might not be hidden behind a complex firewall, it might be sitting right there in a tiny dropdown menu, waiting for someone to ask, "What happens if I send something else?"