mirror of
https://github.com/Harrison-Wells-Cyber/PS-Proxy
synced 2026-07-26 08:06:34 +00:00
Merge pull request #5 from Harrison-Wells-Cyber/codex/fix-tunnel-error-in-powershell-proxy
Accept legacy OAEP-SHA1 agent session encryption for PowerShell 5.1 compatibility
This commit is contained in:
@@ -95,6 +95,9 @@ namespace PSProxy.Agent
|
|||||||
using (var rsa = new RSACryptoServiceProvider())
|
using (var rsa = new RSACryptoServiceProvider())
|
||||||
{
|
{
|
||||||
rsa.ImportParameters(ParseRsaPublicKey(pubDer));
|
rsa.ImportParameters(ParseRsaPublicKey(pubDer));
|
||||||
|
// .NET Framework RSACryptoServiceProvider supports OAEP only as
|
||||||
|
// SHA-1 with the default empty OAEP label. The server accepts
|
||||||
|
// this format for PowerShell 5.1 agent compatibility.
|
||||||
encSecret = rsa.Encrypt(secret, true);
|
encSecret = rsa.Encrypt(secret, true);
|
||||||
}
|
}
|
||||||
string hello = "HELLO " + B64Url(encSecret) + " " + B64Url(nonce) + "\n";
|
string hello = "HELLO " + B64Url(encSecret) + " " + B64Url(nonce) + "\n";
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
|
"crypto/sha1"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
@@ -693,6 +694,25 @@ func handleAgent(conn net.Conn, br *bufio.Reader, server *TunnelServer) {
|
|||||||
server.ClearSession(a)
|
server.ClearSession(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func decryptSessionSecret(key *rsa.PrivateKey, encSecret []byte) ([]byte, error) {
|
||||||
|
label := []byte("PS-Proxy PSP1 session")
|
||||||
|
secret, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, key, encSecret, label)
|
||||||
|
if err == nil {
|
||||||
|
return secret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RSACryptoServiceProvider.Encrypt(..., true), used by the .NET Framework
|
||||||
|
// PowerShell agent, means OAEP-SHA1 with the default empty OAEP label. Keep
|
||||||
|
// accepting that wire format so already-staged agents can enroll.
|
||||||
|
for _, legacyLabel := range [][]byte{nil, label} {
|
||||||
|
legacySecret, legacyErr := rsa.DecryptOAEP(sha1.New(), rand.Reader, key, encSecret, legacyLabel)
|
||||||
|
if legacyErr == nil {
|
||||||
|
return legacySecret, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
func serverHandshake(conn net.Conn, br *bufio.Reader, key *rsa.PrivateKey) (*protocol.SecureCodec, error) {
|
func serverHandshake(conn net.Conn, br *bufio.Reader, key *rsa.PrivateKey) (*protocol.SecureCodec, error) {
|
||||||
line, err := br.ReadString('\n')
|
line, err := br.ReadString('\n')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -713,7 +733,7 @@ func serverHandshake(conn net.Conn, br *bufio.Reader, key *rsa.PrivateKey) (*pro
|
|||||||
if len(clientNonce) != 32 {
|
if len(clientNonce) != 32 {
|
||||||
return nil, errors.New("invalid client nonce")
|
return nil, errors.New("invalid client nonce")
|
||||||
}
|
}
|
||||||
secret, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, key, encSecret, []byte("PS-Proxy PSP1 session"))
|
secret, err := decryptSessionSecret(key, encSecret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
|
"crypto/sha1"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
@@ -131,6 +132,25 @@ func TestSingleListenerAcceptReturnsEOFAfterFirstConn(t *testing.T) {
|
|||||||
t.Fatal("second accept should return EOF")
|
t.Fatal("second accept should return EOF")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func TestDecryptSessionSecretAcceptsAgentSHA1OAEP(t *testing.T) {
|
||||||
|
key, err := rsa.GenerateKey(rand.Reader, 3072)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
secret := []byte("0123456789abcdef0123456789abcdef")
|
||||||
|
enc, err := rsa.EncryptOAEP(sha1.New(), rand.Reader, &key.PublicKey, secret, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
got, err := decryptSessionSecret(key, enc)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if string(got) != string(secret) {
|
||||||
|
t.Fatalf("got %q want %q", got, secret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestServerSecureHandshakeEncryptedFrame(t *testing.T) {
|
func TestServerSecureHandshakeEncryptedFrame(t *testing.T) {
|
||||||
key, err := rsa.GenerateKey(rand.Reader, 3072)
|
key, err := rsa.GenerateKey(rand.Reader, 3072)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user