Open showdownhero opened 4 years ago
The new My 7 Eleven is up...
Obviously we can't lock fuel now....I try to change the APP_VERSION in settings.py to "2.0.0.10867". I was able to login and lock the fuel..But the fuel docket didn't show up in my iphone new My7Eleven app...
I think they tie the fuel docket/offers to the 711 card rather than the account as in previous version....
@micyew, does the Fuel Price Lock tab in the app show the locked price? If yes then I think it's still working?
Nope....Previous version have this button "Show Voucher". Now no more. I can lock the price with this app.py after changing the version in settings.py. Everything good. But it just shows nothing in the new My7Eleven app. Something must have change in the backend. Maybe different database..?
has anybody gone through the app with wireshark running? i'd imagine some of the api endpoints or the host itself may have changed
@LynnAU It seems the new app uses SSL Pinning, I used another proxy tool (https://github.com/alibaba/anyproxy) trying to inspect the requests, failed... It appears it only respected the SSL certificate issued by themselves.
@PinkyJie that's going to be annoying, we'll have to pull the cert out from the app (if it even includes it that is). i'll take a look at it tonight and see if we can decompile the apk or something
Getting more and more difficult to crack.....
Just a quick snoop of a fuel lock request, it loads this URL https://app.api.7eleven.com.au/api/Stores/NearbyFuel?fuel=PULP98&lat=-37.782531&lon=144.943449
and these are the headers:
x-device-os: Android
x-device-os-version: Android: 9 - P (SDK 28)
x-device-build-version: 2.0.0
x-device-identifier: A0001
x-device-uuid: 6f4ba054-****-****-****-************
x-tz-offset: 36000
Date: Wed, 17 Jun 2020 05:28:15 GMT
x-attestation-token:
Authorization: Bearer *snipsnip*
signature: *removed*
And then with that json response it has a list of your 5 closest stores, a hash & timestamp to send on (UTC time it looks like), and your fuel type. For example (store details removed):
{"stores":{["storeId":"1001",
"name":"7-Eleven Oakleigh",
"coordinates":{},
"location":[],
"address":{},
"phone":"",
"openingHoursList":[],
"specialOpeningHours":[],
"allHours":true,
"isActive":true,
"isFuelStore":true,
"hasKiosk":false,
"features":[],
"fuelOptions":[],
"atm":true}],
"fuel":"PULP98",
"time":"2020-01-01T00:00:00.0000000Z",
"hash":"HMrd******************************/ZVRUsYrs"}
And then it uses the stores list, the timestamp, hash and the fuel type redirects to https://app.api.7eleven.com.au/api/Fuel/BestPrice?fuel=PULP98&stores=1001,1002,1003,1004,1005&time=2020-01-01T00:00:00.0000000Z&hash=HMrd******************************/ZVRUsYrs
which then responds with:
{"storeId":"1336","storeName":"Wantirna","storeLatitude":-37.903332,"storeLongitude":145.085953,"ean":"56","fuelType":"PULP98","updated":"2020-06-16T19:33:00Z","price":1419,"time":"2020-01-01T00:00:00.0000000Z","hash":"IdlLV/******************************/U"}
That's all I'm gonna do for now. I've removed some identifying things.
@freyta Out of curiosity, how did you get the response contents with SSL pinning enabled?
There's a few ways to bypass, I use ssl-kill-switch2 on iOS, there's similar for Android I presume (not sure what Freyta used)
How much work would it be to update the python script to interact with the new app?
Just a quick snoop of a fuel lock request, it loads this URL https://app.api.7eleven.com.au/api/Stores/NearbyFuel?fuel=PULP98&lat=-37.782531&lon=144.943449
I think as long as coordinate (lat) can be overridden with a "desirable" one this app is feeding in, the app will be working correctly with new API.
not sure if there is any TLS comm issue with the new API though.
Firstly, I just want to thank @freyta for this wonderful project. I was just wondering if there's been any progress with getting this working with the new app/process?
Hate to be the bearer of bad news.
I've spent some time looking through the Android app and found the source of these headers:
x-attestation-token
/api/Fuel/Lock
call (is left blank on the other preparing calls)SafetyNet has been proven to be difficult to circumvent. It's not feasible to generate this token outside an app context (i.e., in a web script). It's also not possible to repackage the app with the ability to set the GPS location on non-rooted devices.
signature
libapikey.so
Previously, the signature was generated in Java which was trivial to decompile and re-implement (all parameters were visible, along with the algorithms used). It's still possible to use this new module as it will still accept arguments and return a signature but it's difficult to create an interface.
Early signs point to a script like this existing one is not feasible due to SafetyNet. However, using emulators is a viable, albeit less convenient solution.
@yifanfu not sure how freyta did it, but I recompiled the app with a different security config which allows user certificates (and removes the pinning):
diff --git a/res/xml/network_security_config.xml b/res/xml/network_security_config.xml
index df1194a..3e2d64c 100644
--- a/res/xml/network_security_config.xml
+++ b/res/xml/network_security_config.xml
@@ -5,16 +5,9 @@
<certificates src="@raw/rapidsslrsa2018" />
<certificates src="@raw/digicertglobalrootca" />
<certificates src="system" />
+ <certificates src="user" />
</trust-anchors>
</base-config>
- <domain-config cleartextTrafficPermitted="false">
- <domain includeSubdomains="true">*.7eleven.com.au</domain>
- <trust-anchors>
- <certificates src="@raw/isrgx4" />
- <certificates src="@raw/isrgx3" />
- <certificates src="@raw/isrgrootx1" />
- </trust-anchors>
- </domain-config>
<debug-overrides>
<trust-anchors>
<certificates src="system" />
Hate to be the bearer of bad news.
I've spent some time looking through the Android app and found the source of these headers:
x-attestation-token
- required on the
/api/Fuel/Lock
call (is left blank on the other preparing calls)- protects API calls from unverified sources
- comes from SafetyNet
SafetyNet has been proven to be difficult to circumvent. It's not feasible to generate this token outside an app context (i.e., in a web script). It's also not possible to repackage the app with the ability to set the GPS location on non-rooted devices.
signature
- protects API calls from tampering (e.g., changing latitude and longitude)
- comes from
libapikey.so
- compiled module, difficult to decompile
Previously, the signature was generated in Java which was trivial to decompile and re-implement (all parameters were visible, along with the algorithms used). It's still possible to use this new module as it will still accept arguments and return a signature but it's difficult to create an interface.
Early signs point to a script like this existing one is not feasible due to SafetyNet. However, using emulators is a viable, albeit less convenient solution.
@yifanfu not sure how freyta did it, but I recompiled the app with a different security config which allows user certificates (and removes the pinning):
diff --git a/res/xml/network_security_config.xml b/res/xml/network_security_config.xml index df1194a..3e2d64c 100644 --- a/res/xml/network_security_config.xml +++ b/res/xml/network_security_config.xml @@ -5,16 +5,9 @@ <certificates src="@raw/rapidsslrsa2018" /> <certificates src="@raw/digicertglobalrootca" /> <certificates src="system" /> + <certificates src="user" /> </trust-anchors> </base-config> - <domain-config cleartextTrafficPermitted="false"> - <domain includeSubdomains="true">*.7eleven.com.au</domain> - <trust-anchors> - <certificates src="@raw/isrgx4" /> - <certificates src="@raw/isrgx3" /> - <certificates src="@raw/isrgrootx1" /> - </trust-anchors> - </domain-config> <debug-overrides> <trust-anchors> <certificates src="system" />
Any recommendations on emulator and APK to use? PS thanks @freyta for the usage of your app, used it about 30-40 times.
@k0rtina To be honest with you I haven't looked into it. On the ozbargain thread PokemonGo methods (https://www.reddit.com/r/PokemonGoSpoofing/) are mentioned.
If anyone is interested, I wrote up a quick and nasty Python script which implements the current signature generation requirements. Querying nearby stores and fuel prices requires an OAuth token (not supplied), but the signature generation can be validated with the health check and "appconfig" requests. I haven't locked in fuel recently, but for what its worth I haven't come across the "x-attestation-token" on iOS yet.
Nice work!
Have you managed to complete the last step of the lock in?
iOS will require(?) the x-device-check-token
to be set.
I haven't tried that yet, but I'll keep it in mind and post any further notes here.
Definitely interested in seeing it. š
Just an FYI, you can't use the Android signature with iPhone headers, it produces a "signature mismatch" error
@ryleyangus How do I generate the OAuth refresh token?
Hey guys, I spent some time on hacking the login page and realised it's implemented by Azure AD D2C OAuth flow, with the help of the Azure document, I finally figured out the flow to get access token/refresh token.
Here is the snippet written in Node.js to get the access/refresh token: https://runkit.com/wenbo/7-eleven-api-test
@hirani89 Hope this can help answer your question.
Note:
If anyone is interested, I wrote up a quick and nasty Python script which implements the current signature generation requirements. Querying nearby stores and fuel prices requires an OAuth token (not supplied), but the signature generation can be validated with the health check and "appconfig" requests. I haven't locked in fuel recently, but for what its worth I haven't come across the "x-attestation-token" on iOS yet.
I tried running this python script using the refresh token generated by the js code. I get Hash mismatch
@hirani89 I updated my script to include a "nearby stores" API call (with the example provided in the python script), could you try again to see if it works?Just use the same link above https://runkit.com/wenbo/7-eleven-api-test (make sure you are on v1.0.3).
Hey @amcgavin , I was trying to remove SSL pinning with your solution, but the recompiled apk can't be opened, I checked the log with adb logcat
, it says libapikey.so
is missing...
AndroidRuntime: java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/au.com.fuel7eleven-MJ9OaVTWjkE7Y23n2u69FA==/base.apk"],nativeLibraryDirectories=[/data/app/au.com.fuel7eleven-MJ9OaVTWjkE7Y23n2u69FA==/lib/arm64, /system/lib64, /system/product/lib64]]] couldn't find "libapikey.so"
any ideas? The steps I was following are:
apktool d au.com.fuel7eleven.apk
res/xml/network_security_config.xml
apktool b --use-aapt2 au.com.fuel7eleven
(it throws error without --use-aapt2
)keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore au.com.fuel7eleven.apk alias_name
@PinkyJie you'll need to zipalign
after you sign.
zipalign -v 4 au.com.fuel7eleven.apk au.com.fuel7eleven-aligned.apk
@amcgavin thanks, same issue to me even after zipalign
š¤
Hmm, if you re-decompile your built one, are the libraries present?
@amcgavin not sure how to find the libraries š¤¦ not android developer. Did you find the spec for API api/fuel/lock
? Correct me if I'm wrong, I'm thinking we already know how to get the access token, if we know the spec of lock API, we can lock now, right? Or we still require some specific key from libapikey.so
? From the python script provided above, it seems we don't need any other info if we know both the API spec and access token.
@PinkyJie As amcgavin posted earlier, the issue preventing price locking independently of the My 7-Eleven app is generating a valid x-attestation-token (Android) or x-device-check-token (iOS). You also need the customer "loyaltyId", but this can be retrieved from "https://app.api.7eleven.com.au/api/profile" by generating a signature using the general method I described. I have a workaround for the x-device-check-token requirement, but its not a long-term solution (7-Eleven could very easily patch it). I'm happy to look into generating a proper x-device-check-token, but this might not be practical / might take a long time to achieve.
BTW Thanks for your work on describing and implementing the Azure authentication process.
@ryleyangus I see, thanks for explanation, hope you guys can bring us good news soon. :+1:
Hi guys, just seeing if there's been any progress on this? Is it likely we'll be able to use this in the future or have 7 eleven locked this down for good?
In case anyone is still holding out for any news/updates on this. I've been looking into the SafetyNet api that google uses this past week or so. Google basically scraps data from the device, and checks on its servers if it's genuine/untampered, sends those results back to the app which passes them onto 7/11's backend where they verify them. The payload is signed by google so the api will have the information required to decrypt it and read the contents.
There is no spoofing this/generating it in a web script. I can't think of anything at least to fool the api into thinking the request came from a genuine device (unless the developers got lazy and skipped some verification steps).
I've managed to root a spare galaxy s7 and can gps spoof to get cheap fuel again.
@LynnAU Up until a few weeks ago it was possible to use any single character as the "x-device-check-token" header value. About the same time 7-Eleven fixed this oversight, they also blocked the ability to easily overwrite an existing fuel lock with a better fuel lock. There might still be some low-hanging validation bugs, but I've changed my process to using iOS DeviceCheck tokens.
@LynnAU @ryleyangus That's good work! Do either of you have anything working to share please? I'd love to learn more.
Obviously the fuel app is down at the moment. Based on their comment on this Facebook post they will be creating a new app called my 7 eleven.
https://www.facebook.com/132945996743236/posts/3034321299939010/?d=n
Just thought Iād give everyone a heads up