-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Signed request expected / All Accounts banned at creation #26
Comments
new secret: SlkXamhFfBJmlCyNlEuoqgoRSIWMRvOEhbgHBPKs i've managed to get the new ones for IOS but all accounts get insta banned no matter what edit: there seems to be a new Key in /v2/users which is ['apple_device_token'] which authenticate the App before creating an account, which change on each new account(Coule be Apple APN) for future if anyone wants to update this and have a Jailbroken Iphone this will extract the keys and log them in SYS log |
You might want to give this key a try, I just extracted it from the Android-Version 7.37.1:
Moreover, please remember to change the client type from |
Thanks, tried it still accounts are banned, Unfortunately i don't have an android Phone neither a Windows machine to check the requests for any change, if u can check them and gonna try for IOS there is a 1 time request when you open the app for the first time, one you open the app and click continue it gets called if it lets you set Age then your phone is verified with Apple, they couldve implemented the same with Android. I will try to race the method on IOS to get more info and maybe a way to fake the token. |
Maybe you want to try @springjools solutions from issue #19, as far as I recall he got it working back then. If I get to it I'll take a closer look tomorrow and intercept some of the traffic. |
Yes, but my accounts also get instabanned. But the first time you check for ban, it reports false. But when you immediately check again, it reports true. |
I've found the Token its server to server check https://developer.apple.com/documentation/devicecheck?language=objc idk if its possible to spoof it or trick it edit2: found the method and was able to generate |
I've figured everything and its not good :( So if someone tries to make an account with the API, they first need to get a token from their iPhone and make a request with it, So you need to wait until Jodel servers update apple servers and switch it back to If the token that got sent to Jodel is wrong apple will respond with HTTP Code 400 and this account also get banned. |
Ok, I think it's difficult to circumvent a DCDevice token, since if I understand it correctly, it's a server to server thing. But I understand this only applies to ios. What about the procedure on android? Something similar there? |
I've set isSupported to False and it created a new account without DCDevice but i got 7-10 day ban, i think im banned by device_uid i'll try to spoof it can i ask what decompiler you use, it looks alot better than Ghidra edit: this device_uid token is weird it changes every time i register, It looks Base64 but when i decrypt it it looks like this |
I've spoofed the UUID before it gets hashed but still getting insta ban if anyone wants to try build this with Theos, it'll randomize it when called is there a chance that Jodel just bans all accounts as precaution? |
I use IDA as a decompiler for Jodel. The Apple reference of DeviceCheck says the application must check whether DeviceCheck is supported by the device before using it. Maybe older iPhones do not support DeviceCheck. If we can find an Jodel-Version for e.g. iPhone 6 (iOS 12 is the last supported version) we could try using this version and HMAC-Key to register a user. This might circumvent the DeviceCheck entirely. |
to my testing, jodel allows accounts made with old version to work in the old version, but trying to create an account with older version fails and says Please update the app, if you know the last supported version number on iPhone 6 i will downgrade to it and see |
Think i made a mistake, I've downloaded Version 7.10 and checked the http request there is the same DCDevice token, it's not new they using it for over a year now |
random 3 AM idea might worth it, i noticed on the app that when opening a link to a post it wont open in the app if i got nextDNS enabled, thats because Branch.io is integrated in the app and nexDNS blocks all requests to it. googling Branch.io shows
what if the accounts get banned because of Branch's stuff as its requests aren't implemented here? we should try to create an account with Branch's HTTPS requests and see if its banned. when i spoofed UUID before it was for jodel HTTPS requests, but i didn't check if branch's is logging any tokens or anything im going to sleep now i will follow with this when i wake up. |
Might be definitely worth a try but I thing i tested this some time ago and it did not have any effect. |
my basic analysis 1st token 2nd 3rd
{
"session_id": "10134534657934677872",
"link": "https://shared.jodel.com/a/key_live_jcESXFnKwxb53gafuWSRFijozto4BLB5?%24randomized_bundle_token=1066931657934513952",
"data": "{\"+clicked_branch_link\":false,\"+is_first_session\":false}",
"randomized_device_token": "1059087119560141413",
"randomized_bundle_token": "1066931657934513952",
"invoke_register_app": true
} not very useful but they got 1 thing right, not my first session so im in the system and probably tagged banned if Jodel really integrates with them |
Might be helpful |
Thank you very much @ExTBH! Just updated the keys to the 4.139 version, for me most of the tests are currently passing, you might want to give it a try! |
Out of home now without my mac, will be back in 9 hours and test, if this works i might use it for another project that i can't fix because of DeviceCheck, thanks |
I also updated with git pull and it resolves the signed request expected-error. But accounts are still blocked. You need to test it like this: `Python 3.10.1 (tags/v3.10.1:2cd268a, Dec 6 2021, 19:10:37) [MSC v.1929 64 bit (AMD64)] on win32
Moreover, I rememberthat previously the first call used to return False, and any second call to get the same information used to return True. Also before there was a case when the status of the blocked-variable depended on the lat and lon-coordinates you fed to the function, ie I think geo-fence of some sort. |
Not sure what is going on, just tested the requests with updated keys (iOS, 7.51) and the response looks good for me! Key is as follows:
And the corresponding requests i performed are:
which lead to the following output:
Could you please verify this on your end? If it works i'll update the keys accordingly |
Weird. I updated the secret and version in L30-31 in jodel_api, ran setup build and setup install --user. I get this:
test.py is copy paste of the code you posted |
Try altering the account creation to the following line to ensure the correct secret and version are used:
Additionally you might want to modify the coordinates to a random value, some bans seem to be based on coordinates. |
But we used the same coordinates... |
If accounts with the same coordinates are created from different IP addresses, they might detect it and ban them. Therefore a randomisation of coordinates might be necessary. |
for a minute i thought Jodel team disabled this shit :( edit: @Unbrick could you make another account and check to make sure? lat, lng, city, country = 26.4591484, 50.117690, "Saar", "BH"
j = jodel_api.JodelAccount(lat=lat, lng=lng, city=city, country=country)
time.sleep(5)
status, response = j.get_user_config()
print("Blocked ", response.get('user_blocked'))
time.sleep(1)
print("Karma", j.get_karma())
time.sleep(1)
print("Blocked ", response.get('user_blocked'))
|
Just checked, the block seems to dependant on the IP address. You might want to try residential proxies, i tested now with two different, one got me blocked, the other one worked like a charm! Edit: Pushed the current version state to master now. |
i'll check with my cellular IP, something is not right.. Edit: My cellular looks to be banned too Edit2: in this Lib API URL is set to |
For what it is worth, I have tried this with a vpn from several locations (changing coordinates, city and country input every time) and i am also banned every time i make an account. I've tried with both |
What about switching to Android version? Does Android implement something like DeviceCheck? +Android is bigger, so if there any its probably bypassed. |
I'll perform more tests tomorrow regarding IP address and location. @ExTBH the Android version requires email verification which would require a mail server to verify the account. |
Sadly i now can replicate your issue, account seems to be banned instantly. |
Guess that was a bug on their servers..
|
Defeating DeviceCheck is no possible option from my point of view. Leaving us with the email verification. I recorded the required requests and documented the (hopefully) complete process here. Now in theory all it needs is a mail server which allows API access. I tested OpenTrashmail which seems to do just fine. All it takes now is plugging it all together. |
i can think of one problem here, Google banning domains after it notices a bunch of accounts made with it. 2 AM for me now, i'll check with a public mail provider tomorrow since i don't have a VPS to work with. if this work i've got an idea to solve iOS bans for good, basic idea is, MITM the IOS app calling the api, replace the requests to android stuff, get the responses, convert them to something the iOS app understand i don't see CORS headers also, should be possible for me to make a web client for the app with this |
Oki I've followed the steps above but haven't tested step 4, the rest works. I tried https://www.mohmal.com/ this email service and made a script to make it in 2 steps, should be able to use a free mail with API and work also. from typing import Union
import requests
#Used by all methods here
baseURL = "https://www.googleapis.com"
querystring = {"key":"AIzaSyDFUC30aJbUREs-vKefE6QmvoVL0qqOv60"}
headers = {
"X-Android-Package": "com.tellm.android.app",
"X-Android-Cert": "A4A8D4D7B09736A0F65596A868CC6FD620920FB0",
"X-Client-Version": "Android/Fallback/X21000001/FirebaseCore-Android",
}
def requestLogin(email: str) -> Union[bool, str]:
url = f"{baseURL}/identitytoolkit/v3/relyingparty/getOobConfirmationCode"
payload = {
"requestType": 6,
"email": f"{email}",
"androidInstallApp": True,
"canHandleCodeInApp": True,
"continueUrl": "https://jodel.com/app/magic-link-fallback",
"androidPackageName": "com.tellm.android.app",
"androidMinimumVersion": "5.116.0"
}
response = requests.post(url=url, json=payload, headers=headers, params=querystring)
if response.json()['kind'] == 'identitytoolkit#GetOobConfirmationCodeResponse' and response.status_code == 200:
return True
return f"{response.status_code} | Failed to create account | {response.text}"
def extractOob(link: str) -> Union[bool, str]:
try:
url = requests.utils.unquote(link)
start = 'oobCode='
end = '&continueUrl'
return(url[url.find(start)+len(start):url.rfind(end)])
except:
return False
def redeemOob(oobCode: str, email: str) -> Union[str, dict]:
url = f"{baseURL}/identitytoolkit/v3/relyingparty/emailLinkSignin"
payload = {
"email": f"{email}",
"oobCode": f"{oobCode}"
}
response = requests.post(url, json=payload, headers=headers, params=querystring)
responseJsoned = response.json()
if response.status_code == 200 and responseJsoned['kind'] == 'identitytoolkit#EmailLinkSigninResponse':
return {
'idToken': responseJsoned['idToken'],
'refreshToken': responseJsoned['refreshToken'],
'expiresIn': responseJsoned['expiresIn'],
'localId': responseJsoned['localId'],
}
return f"{response.status_code} | Failed to redeem Oob | {response.text}"
def refreshTokens(refreshToken: str) -> Union[str, dict]:
url = "https://securetoken.googleapis.com/v1/token"
payload = {
"grantType": "refresh_token",
"refreshToken": f"{refreshToken}"
}
response = requests.post(url, json=payload, headers=headers, params=querystring)
responseJsoned = response.json()
if response.status_code == 200:
return {
'access_token': responseJsoned['access_token'],
'expires_in': responseJsoned['expires_in'],
'refresh_token': responseJsoned['refresh_token'],
'user_id': responseJsoned['user_id'],
'project_id': responseJsoned['project_id']
}
return f"{response.status_code} | Failed to refresh tokens | {response.text}"
email = '<Your@mail.com>'
if requestLogin(email):
oob = extractOob(input("Paste URL from Email: "))
if oob == False:
print("\n\nCan't extract OobCode")
exit()
oobTokens = redeemOob(oob, email)
if type(oobTokens) != dict:
print('\n\n' + oobTokens)
exit()
refreshedTokens = refreshTokens(oobTokens['refreshToken'])
if type(refreshedTokens) != dict:
print('\n\n' + refreshedTokens)
exit()
print(refreshedTokens)
``` |
@ExTBH please check out the android_mail_auth branch. For me the registration using email works like a charm:
Edit: I used a good portion of your code for the verification, i hope you are fine with this :) |
Out of home, will check when im back. Im all in FOSS so yeah im ok |
Quick update: Seems like they have a absolutely brilliant bot prevention system. Even though verifying by mail my accounts are now blocked. And quick code update, you can now either pass a mail address and mail fetch handler directly in the constructor or leave them out. Leaving them out prompts you for manual input. The fetch_handler requires one parameter (the email address argument) and should return a text containig the oobCode. The code is extracted automatically afterwards. Code example with handler:
Example without handler (interactive mode):
|
my attempt with the new branch edit1: email seems to be sensitive to spaces, it needs to be stripped from spaces that comes after the .[tld] part edit3: In here, client_id is I think API's are separated now, every platform has different keys, we should probably fill all the fields filled in the logged requests lat, lng, city, country = 23.175, 50.1486, "Manama", "BH"
j = jodel_api.JodelAccount(lat=lat, lng=lng, city=city, country=country)
time.sleep(5)
response = j.get_user_config()
print("Blocked ", response.get('user_blocked'))
time.sleep(1)
print("Karma", j.get_karma())
time.sleep(1)
print("Blocked ", response.get('user_blocked'))
|
Your third edit really did the trick for me there! Using the correct client_id, the accounts do not seem to be banned anymore. Just pushed the changes, does it work for you? |
im installing with pip3 install git+https://github.com/JodelRaccoons/jodel_api.git@android_mail_auth#egg=jodel-api but it doesn't allow me to set the email now, using same code as before, it just creates an account by itself which is bananed
|
I split the accounts into iOSJodelAccount and AndroidJodelAccount. The current default is iOSJodelAccount as it is more easy to use for read only access. Try to use the AndroidJodelAccount like mentioned in the branches readme Edit: Codeexample
|
works! i get False now, i'll test making a post and update edit: endpoint might be different print(j.create_post(message="Test The Jodel_API.", imgpath=None, b64img=None, color=None, ancestor=None, channel="")) returns, with unbananed account
|
477 sounds to me like the request signing is somehow broken. I'll check that tomorrow and will try to verify the signing mechanism. |
calling below works fine, don't think its signing, i dont own an Android to check
iOS post Request looks like the below {
"location" : {
"loc_coordinates" : {
"lat" : 26.213154187145772,
"lng" : 50.557814349952793
},
"loc_accuracy" : 3639.623509412248,
"country" : "BH",
"city" : "Manama",
"name" : "unknown"
},
"color" : "A867E9",
"test" : false,
"channel_id" : "5f8ebbb3fd37e500256f7a67",
"to_home" : false,
"section" : "Main",
"promoted_link" : "",
"message" : "..."
} |
Somehow the HMAC calculation seems off. I tested the same requests in BurpSuite (using the HMAC calculator extension) and they work just fine. Even using BurpSuite as a proxy for the python_api works flawlessly. But i can't spot the difference between the two requests: Signed by BurpSuite:
which is signed using the following HMAC input parameters:
which successfully creates a post. Performing the same request from python:
with the following input parameters:
returns the 477 unknown. |
can't think of anything for this as i don't know anything about HMAC |
Couple of things that caught my eye :
|
Try to use double quotes instead of single ones. I know in a previous project, that this was the issue. Also the format of string/number. Also in this other project, I remeber there was some difference with how you supply the payload to requests. I think it was better to use json = parameter instead of data = parameter. See this: https://stackoverflow.com/questions/9733638/how-to-post-json-data-with-python-requests |
the quotes make sense, i think i've worked in a file before i used single or double don't remember and it errored |
I think json doesn't support single quotes, or was it requests? Or I may be wrong. |
I replicated two absolute identical requests...the one in BurpSuire still worked, the one in python did not. Turned out you need to handle the HMAC key passed into the constructor instead of just ignoring it. |
Sounds like we can close this issue for now 👍 |
Issue
Secret key got changed
...
Environment
If you're reporting a bug, please attach the output of the following commands:
The text was updated successfully, but these errors were encountered: