Skip to content

Commit

Permalink
Break up callback uri for linux payload by adding a empty val.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 569296906
Change-Id: I21db9d019c16c3be9853385d397ed51895849862
  • Loading branch information
maoning authored and copybara-github committed Sep 28, 2023
1 parent 93dee00 commit 65e84d5
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import static com.google.common.base.Preconditions.checkNotNull;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.protobuf.ByteString;
import com.google.tsunami.plugin.TcsClient;
Expand All @@ -32,11 +31,8 @@

/** Holds the generate function to get a detection payload given config parameters */
public final class PayloadGenerator {
@VisibleForTesting static final String UNDEF_VAL = "${TCS_UNDEF}";
private static final int SECRET_LENGTH = 8;
private static final String TOKEN_CALLBACK_SERVER_URL = "$TSUNAMI_PAYLOAD_TOKEN_URL";
private static final String TOKEN_CALLBACK_SERVER_URL_LINUX_RCE =
"$TSUNAMI_PAYLOAD_TOKEN_URL_LINUX_RCE";
private static final String TOKEN_RANDOM_STRING = "$TSUNAMI_PAYLOAD_TOKEN_RANDOM";

private final TcsClient tcsClient;
Expand Down Expand Up @@ -116,42 +112,34 @@ private boolean isMatchingPayload(PayloadDefinition p, PayloadGeneratorConfig c)
private Payload convertParsedPayload(PayloadDefinition p, PayloadGeneratorConfig c) {
String secret = secretGenerator.generate(SECRET_LENGTH);
if (p.getUsesCallbackServer().getValue()) {
String callbackUri = tcsClient.getCallbackUri(secret);
return new Payload(
p.getPayloadString()
.getValue()
.replace(
TOKEN_CALLBACK_SERVER_URL_LINUX_RCE, generateLinuxRceCallbackUri(callbackUri))
.replace(TOKEN_CALLBACK_SERVER_URL, callbackUri),
.replace(TOKEN_CALLBACK_SERVER_URL, tcsClient.getCallbackUri(secret)),
(Validator) (unused) -> tcsClient.hasOobLog(secret),
PayloadAttributes.newBuilder().setUsesCallbackServer(true).build(),
c);
} else {
String payloadString = p.getPayloadString().getValue().replace(TOKEN_RANDOM_STRING, secret);
Validator v;
switch (p.getValidationType()) {
case VALIDATION_REGEX:
String processedRegex =
p.getValidationRegex().getValue().replace(TOKEN_RANDOM_STRING, secret);
v =
(Validator)
(Optional<ByteString> input) ->
input.map(i -> i.toStringUtf8().matches(processedRegex)).orElse(false);
return new Payload(
payloadString,
v,
PayloadAttributes.newBuilder().setUsesCallbackServer(false).build(),
c);
default:
throw new NotImplementedException(
"Validation type %s not implemented.", p.getValidationType());
}
}
String payloadString = p.getPayloadString().getValue().replace(TOKEN_RANDOM_STRING, secret);
Validator v;
switch (p.getValidationType()) {
case VALIDATION_REGEX:
String processedRegex =
p.getValidationRegex().getValue().replace(TOKEN_RANDOM_STRING, secret);
v =
(Validator)
(Optional<ByteString> input) ->
input.map(i -> i.toStringUtf8().matches(processedRegex)).orElse(false);
return new Payload(
payloadString,
v,
PayloadAttributes.newBuilder().setUsesCallbackServer(false).build(),
c);
default:
throw new NotImplementedException(
"Validation type %s not implemented.", p.getValidationType());
}
}

private static String generateLinuxRceCallbackUri(String callbackUri) {
return callbackUri.substring(0, callbackUri.length() / 2)
+ UNDEF_VAL
+ callbackUri.substring(callbackUri.length() / 2);
}

/** Guice interface for injecting parsed payloads from payload_definitions.yaml */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ payloads:
interpretation_environment: LINUX_SHELL
execution_environment: EXEC_INTERPRETATION_ENVIRONMENT
uses_callback_server: true
payload_string: curl $TSUNAMI_PAYLOAD_TOKEN_URL_LINUX_RCE
payload_string: curl $TSUNAMI_PAYLOAD_TOKEN_URL
vulnerability_type:
- REFLECTIVE_RCE
- BLIND_RCE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package com.google.tsunami.plugin.payload;

import static com.google.common.truth.Truth.assertThat;
import static com.google.tsunami.plugin.payload.PayloadGenerator.UNDEF_VAL;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
Expand Down Expand Up @@ -91,7 +90,6 @@ public void generate_withLinuxConfiguration_returnsCurlPayload() {
Payload payload = payloadGenerator.generate(LINUX_REFLECTIVE_RCE_CONFIG);

assertThat(payload.getPayload()).contains("curl");
assertThat(payload.getPayload()).contains(UNDEF_VAL);
assertThat(payload.getPayload()).contains(mockCallbackServer.getHostName());
assertThat(payload.getPayload()).contains(Integer.toString(mockCallbackServer.getPort(), 10));
assertTrue(payload.getPayloadAttributes().getUsesCallbackServer());
Expand All @@ -102,7 +100,6 @@ public void generate_withLinuxConfiguration_returnsPrintfPayload() {
Payload payload = payloadGenerator.generateNoCallback(LINUX_REFLECTIVE_RCE_CONFIG);

assertThat(payload.getPayload()).isEqualTo(CORRECT_PRINTF);
assertThat(payload.getPayload()).doesNotContain(UNDEF_VAL);
assertFalse(payload.getPayloadAttributes().getUsesCallbackServer());
}

Expand Down
68 changes: 27 additions & 41 deletions plugin_server/py/plugin/payload/payload_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ class PayloadGenerator:

SECRET_LENGTH = 8
TOKEN_CALLBACK_SERVER_URL = '$TSUNAMI_PAYLOAD_TOKEN_URL'
TOKEN_CALLBACK_SERVER_URL_LINUX_RCE = '$TSUNAMI_PAYLOAD_TOKEN_URL_LINUX_RCE'
TOKEN_RANDOM_STRING = '$TSUNAMI_PAYLOAD_TOKEN_RANDOM'
UNDEF_VAL = '${TCS_UNDEF}'

def __init__(
self,
Expand Down Expand Up @@ -112,13 +110,9 @@ def _parse_payload(
"""Create payload from the selected payload definition."""
secret = self.payload_secret_generator.generate(self.SECRET_LENGTH)
if bool(payload.uses_callback_server.ByteSize()):
callback_uri = self.tcs_client.get_callback_uri(secret)
payload_string = payload.payload_string.value.replace(
self.TOKEN_CALLBACK_SERVER_URL_LINUX_RCE,
_generate_linux_rce_callback_uri(callback_uri),
).replace(
self.TOKEN_CALLBACK_SERVER_URL,
callback_uri,
self.tcs_client.get_callback_uri(secret),
)
validator = type(
'PayloadValidator',
Expand All @@ -131,32 +125,32 @@ def _parse_payload(
pg.PayloadAttributes(uses_callback_server=True),
config,
)

payload_string = payload.payload_string.value.replace(
self.TOKEN_RANDOM_STRING, secret
)
if payload.validation_type != pg.PayloadValidationType.Value(
'VALIDATION_REGEX'
):
raise NotImplementedError(
'Validation type %s not supported.'
% pg.PayloadGeneratorConfig.VulnerabilityType.Name(
config.vulnerability_type)
)
regex = payload.validation_regex.value.replace(
self.TOKEN_RANDOM_STRING, secret
)
validator = type(
'PayloadValidator',
(Validator,),
{'is_executed': _is_executed(regex)},
)()
return Payload(
payload_string,
validator,
pg.PayloadAttributes(uses_callback_server=False),
config,
)
else:
payload_string = payload.payload_string.value.replace(
self.TOKEN_RANDOM_STRING, secret
)
if payload.validation_type != pg.PayloadValidationType.Value(
'VALIDATION_REGEX'
):
raise NotImplementedError(
'Validation type %s not supported.'
% pg.PayloadGeneratorConfig.VulnerabilityType.Name(
config.vulnerability_type)
)
regex = payload.validation_regex.value.replace(
self.TOKEN_RANDOM_STRING, secret
)
validator = type(
'PayloadValidator',
(Validator,),
{'is_executed': _is_executed(regex)},
)()
return Payload(
payload_string,
validator,
pg.PayloadAttributes(uses_callback_server=False),
config,
)

def _payload_matches_config(
self,
Expand All @@ -183,11 +177,3 @@ def check_payload_execution(_, data: Optional[bytes]) -> bool:
return bool(re.compile(regex).search(string)) or False

return check_payload_execution


def _generate_linux_rce_callback_uri(callback_uri: str) -> str:
return (
callback_uri[0 : len(callback_uri) // 2]
+ PayloadGenerator.UNDEF_VAL
+ callback_uri[len(callback_uri) // 2 :]
)
14 changes: 2 additions & 12 deletions plugin_server/py/plugin/payload/payload_generator_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,7 @@ def test_is_callback_server_enabled_returns_true(self):
self.assertTrue(self.payload_generator.is_callback_server_enabled())

@parameterized.named_parameters(
(
'linux_config',
LINUX_REFLECTIVE_RCE_CONFIG,
'curl',
),
('linux_config', LINUX_REFLECTIVE_RCE_CONFIG, 'curl'),
(
'ssrf_config',
ANY_SSRF_CONFIG,
Expand All @@ -59,16 +55,10 @@ def test_generate_with_callback_returns_payload(
):
payload = self.payload_generator.generate(config)
self.assertIn(expected_payload, payload.payload)
self.assertIn(
_IP_ADDRESS, payload.payload.replace(PayloadGenerator.UNDEF_VAL, '')
)
self.assertIn(_IP_ADDRESS, payload.payload)
self.assertIn(str(_PORT), payload.payload)
self.assertTrue(payload.get_payload_attributes().uses_callback_server)

def test_generate_with_callback_returns_undef_val_placeholder(self):
payload = self.payload_generator.generate(LINUX_REFLECTIVE_RCE_CONFIG)
self.assertIn(PayloadGenerator.UNDEF_VAL, payload.payload)

@parameterized.named_parameters(
(
'linux_config',
Expand Down

0 comments on commit 65e84d5

Please sign in to comment.