Open infamousjoeg opened 10 months ago
@Infraded,
Can you please build and test this locally to see if it fixes the problems you're experiencing?
make build
from the root directory will build the executable into bin.
Tested and got a failure after password input.
cybr-cli % ./bin/cybr logon -u $USER -a radius -b https://cyberark.internal.domain
Enter password:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x8 pc=0x100a92f38]
goroutine 1 [running]:
github.com/infamousjoeg/cybr-cli/cmd.logonToPAS({{0x16f77f52b, 0x23}, {0x16f77f521, 0x6}, {0x0, 0x0}, 0x0, {0x0, 0x0}, {0x0, ...}}, ...)
/Users/infraded/dev/cybr-cli/cmd/logon.go:81 +0x148
github.com/infamousjoeg/cybr-cli/cmd.glob..func40(0x140001dc200?, {0x100a9a7a6?, 0x4?, 0x100a9a7aa?})
/Users/infraded/dev/cybr-cli/cmd/logon.go:174 +0x4b8
github.com/spf13/cobra.(*Command).execute(0x100f7cec0, {0x1400012f500, 0x6, 0x6})
/Users/infraded/go/pkg/mod/github.com/spf13/cobra@v1.1.1/command.go:854 +0x53c
github.com/spf13/cobra.(*Command).ExecuteC(0x100f7d6a0)
/Users/infraded/go/pkg/mod/github.com/spf13/cobra@v1.1.1/command.go:958 +0x310
github.com/spf13/cobra.(*Command).Execute(...)
/Users/infraded/go/pkg/mod/github.com/spf13/cobra@v1.1.1/command.go:895
github.com/infamousjoeg/cybr-cli/cmd.Execute()
/Users/infraded/dev/cybr-cli/cmd/root.go:31 +0x24
main.main()
/Users/infraded/dev/cybr-cli/main.go:6 +0x1c```
❯ cybr logon -b https://pineapple.privilegecloud.cyberark.cloud -a cyberark -u jgarcia --verbose
Enter password:
Successfully logged onto PAS as user jgarcia.
Okay, I fixed the nil pointer dereference. Please give it another shot, @Infraded.
No more nil pointer dereference, but getting this now after password:
2023/11/08 10:55:50 Failed to logon to the PVWA and error details are unavailable. Unable to unmarshal response from PAS REST API Web Service. unexpected end of JSON input
On the older builds I was getting the "expected" 500 responses and I've confirmed that I can get through via the API directly
Added some debug outputs and it seems like here: https://github.com/infamousjoeg/cybr-cli/pull/214/files#diff-34ff7a443be24db6bbf225c6913a8c0f097b382c1f5dc6f6de688935e09e5a88R173-R175 is where it dies. It gets a 500 response back for ErrorCode ITATS542I
( which IS an improper HTTP response for this result, but that's what we get ) that it's considering an error in getResponse
and bombing out downstream
Thanks @Infraded. I apologize that I don't have a radius server setup to test this on. I've implemented a conditional in an attempt to handle status code 500 and the existence of ITATS542I. I'm hoping this is the ticket: https://github.com/infamousjoeg/cybr-cli/blob/8e7635aee3461761f43510ff54354419cc9e1ed2/pkg/cybr/helpers/httpjson/httpjson.go#L183-L189
Partial success, with some more tweaking. https://github.com/infamousjoeg/cybr-cli/blob/8e7635aee3461761f43510ff54354419cc9e1ed2/pkg/cybr/helpers/httpjson/httpjson.go#L173-L176 is still catching any error from getResponse
which looks to be doing the same checking sendRequestRaw
was doing https://github.com/infamousjoeg/cybr-cli/blob/8e7635aee3461761f43510ff54354419cc9e1ed2/pkg/cybr/helpers/httpjson/httpjson.go#L135-L137
When I bypass that first err check in sendRequestRaw
it proceeds properly into the the ITATS542I body conditional but does not further prompt me for the next inputs and returns Successfully logged onto PAS ...
@Infraded,
I want to avoid removing that error check that you bypassed. The 500 status code shouldn't be causing it to error there. That should just be for network and protocol errors of the net/http Do method.
What I did find, however, is in the logic of [cmd/logon.go]() a conditional that wasn't checking for the error code to prompt for OTP. So, I made changes to that so that it prompts for OTP when the code is detected.
If you need to, please manually bypass the SendRawRequest
first error check if you need to... I'm going to have to figure something out for that. @AndrewCopeland: Do you have any ideas, by chance?
I wouldn't want to remove that check either, but getResponse
has the same >300 = error
logic that was patched in sendRequestRaw
so it's returning an err that either needs another conditional filtering to be handled differently in getResponse
or to also be filtered in this check . It actually looks like that status code checking logic is duplicated, maybe it moved or got altered between the original PR time and now. Another issue I found yesterday was the actual return of content from that call. auth.go
is expecting data passed down from getResponse
on both content/response
and err
, but err
from the getResponse
call is getting clobbered by the io.ReadAll
bit before being returned in sendRequestRaw
.
I'm hacking through it locally, but am far from proficient in Go. Bypassing the error catch still and making sure sendRequestRaw
returns the err
from getResponse
, I can get a second prompt now, which for me is still and intermediate 2fa type choice, but it fails when sending that call back up with 403, indicating maybe the cookies/context are not being kept.
@Infraded I got it! I got my hands on a self-hosted PAM lab with Radius configured. I needed to implement AND/OR as needed for when ITATS542I was contained in the response body. This should be prompting for one-time passcode now:
The problem now is handling the OTP code afterwards. Troubleshooting that portion now... PROGRESS!
I am pretty sure at this point after all my testing that challenge/response via API is not supported. I have tested using Postman, curl, and writing a small Go app just to attempt authentication with a cookie jar. All tests failed with the error: {"ErrorCode":"PASWS013E","ErrorMessage":"Authentication failure for User [kyle]."}
Even the Vault trace logs show an issue with the session handling in the way it flips between 0 and -1 for session IDs:
Here's what the Vault trace logs looks like with a successful Radius challenge/response authentication from the PVWA:
Further, I used Fiddler to collect all request/response data of a successful authentication from the Browser via PVWA and mimicked the same actions in my Go app to which I was still met with failure.
I'm going to keep this open for now in hopes that someone can prove that they are able to do challenge/response radius via API, but from what I understand from the Discord community... many have attempted, all have failed.
Used gorilla/sessions instead of net/http and it is working using that. I don't know that I want to switch everything over to using gorilla/sessions, though. Going to continue to investigate and use that as a last resort.
I was definitely able to get a token back from the API manually with challenge/response. Our usage has two sets of challenges and even that was OK when manually hitting with Insomnia. Sounds like you had some success though, is it in a state to test or still working on it?
The SonarCloud Quality Gate passed, but some issues were introduced.
3 New issues
0 Security Hotspots
No data about Coverage
0.0% Duplication on New Code
@infamousjoeg Any further thoughts on this? Is the current state of this branch worth testing or is there more to do still?
@Infraded there's something with the way Go needs to handle the cookies when dealing with the challenge/response that I just cannot figure out. PowerShell does it natively, so it's not something that anyone with experience there has encountered before. I did go to the Discord Community in hopes that a customer or partner may have ran into this in the past and they had. Unfortunately, no one had any answers or workarounds outside of "Use PowerShell".
This is still on my radar, but it's going to take time for me to learn what is going on. Any community contributions in the meantime are welcomed!
From my testing, it just needs to keep cookies during the challenge/response calls, until it gets the token. And also not have any old ones when it starts that process. I've got a script now just using a cookie jar w/ curl that works ok. I don't know the mechanisms for that in Go (yet), but will keep poking around too. Appreciate your work on this!
This should fix 403 issues when attempting a challenge/response via MFA on self-hosted PAS.