Discovering who owns John Deere tractors, harvesters, and implements. What farm they are at. How old they are. And how long they are “subscribed” for.
Willie Cade: https://twitter.com/WillieCade7
https://sick.codes/sick-2021-012/ (site-specific, no CVE)
https://sick.codes/sick-2021-031/ (site-specific, no CVE)
A few months ago, I got the idea from a colleague to start looking for vulnerabilities in John Deere products.
He told me that John Deere devices are able to send and receive files to “devices” out in the field via the website.
And what I mean by “devices” is actually million dollar machinery that automates farming through GPS auto-steer and things like that.
As a security researcher, this seemed like an awesome attack vector to start looking at, with the intention of obviously reporting the vulnerabilities to John Deere, if I found any.
So I signed up with a free developer account, as most good and bad hackers would do.
At that time I did not know the difference between a combine harvester and a tractor. They were all tractors to me.
Limitless Username Look-ups
I left the account for a few weeks, to do some other paid work, and when I came back to try find a vulnerability or two, I had forgotten whether or not I created an account.
As I started typing, the API was making username look-ups every time I typed a letter on the signup page.
Seemed out of the ordinary that a username lookup would check every time you enter a letter!
Usually when things are out of the ordinary, that means I’m getting warmer.
I copied the request as a cURL and began removing the cookies one by one until the request failed.
To my surprise, the API worked without any cookies!
This indicated to me that I could potentially submit any number of usernames.
Moreover, uppercase and lowercase were treated as the same, so for a neat Proof of Concept I submitted the Fortune 1000 companies.
I looked on GitHub for something like a big CSV or TSV of the Fortune 500.
Then found this which worked perfectly: https://github.com/dmarcelinobr/Datasets/
Specifically, this file: https://raw.githubusercontent.com/dmarcelinobr/Datasets/master/Fortune1000.csv
A list of big companies that would be likely to have John Deere accounts.
And here is the Proof of Concept.
I submitted the 1000 queries in just over a minute or two, and then checked the results.
192 out of 1000 of the companies returned “This username is already taken” response.
This surprised me.
- I was able to submit 1000 username look-ups completely unauthenticated.
- Almost 20% of the companies had accounts!
The first issue was discovered within just a few minutes of me returning back to security research on the JD portal.
I immediately prepared a report to submitted to the specified email in their terms of service.
The report was submitted on 2021-03-25 and I requested a CVE at the same time.
Probably shouldn’t have submitted the CVE as it was subsequently rejected since the website didn’t have any version numbers or anything and it’s a site-specific vulnerability. Before I submit a CVE, I usually look for similar CVE’s in different products, just to be sure it would fit the bill.
Secondly, I submittted a request on their disclosure form.
Since I was using a developer account, I followed the rules at the very bottom of their Terms and Conditions: https://developer.deere.com/
Funnily as I write this today, that terms page is now gone.
I archived a cache here for transparency. These are the terms I was acting under:
Also here they are verbatim, given there was no Vulnerability Disclosure Program (VDP):
Exhibit A API Security Standards Licensee will comply with the following API security standards ("Security Standards"): 1. Security Precautions: Best Practices. Licensee agrees to adhere at all times to the security practices described in the security publications promulgated by The United States Computer Emergency Readiness Team ("US-CERT"). As of the date of this Agreement, such publications may be found at http://www.us-cert.gov/security-publications. 2. Security Audits 2.1. Audit after a Security Breach Incident. For purposes of these Security Standards, a "Security Breach" is defined as a breach of security of Licensee's Application, facility, systems or site where Deere Content has been accessed or acquired by an unauthorized person. In the event of a Security Breach, Deere may suspend or terminate Licensee's access to the Deere API and/or Licensed Materials and Deere Content and Deere may conduct a security audit. 2.2. Audit Results. Deere will provide Licensee with the results of any security audit performed by Deere pursuant to these Security Standards. 3. Security Incidents and Response 3.1. Notification and Timing. Notwithstanding any other legal obligations Licensee may have, Licensee agrees to immediately notify Deere in writing upon Licensee's discovery of a Security Breach or of any transmission defined in Section 4.1.(f) of the Agreement. Licensee agrees to notify Deere of Licensee's detection of a Security Breach or of any transmission defined in Section 4.1.(f) of the Agreement no more than twenty-four (24) hours after its detection. 3.2. Notification Format . Licensee's notification of a Security Breach in accordance with the requirements set forth above will take the form of an email to apisupport at johndeere.com. Such notification email will include: a problem statement, expected resolution time (if known), and the name and phone number of Licensee's representative that Deere can contact to obtain incident updates.
While looking around though, I ended up finding this on Google: https://www.deere.com/en/forms/corporate/it-security-consulting/
Given the URL was
corporate/it-security-consulting it didn’t really stand out at first as the right form.
So I submitted the request to Global Security Request in markdown format as I couldn’t upload any files.
And I also emailed a copy report to apisupport@, which didn’t exactly look like a security orientated email address.
I’m not the judge or jury, but I did exactly what I was told to do.
About 4 days later, I thought I might chase up the report, just in-case neither the email or the form was received.
Seeing they had an active Twitter account, I decided to privately DM them on Twitter.
This was their response:
Hey there! Can you share the report with us at SocialMedia at JohnDeere.com and we'll ensure it's shared with our internal teams? Thanks,
Usually sending vulnerabilities to the Social Media team is not ideal, but again, I am giving them the benefit of the doubt, so I politely asked for the Security Team’s contact details.
Do you have a more secure destination? It’s not appropriate to send security vulnerabilities to a group email
The Twitter account told me to check my email. And the email said to submit the research via their HackerOne.
This is where things get awkward.
They didn’t have HackerOne, it was Disclosure Assistance page, so I CC’ed in HackerOne who confirmed they did not have a program at the time.
They did not have a private or public program.
The next day, April 1st, the Engineering Manager – Cyber Security Operations replied to my earlier form request and asked that I send the report again. I obliged.
John Deere has a massive software component. And I had only scratched the login page!
The actual software portal is massive. Lots of agriculture software integrations. But I needed to know what I was looking at. I wanted to see how they interact with the actual tractors, and other “implements”.
At this stage, I needed to find someone who knew a lot about tractors. This would help me skip the learning curve because I literally knew nothing.
That’s when I found this article: https://www.theamericanconservative.com/articles/nothing-breaks-down-like-a-deere/
I reached out to the Author, Willie Cade.
This video started to make sense: https://www.youtube.com/watch?v=EPYy_g8NzmI
Secondly, I wanted to find this mysterious “Ukrainian Software” that apparently farmers have been running.
He suggested I get in contact with one of the guys in the Vice video about hacking tractors.
That’s when I met Kevin Kenney, an engineer. Here’s Kevin on video: https://www.youtube.com/watch?v=vD9SXZOfmbQ. He blew my mind about how computerized these tractors, combines and harvesters really were.
Since you could upload files to and from the vehicles, I started playing with generic stored XSS attempting to get the page to load the XSS.
The system comes preloaded with sample data. So I downloaded sample ZIP, modified it, and re-uploaded it to the portal.
This was not successful. I usually don’t look for XSS, but I’m sure someone else could get it to work.
These files can also be sent over the air to the actual tractor.
I don’t have a tractor, so I asked Willie and Kevin if they could get me access to one to poke around at.
This led me to the John Deere Operations Center.
I submitted the first VIN number to the API that I could think of:
The response was a JSON of 5,800 character in length.
This is apparently a potato planter implement.
And it’s not even a John Deere piece of equipment. It’s made by https://www.alamo-industrial.com/.
Why would a VIN lookup return other brands?
Because the Operation Center seemed to be a SAAS more than just a John Deere IFTTT thing.
It returned a lot of info about my own developer account, but a bit too much about the hardware/implement itself.
"isSupplier": false, "sharedOrg": null, "type": "CUSTOMER", "userId": "sickcodes", "isDealer": false, "actingOrgType": "CUSTOMER", "isCustomer": true, "userDbId": XXXXXXXXXXXX, "appBar": true,
I submitted a few more VINs.
This was yet another company called Terex which makes construction equipment.
I needed a John Deere VIN.
It didn’t take long to find a JD VIN online.
I found an 8235R tractor and submitted the model number as the VIN:
At the time of research, I showed me it was made by John Deere. Now it doesn’t show John Deere.
This is because the vulnerability I am about to disclose seems to have locked it down quite a lot.
As of time of writing, only non-John Deere VIN information appears.
New Harvester, Who Dis?
As there was almost no PII in the early tests (this changes dramatically! requests, I began brainstorming with Willie & Kevin.
We ended up finding another place to add equipment.
They are submitted on https://terminals.deere.com/.
The page looks very similar to the other equipment page.
I looked up an old tractor.
The response was different to the other request, which was intriguing.
And then it struck me.
I was looking up ancient tractors. I was submitting almost 30 year old equipment to the API.
Which models would have lots of electronics and telemetry?
I needed to be looking up the newest models…
The model I ended up investigating was the S770 Combine 2020 model Combine Harvester.
Willie & Kevin said these probably retail for over $1,000,000.
I couldn’t find any on eBay so I went to the first Tractor auction site that I could find and picked up a bunch of VIN numbers for that exact model and submitted requests…
This time the response was smaller, however I could see:
jq '.. | keys?'
[ "categoryClass", "mtm-definition", "terminals" ] [ 0 ] [ "equipmentMake", "equipmentModel", "equipmentType", "id", "name", "owningOrganization", "vin" ] [ "@type", "ERID", "certified", "id", "name" ] [ "@type", "GUID", "category", "certified", "id", "marketSegment", "name" ] [ "@type", "GUID", "certified", "classification", "id", "name" ] [ "@type", "id", "member" ] [ 0 ] [ "associatedMachine", "dateReceived", "disablePingKey", "features", "hardwareType", "id", "isFromPartner", "isRestricted", "orgFeatures", "owningOrganization", "permissions", "productPackages", "registrationStatus", "serialNumber", "type" ] [ "declaredType", "globalScope", "name", "nil", "scope", "typeSubstituted", "value" ] [ "accountId", "accountKey", "addresses", "farms", "id", "includesMachineData", "intendedUse", "internal", "legalName", "links", "member", "name", "notifyToOrgAdmins", "organizationController", "organizationPreferences", "partnerships", "status", "timeZone", "type" ]  [ 0 ] [ "@type", "addressElement", "country", "formattedLine" ] [ 0, 1, 2, 3 ] [ "@type", "elementClass", "elementValue" ] [ "@type", "elementClass", "elementValue" ] [ "@type", "elementClass", "elementValue" ] [ "@type", "elementClass", "elementValue" ] [ 0, 1, 2 ]  [ 0 ] [ "@type", "displayName", "expirationDate", "serialNumber", "startDate", "state", "type" ] [ "GUID", "categoryClass", "categoryName", "defaultColors", "equipmentType", "id", "machineName", "make", "makeId", "model", "modelId", "pin", "primaryColor", "secondaryColor", "stripeColor", "telematicsState", "type", "visualizationCategory" ]  [ "JDLINK_FBM", "REMOVE_TYPE_FILTER", "REMOVE_USER_ADDRESS", "SUPPORT_TOOLS", "TERMINALS_ADD_EQUIPMENT_ENHANCEMENTS", "TERMINALS_ALLOW_CUSTOMER_TO_CUSTOMER_TRANSFER", "TERMINALS_CHECK_TRANSFER_ORG_RESTRICTED_STATUS", "TERMINAL_REQUEST_SYSTEM", "TERMINAL_RESPONSIBLE_DEALER", "TRS_SUPPORT_TOOLS" ] [ "JDLINK_FBM", "REMOVE_TYPE_FILTER", "REMOVE_USER_ADDRESS", "SUPPORT_TOOLS", "TERMINALS_ADD_EQUIPMENT_ENHANCEMENTS", "TERMINALS_ALLOW_CUSTOMER_TO_CUSTOMER_TRANSFER", "TERMINALS_CHECK_TRANSFER_ORG_RESTRICTED_STATUS", "TERMINAL_REQUEST_SYSTEM", "TERMINAL_RESPONSIBLE_DEALER", "TRS_SUPPORT_TOOLS" ]
These also all expanded. You can see a fully redacted example in the advisory for that vulnerability.
So at this stage, I was quite surprised. I could see who owned the equipment, what address it was entered into the Operations Manager as, the name of the tractor that the owner had used, when the subscription started, and when it finished.
However, one of the other researchers mentioned this might be only the dealer’s information.
So I tested more, to validate my results.
I Googled one of the results, and yes, it was a real farm. Not a dealership.
At this stage, I knew what needed to be done. I immediately reported the issue to JD.
Here is the email to John Deere:
[HIGHLY SENSITIVE EMAIL CONTENTS CONTAINS PII RETURNED TO VENDOR] Hi [REDACTED], Your email filter is preventing me from sending more reports, attached is the report only, please fix your email attachment filter so I can return the PII as discussed below Attached is an extremely serious vulnerability report discovered in the last <24 hours by myself and another researcher. Please handle with absolute care as this vulnerability allowed me to see the owner of any VIN number on the Terminal section of the Operations Manager. I have attached a copy of ZIP of all of the data that I obtained while conducting good-faith ethical research, including the combine VINs I downloaded off the public website TractorHouse. This is not a breach, it is research. My account is a developer account and account username is sickcodes. All of the IP addresses during good faith research used will be in my account login history, or they should be around [REDACTED].[REDACTED].[REDACTED].* and the ISP is [REDACTED]. I am following all the required guidelines of US-CERT, your developer agreement, and Computer Crime & Intellectual Property Section of the Cybersecurity Unit PDF which I also attached: (2) Directing that sensitive information be viewed only to the extent required to identify a vulnerability and that it not be retained; or Myself and two other individuals who validated the research with me have viewed this data. One other independent researcher has validated this vulnerability. 3 people have seen the attached PDF. Again, I would not consider this a breach. This is genuine validated security research that I am conducting in Good Faith. Once you have confirmed receipt of the report, all copies of the sensitive information obtained will be immediately deleted off my disk and redacted from SICK-2021-031.pdf. For both of our sake, can you please get a Vulnerability Disclosure terms posted on the website: https://github.com/disclose/dioterms I have not yet requested a CVE, but I believe the best course of action would be highly responsible and co-ordinated public disclosure. Here are my previous CVE's for example: https://github.com/sickcodes/security/tree/master/advisories Once again, stating that I am a strictly ethical hacker conducting independent security researcher. I have absolutely no intentions other than conducting safe independent security research. I am adhering strictly to the developer agreement below guidelines of my developer account at https://developer.deere.com/content/home/landing/newClickThrough.htm?version=1 As requested in your Exhibit A: - Research was conducted less than 24 hours ago. - Problem statement is attached in PDF - Expected resolution time: your team could fix the permissions of the terminal "Add Equipment" API in a matter of minutes - Sick Codes is my name - I do not retain a permanent phone number however yesterday I left a message on your phone and for privacy reasons that is the extent that I will provide my number. I additionally sent you an earlier email with a contact number in a previous email, and I sent you a message on Signal App. As per the agreement, I have CC'ed [REDACTED]
Since that email John Deere have deleted the terms of service: https://developer.deere.com/content/home/landing/newClickThrough.htm?version=1
As I mentioned earlier, I archived it for transparency: https://web.archive.org/web/20210421215911/https://webcache.googleusercontent.com/search?q=cache%3AkKy0Wp2_NfAJ%3Ahttps%3A%2F%2Fdevadmin.deere.com%2Fcontent%2Fapi%2Fapi27358.johndeere%2Flegal%2Flegal%2520ag.htm+&cd=5&hl=en&ct=clnk&gl=au
I had earlier told them I didn’t want a bounty.
Because in the CERT CISA link from those terms, there is a fine line between a breach and research, I suggested they get a VDP urgently.
Additionally I sent the following recommended solutions:
### Disclosure types - Coordinated Disclosure: A researcher can share details of the vulnerability after a fix has been applied and the program owner has provided permission to disclose or after a clearly-stated time has passed from submission, whichever is sooner; - Discretionary Disclosure: The researcher or the program owner can request mutual permission to share details of the vulnerability after approval is explicitly received; or - Non-Disclosure: Researchers are required to keep vulnerability details and the existence of the program itself confidential, regardless of the fix or any conversations between them and the vendor. Note that non-disclosure is considered inappropriate and generally ineffective as a disclosure type for VDPs.
The next day I forwarded everything to cisa.dhs.gov (April 15th).
This is a serious issue and could jeopardize the US food security supply chain.
April 16th the vulnerability was fixed (no confirmation from John Deere)
I sent them to following email:
I have validated SICK-2021-031 has been fixed. All new PII has been deleted again. I'll also validate that SICK-2021-012 has not yet been fixed. May I recommend the following fix: https://www.nginx.com/blog/rate-limiting-nginx/ Also regarding disclosure, I would like to do coordinated responsible public disclosure. Please see this as an example: https://github.com/disclose/dioterms/blob/master/core-terms-vdp.md Please see attached the drafts for both reports. If you would like me to add or remove anything from the reports, please advise what you'd like me to add or remove. In good faith, The Security Research Team @SickCodes
I told John Deere I would like to do a coordinated public disclosure.
Few days later I sent them this
Hopefully we can do a joint release, where I outline what I found, and how JD fixed it, and we can all pat each others' backs. I absolutely commend the engineering team for fixing SICK-2021-031 in under 72 hours.
I sent them this on the 19th:
Hi JD, Any updates? In my opinion, communications from [ENGINEER] seemed to have ceased, which is not really ideal. Since SICK-2021-031 is fixed, I would like to politely remind that you I am asking for the opportunity to work with JD on a positive, public, and responsible disclosure of the vulnerability. I am probably not going to request a CVE ID for this vulnerability as there are no version numbers on the Terminal manager, but here are some notes regarding previous experiences not unlike this vulnerability lifecycle: https://github.com/disclose/research-threats#for-companies In Security Research, the same applies to sports: "a quick game is a good game." I will be writing about my research as it's my job, and it will go here as per usual: https://sick.codes/category/security/ Here is a small vulnerability I published in Brave Browser that from discovery to disclosure took a whopping 24 hours. Brave was commended for their responsiveness by peers in the same "industry" as me, and subsequently the general public: https://community.disclose.io/t/how-i-found-a-tor-vulnerability-in-brave-browser-reported-it-watched-it-get-patched-got-a-cve-cve-2020-8276-and-a-small-bounty-all-in-one-working-day/65 Here is one vulnerability that I published that ended in absolute chaos and speculation, due to sheer lack of communication: https://sick.codes/extraordinary-vulnerabilities-discovered-in-tcl-android-tvs-now-worlds-3rd-largest-tv-manufacturer/ TCL learned from their mistake and ended up building https://src.tcl.com, which is one of the best in-house security bounty/VDP's I've ever seen. It would look very cool if JD whipped up a VDP before we publish. Bounty is not a necessity. Hopefully we can do a joint release, where I outline what I found, and how JD fixed it, and we can all pat each others' backs. I absolutely commend the engineering team for fixing SICK-2021-031 in under 72 hours. I repeat, I want to do a joint disclosure of the vulnerabilities because it looks fantastic when big companies engage small researchers who find big bugs. If doing a joint release, for some reason, isn't in your interests, I'll be publishing the research regardless. Via https://github.com/disclose/research-threats#for-companies: For Companies Find examples below of what not to do. Embrace security researchers. Learn from the documented examples in this archive. Researcher's who have been threatened by naive entities while legitimately working to improve the security of a product should be a source of collaboration; they may know more about your systems than you do. Put researchers who voluntarily submit bugs & vulnerabilities in touch with your internal security teams, work together to fix vulnerabilities, and coordinate the disclosure to your customers and the public. An excellent coordinated disclosure generally boosts a company's public image & customer confidence. It encourages researchers to work with you, not against you. A negative experience can exponentially generate negative publicity, sometimes even viral. Providing researchers safe harbor for reporting a vulnerability to you is critical to working towards a more secure product and ecosystem. Entities that engage researchers and respond quickly to security events are more likely to generate a positive experience. Entities with no security response team, may be more likely to experience a negative disclosure event. Here is a list of 2,000 companies that have their Vulnerability Disclosure Program (VDP) sorted out: https://disclose.io/programs/ Here's some notes regarding disclosure methods, via https://www.bugcrowd.com/blog/whats-a-vulnerability-disclosure-program/
Thank you for reporting this issue. We have a private VDP with [REDACTED], and you should be receiving an invite to the program in the next 24 hours.
Suddenly they had a private vulnerability disclosure program. It did not exist when we started.
24 hours later, I received the invitation to the program…
- I was the only researcher in the program
- The program was created that day
- Every single asset had no bounty
- The company does not allow public disclosure
That is by far, the strangest vulnerability disclosure program I’ve ever been invited to.
Since I had already told them I would be be ineligible to participate, I rejected the unsolicited invitation, left their program, and published my research.
https://sick.codes/sick-2021-012/ (site-specific, no CVE)
https://sick.codes/sick-2021-031/ (site-specific, no CVE)
Willie Cade: https://twitter.com/WillieCade7