knavesec / CredMaster

Refactored & improved CredKing password spraying tool, uses FireProx APIs to rotate IP addresses, stay anonymous, and beat throttling
926 stars 120 forks source link

[O365Enum] Users with passwordless auth return not found #60

Open TheToddLuci0 opened 1 year ago

TheToddLuci0 commented 1 year ago

Calling via credmaster, we get image (Note: I added a print(response.json()) at line 59 to get the json.)

{
  "Username": "redacted@urmum.com",
  "Display": "hidden@meme.com",
  "IfExistsResult": 1,
  "IsUnmanaged": false,
  "ThrottleStatus": 0,
  "Credentials": {
    "PrefCredential": 1,
    "HasPassword": true,
    "RemoteNgcParams": null,
    "FidoParams": null,
    "SasParams": null,
    "CertAuthParams": null,
    "GoogleParams": null,
    "FacebookParams": null,
    "CaptchaParams": null
  },
  "EstsProperties": {
    "UserTenantBranding": null,
    "DomainType": 3
  },
  "IsSignupDisallowed": true,
  "apiCanary": "asdfmovie4"
}

Going to log in manually, we see this image

Note that here the value of IfExistsResult from /common/GetCredentialType is 5.

From the response:

{
  "Username": "knavesec@example.com",
  "Display": "obviously_redacted@example.com",
  "IfExistsResult": 5,
  "IsUnmanaged": false,
  "ThrottleStatus": 0,
  "Credentials": {
    "PrefCredential": 1,
    "HasPassword": true,
    "RemoteNgcParams": null,
    "FidoParams": null,
    "SasParams": null,
    "CertAuthParams": null,
    "GoogleParams": null,
    "FacebookParams": null,
    "CaptchaParams": null
  },
  "EstsProperties": {
    "UserTenantBranding": null,
    "DomainType": 3
  },
  "FlowToken": "gowiththeflowman",
  "IsSignupDisallowed": true,
  "apiCanary": "some_garbage"
}

(Looks like this code is "Different IDP", not sure if that's used elsewhere, of just for passwordless auth.)

The only other difference I'm seeing is the FlowToken being set in the second.

TheToddLuci0 commented 1 year ago

Sending garbage in as a flow token doesn't seem to fix it. The actual token is generated client site in JS.

knavesec commented 1 year ago

Rare for me to see an issue from you without a PR, do you have any idea how to differentiate?

I'm a little confused by the two JSON objects, it seems like the first one is what you're saying needs to change (ifexistsresult 1) so we would need to figure out what the difference would be elsewise?

TheToddLuci0 commented 1 year ago

Sorry man, I'm only human. I'll send some other PR (maybe add pet credmaster functionality?) to make up for it 😉

The issue seems to be that calling as credmaster does (without the other variables that are computed via clientside JS), you get "user not found" vs "user exists, but don't use a password". I haven't been able to figure out how to get that value correctly as of yet.

TheToddLuci0 commented 1 year ago

The second JSON object where the correct result is retuned is from burp-proxying the request through the normal web flow

knavesec commented 1 year ago

Hahah, pet credmaster would be creepy but an invaluable contribution to the tool.

So are you saying that the clientside JS determines different request variables, which then impacts the response itself?

ville87 commented 10 months ago

Just as an input, not sure if it helps anything... I used the tool with the o365 module against a list of test users with a valid password. All of them returned "FAILURE". The response code 401 was returned for all requests (even though MFA excluded, correct password). Using the module msol however worked and identified the correct credentials. Maybe Microsoft changed something in the autodiscover url / endpoint so that this does not work anymore? If I have time for further debugging, I'll let you know.

alecmoran1 commented 10 months ago

Yeah I just opened ann issue on that I belive it is because of AADSTS53003 or the CAP policy

TwistedSim commented 10 months ago

Just as an input, not sure if it helps anything... I used the tool with the o365 module against a list of test users with a valid password. All of them returned "FAILURE". The response code 401 was returned for all requests (even though MFA excluded, correct password). Using the module msol however worked and identified the correct credentials. Maybe Microsoft changed something in the autodiscover url / endpoint so that this does not work anymore? If I have time for further debugging, I'll let you know.

Microsoft disabled BasicAuth for all tenant, which the o365 plugin rely on.