Skip to content

Commit

Permalink
Merge pull request #42 from newrelic/dev
Browse files Browse the repository at this point in the history
Release v1.2.0
  • Loading branch information
aayush-ap authored Apr 12, 2024
2 parents 97dfc89 + f480dd7 commit 41c4a3a
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 12 deletions.
9 changes: 9 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## [v1.2.0] - 2024-04-12
### Features
* IAST replay header decryption due to Security Findings.
* Json Version bump to 1.2.0
### Miscellaneous chores
* Prepended the vulnerability case type with apiId.
* Updated time interval for IAST pull request.
* Bumped golang.org/x/net from v0.17.0 to v0.23.0

## [v1.1.0] - 2024-03-26
### Features
* Functionality to report API endpoints of the application
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/dlclark/regexp2 v1.9.0
github.com/gorilla/websocket v1.5.0
github.com/k2io/hookingo v1.0.5
golang.org/x/crypto v0.22.0
)

retract v0.5.0 // backward compatibility error corrected in v0.5.1
9 changes: 9 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/k2io/hookingo v1.0.3 h1:9rJMlAKzhBLTEn3jmpmt6AsyHmXONPvRgCRxzvxS89Y=
github.com/k2io/hookingo v1.0.3/go.mod h1:GfmXAKuiFd8/UafviDs8nnciGQ89QvHIzQQUaAmvRJ4=
github.com/k2io/hookingo v1.0.5 h1:MAuYIjpOf2IFs7UqEDrHntNBswWg7z7/I2XMQHogEio=
github.com/k2io/hookingo v1.0.5/go.mod h1:2L1jdNjdB3NkbzSVv9Q5fq7SJhRkWyAhe65XsAp5iXk=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
Expand All @@ -16,8 +18,15 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
golang.org/x/arch v0.0.0-20190927153633-4e8777c89be4/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc=
golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
2 changes: 1 addition & 1 deletion instrumentation/csec_grpc/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ require (
)

require(
golang.org/x/net v0.17.0
golang.org/x/net v0.23.0
)

exclude(
Expand Down
6 changes: 3 additions & 3 deletions internal/security_utils/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
package security_utils

const (
CollectorVersion = "1.1.0"
JsonVersion = "1.1.1"
CollectorVersion = "1.2.0"
JsonVersion = "1.2.0"
CollectorType = "GOLANG"
BuildNumber = "158"
BuildNumber = "159"
)
118 changes: 118 additions & 0 deletions internal/security_utils/encryptorUtils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package security_utils

import (
"crypto/aes"
"crypto/cipher"
"crypto/sha1"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"

"golang.org/x/crypto/pbkdf2"
)

const (
ITERATION = 1024
KEY_LEN = 32 // 256 bits
OFFSET = 16
EMPTY_PASSWORD = "Empty Password provided"
DATA_TO_BE_DECRYPTED = "Data to be decrypted is Empty"
INCORRECT_SECRET = "Incorrect Password / salt provided: %s"
EMPTY_SECRET = "secretKey is empty"
ERROR_WHILE_DECRYPTION = "Error while decryption %s: %s"
ENCRYPTED_DATA_DECRYPTED_DATA = "Encrypted Data: %s, Decrypted data: %s"
ERROR_WHILE_GENERATING_REQUIRED_SALT_FROM_S_S = "Error while generating required salt from %s"
ERROR_WHILE_VERIFY_HASH_DATA = "Hash Data not macth %s: %s"
)

func Decrypt(password, encryptedData, hashVerifier string) (string, error) {
if password == "" {

return "", fmt.Errorf(EMPTY_PASSWORD)
}
if encryptedData == "" {
return "", fmt.Errorf(DATA_TO_BE_DECRYPTED)
}

salt, err := generateSalt(password)
if err != nil {
return "", fmt.Errorf(ERROR_WHILE_GENERATING_REQUIRED_SALT_FROM_S_S, err)
}

secretKey := deriveKey(password, salt)
if secretKey == nil {
return "", errors.New(EMPTY_SECRET)
}

encryptedBytes, err := hex.DecodeString(encryptedData)
if err != nil {
return "", fmt.Errorf(INCORRECT_SECRET, err)
}

block, err := aes.NewCipher(secretKey)
if err != nil {
return "", fmt.Errorf(INCORRECT_SECRET, err)
}

decrypted := make([]byte, len(encryptedBytes))

cipher.NewCBCDecrypter(block, make([]byte, block.BlockSize())).CryptBlocks(decrypted, encryptedBytes)
decrypted = removePadding(decrypted)
decryptedData := string(decrypted[OFFSET:])

if verifyHashData(hashVerifier, decryptedData) {
return decryptedData, nil
} else {
return "", fmt.Errorf(ERROR_WHILE_VERIFY_HASH_DATA, hashVerifier, decryptedData)
}

}

func generateSalt(salt string) ([]byte, error) {
// Encode the first OFFSET characters of the salt as hexadecimal
if len([]byte(salt)) < OFFSET {

return nil, errors.New("Error while generating required salt")
}
encoded := hex.EncodeToString([]byte(salt)[:OFFSET])

decoded, err := hex.DecodeString(encoded)
if err != nil {
return nil, err
}

return decoded, nil
}

func deriveKey(password string, salt []byte) []byte {
key, err := pbkdf2KeyDerivation([]byte(password), salt, ITERATION, KEY_LEN)
if err != nil {
return nil
}
return key
}

func pbkdf2KeyDerivation(password, salt []byte, iterations, keyLen int) ([]byte, error) {
key := pbkdf2.Key(password, salt, iterations, keyLen, sha1.New)
return key, nil
}

func verifyHashData(knownDecryptedDataHash, decryptedData string) bool {
return knownDecryptedDataHash == generateSHA256HexDigest(decryptedData)
}

func generateSHA256HexDigest(data string) string {
digest := sha256.Sum256([]byte(data))
return hex.EncodeToString(digest[:])
}

func removePadding(data []byte) []byte {
if i := len(data) - 1; i > 0 {
paddingLength := int(data[i])
if j := len(data) - paddingLength; j > 0 {
return data[:j]
}
}
return data
}
10 changes: 10 additions & 0 deletions security_config/global_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,16 @@ func (info *Info_struct) SetApiData(data Urlmappings) {
return
}

func (info *Info_struct) IastProbingInterval() int {
info.ploicyMutex.Lock()
defer info.ploicyMutex.Unlock()
if GlobalInfo.currentPolicy.VulnerabilityScan.IastScan.Probing.Interval <= 0 {
return 5
} else {
return GlobalInfo.currentPolicy.VulnerabilityScan.IastScan.Probing.Interval
}
}

type metaData struct {
linkingMetadata interface{}
accountID string
Expand Down
4 changes: 3 additions & 1 deletion security_handlers/fuzz_request_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,9 @@ func InitFuzzScheduler() {
}
eventGeneration.SendLogMessage("initializing fuzz request scheduler", "InitFuzzScheduler", "INFO")
for {
time.Sleep(1 * time.Second)
iastProbingInterval := secConfig.GlobalInfo.IastProbingInterval()
logger.Debugln("iastProbingInterval SleepTime", iastProbingInterval)
time.Sleep(time.Duration(iastProbingInterval) * time.Second)
if !secConfig.SecureWS.GetStatus() {
logger.Debugln("WS not connected sleep FuzzScheduler for 5 sec")
time.Sleep(5 * time.Second)
Expand Down
8 changes: 4 additions & 4 deletions security_implementation/implementation.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func (k Secureimpl) AssociateOutboundRequest(dest, dport, urlx string) {
func (k Secureimpl) CalculateOutboundApiId() {
request := getRequest(getID())
if request.VulnerabilityDetails.APIID == "" {
vulnerabilityDetails := presentStack(request.Request.Method)
vulnerabilityDetails := presentStack(request.Request.Method, "REFLECTED_XSS")
request.VulnerabilityDetails = vulnerabilityDetails
}
}
Expand Down Expand Up @@ -264,7 +264,7 @@ func sendEvent(eventId, category string, args interface{}) *secUtils.EventTracke
if category == "REFLECTED_XSS" && (*req).VulnerabilityDetails.APIID != "" {
vulnerabilityDetails = (*req).VulnerabilityDetails
} else {
vulnerabilityDetails = presentStack((*req).Request.Method)
vulnerabilityDetails = presentStack((*req).Request.Method, category)
}

return eventGeneration.SendVulnerableEvent(req, category, args, vulnerabilityDetails, getEventID(eventId, id))
Expand Down Expand Up @@ -347,7 +347,7 @@ func isAgentReady() bool {
return secConfig.SecureWS != nil
}

func presentStack(method string) (vulnerabilityDetails secUtils.VulnerabilityDetails) {
func presentStack(method, caseType string) (vulnerabilityDetails secUtils.VulnerabilityDetails) {
pc := make([]uintptr, 20)
n := runtime.Callers(4, pc)
frames := runtime.CallersFrames(pc[:n])
Expand Down Expand Up @@ -410,7 +410,7 @@ func presentStack(method string) (vulnerabilityDetails secUtils.VulnerabilityDet
stackTrace = stackTrace[:120]
}

vulnerabilityDetails.APIID = apiId
vulnerabilityDetails.APIID = caseType + "-" + apiId
vulnerabilityDetails.Stacktrace = stackTrace

return vulnerabilityDetails
Expand Down
21 changes: 18 additions & 3 deletions security_intercept/intercept.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const (
NR_CSEC_TRACING_DATA = "NR-CSEC-TRACING-DATA"
NR_CSEC_FUZZ_REQUEST_ID = "nr-csec-fuzz-request-id"
NR_CSEC_PARENT_ID = "NR-CSEC-PARENT-ID"
COMMA_DELIMETER = ","
)

/**
Expand Down Expand Up @@ -562,9 +563,23 @@ func createFuzzFile(fuzzheaders string) (tmpFiles []string) {
if DSON && fuzzheaders != "" {
additionalData := strings.Split(fuzzheaders, IAST_SEP)
logger.Debugln("additionalData:", additionalData)
if len(additionalData) >= 7 {
for i := 6; i < len(additionalData); i++ {
fileName := additionalData[i]
if len(additionalData) >= 8 {
encryptedData := additionalData[6]
hashVerifier := additionalData[7]
logger.Debugln("Encrypted file name : ", encryptedData)
filesToCreate, err := secUtils.Decrypt(secConfig.GlobalInfo.MetaData.GetEntityGuid(), encryptedData, hashVerifier)

if err != nil {
logger.Errorln(err)
SendLogMessage(err.Error(), "createFuzzFile", "SEVERE")
return
}

logger.Debugln("Decrypted file name : ", filesToCreate)
allFiles := strings.Split(filesToCreate, COMMA_DELIMETER)

for i := range allFiles {
fileName := allFiles[i]
dsFilePath := filepath.Join(secConfig.GlobalInfo.SecurityHomePath(), "nr-security-home", "tmp")
fileName = strings.Replace(fileName, "{{NR_CSEC_VALIDATOR_HOME_TMP}}", dsFilePath, -1)
fileName = strings.Replace(fileName, "%7B%7BNR_CSEC_VALIDATOR_HOME_TMP%7D%7D", dsFilePath, -1)
Expand Down

0 comments on commit 41c4a3a

Please sign in to comment.