Conversation
Signed-off-by: Deepak Jain <deepujain@gmail.com>
The bounded-gap patterns used '.' which does not match newlines in YARA regexes, so socket creation and .connect() on separate lines never matched. Add the 's' (dotall) modifier to the python_socket and perl_socket patterns so multiline forms are detected. Fixes the two failing parametrized cases in test_builtin_reverse_shell_matches_multiline_socket_forms. Signed-off-by: Deepak Jain <deepujain@gmail.com>
rng1995
left a comment
There was a problem hiding this comment.
[SkillSpector Review]
Reviewed exact head 8f7cb94dfda2a09b6cdf18b140282b3ad60edf9c. The bounded dot-all syntax is valid and closes the newline gap, but both widened signatures remain generic socket-client detectors rather than reverse-shell detectors. The Python case needs only stream-socket construction plus connect; the Perl case needs only use Socket plus socket creation. With any of them, benign clients become CRITICAL reverse_shell/YR1 findings.
Require bounded shell-specific evidence and add paired positive real-shell and negative ordinary-client regressions for both languages. Keep signature-triggering fixtures encoded per the test module's antivirus-safety convention. Also preserve the packaged rule's existing CRLF bytes: this branch converts all 125 decoded lines to LF, turning a two-expression fix into full-file base64 churn and increasing conflict/audit risk. PRs #593, #594, and #599 are alternatives; only one corrected implementation should land.
All six hosted checks pass and GitHub reports mergeable/clean, but the detector false positives and unnecessary resource rewrite require changes.
| [ | ||
| ( | ||
| "import socket\ns = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n" | ||
| 's.connect(("10.0.0.1", 4444))\n', |
There was a problem hiding this comment.
[P0] This positive fixture has no reverse-shell action—only normal socket creation and connection—so the test pins a CRITICAL false positive. Tighten the rule to require bounded shell/descriptor-redirection evidence, make this a negative regression, and use an encoded complete reverse-shell fixture for the positive path.
There was a problem hiding this comment.
Addressed in c20dec8 (pushed to fix/592-multiline-reverse-shell).
Both signatures now require bounded shell-specific evidence instead of matching any socket client: the Python pattern requires os.dup2 or a subprocess call within 400 chars after connect; the Perl pattern requires STD(IN|OUT|ERR) redirection or exec of /bin/sh within 400 chars after socket creation.
Paired regressions added: encoded complete reverse-shell fixtures are the positive path for both languages, and the former positive ordinary-client fixtures are now negative regressions, per the test module's AV-safety convention. The packaged base64 rule was re-encoded from the CRLF original, so the decoded diff is exactly two lines with no full-file churn. tests/nodes/analyzers/test_static_yara.py: 90 passed; ruff lint and format clean.
Please re-review.
The widened Python and Perl signatures matched any socket client: the Python pattern needed only stream-socket construction plus connect, and the Perl pattern only use Socket plus socket creation, so ordinary TCP clients raised CRITICAL reverse_shell/YR1 findings. Both signatures now require bounded shell-specific evidence (dup2/subprocess after connect for Python, STD descriptor redirection or /bin/sh exec for Perl). Paired regressions: encoded complete-shell fixtures are the positive path for both languages; the former positive ordinary-client fixtures are now negative regressions. The packaged base64 rule is re-encoded from the CRLF original, so the decoded diff is exactly two lines with no full-file churn. Signed-off-by: Deepak Jain <deepujain@gmail.com>
|
rng1995: the false-positive and churn findings are addressed on head c20dec8. Both widened signatures now require bounded shell-specific evidence: dup2/subprocess after connect for Python, STD descriptor redirection or /bin/sh exec for Perl. The former positive ordinary-client fixtures are now negative regressions, and encoded complete-shell fixtures are the positive path for both languages. The packaged base64 rule was re-encoded from the CRLF original, so the decoded diff is exactly two lines with no full-file churn. All six hosted checks pass on this head. Please re-review when convenient. (On #593/#599 as alternatives: leaving that choice to maintainers.) |
rng1995
left a comment
There was a problem hiding this comment.
Re-reviewed head c20dec868bcb3a3c7d8ee4d4f1469062c4213557 against the previous review.
The CRLF/resource-churn issue is fixed: all 125 decoded lines retain CRLF, and only the two socket expressions change. Both languages now have encoded complete-shell positive fixtures and plain-client negative regressions. Validation: 90 YARA tests passed; Ruff lint and format checks passed; all six hosted checks passed.
The central false-positive concern remains partially unresolved. I reproduced two benign multiline clients that still produce CRITICAL reverse_shell / YR1 findings through the full analyzer: Python invoking a normal subprocess, and Perl opening a local log file on STDOUT. Neither matches the base rule. The added alternatives do not yet establish shell execution or socket-descriptor redirection; details and reproductions are inline.
Please tighten both signatures and add negative regressions for these ordinary operations before approval.
| XCguKlNPQ0tfU1RSRUFNLipcLmNvbm5lY3RcKC8NCiAgICAgICAgJHBlcmxfc29ja2V0ICAgICAg | ||
| PSAvdXNlXHMrU29ja2V0Oy4qc29ja2V0XHMqXChccypTT0NLLw0KICAgICAgICAkcGhwX2Zzb2Nr | ||
| XCguezAsNDAwfVNPQ0tfU1RSRUFNLnswLDQwMH1cLmNvbm5lY3RcKC57MCw0MDB9KG9zXC5kdXAy | ||
| XHMqXCh8c3VicHJvY2Vzc1wuKGNhbGx8UG9wZW58cnVuKVxzKlwoKS9zICAgICAgICAgICAgIA0K |
There was a problem hiding this comment.
[P1] Require shell-specific evidence in the Python alternative
The decoded $python_socket expression accepts any nearby subprocess.call, Popen, or run invocation, regardless of its arguments; the os.dup2 alternative similarly does not establish socket-to-stdio redirection. This benign multiline client produces CRITICAL reverse_shell / YR1 on this head through static_yara.node, while the base rule does not match:
import socket, subprocess
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", 8080))
subprocess.run(["date"], check=True)
s.sendall(b"healthcheck\n")
s.close()No shell is launched or attached to the socket. Please require actual shell-specific invocation or socket-descriptor redirection evidence and add this kind of ordinary subprocess client as an encoded negative regression. The current plain-client negative has neither operation, so it does not catch this remaining false positive.
There was a problem hiding this comment.
Fixed in a892688. The Python rule now requires bounded socket-file-descriptor redirection plus an actual shell invocation, instead of matching a generic subprocess call. Regression controls retain subprocess, pty.spawn and os.execl shell variants and reject the ordinary date subprocess and logfile-redirection cases. All95 focused YARA tests and5983 CI-suite tests pass; lint and formatting pass. The encoded resource retains76-column wrapping and decoded CRLF.
| XCguezAsNDAwfVNPQ0tfU1RSRUFNLnswLDQwMH1cLmNvbm5lY3RcKC57MCw0MDB9KG9zXC5kdXAy | ||
| XHMqXCh8c3VicHJvY2Vzc1wuKGNhbGx8UG9wZW58cnVuKVxzKlwoKS9zICAgICAgICAgICAgIA0K | ||
| ICAgICAgICAkcGVybF9zb2NrZXQgICAgICA9IC91c2VccytTb2NrZXQ7LnswLDQwMH1zb2NrZXRc | ||
| cypcKFxzKlNPQ0suezAsNDAwfShvcGVuXHMqXChccypTVEQoSU58T1VUfEVSUil8ZXhlY1xzKlwo |
There was a problem hiding this comment.
[P1] Distinguish Perl file logging from socket descriptor redirection
The decoded $perl_socket expression stops the open alternative at STD(IN|OUT|ERR), so merely opening a local log file on STDOUT satisfies the supposed reverse-shell evidence. This benign multiline client produces CRITICAL reverse_shell / YR1 through static_yara.node on this head, while the base rule does not match:
use Socket;
socket(SOCKET, PF_INET, SOCK_STREAM, getprotobyname("tcp"));
connect(SOCKET, sockaddr_in(8080, inet_aton("127.0.0.1")));
open(STDOUT, ">", "client.log") or die $!;
print SOCKET "healthcheck\n";
close(SOCKET);STDOUT is a local file, and there is no shell execution. Please require socket descriptor duplication/redirection or sufficient additional shell evidence, and add an encoded negative regression covering ordinary file logging.
There was a problem hiding this comment.
Fixed in a892688. The Perl rule now requires STDIN/STDOUT/STDERR duplication from SOCK plus shell execution; opening STDOUT to a client.log file no longer matches. The complete reverse-shell positive fixture remains detected. All95 focused YARA tests and5983 CI-suite tests pass.
Signed-off-by: Deepak Jain <deepujain@gmail.com>
Summary
Multiline Python and Perl socket reverse shells can evade the built-in YARA rule because its original expressions stop at line breaks. Match those bounded multiline sequences while requiring shell-specific behavior, so ordinary socket clients that run
dateor write a log file do not become CRITICAL findings.Python detection now requires socket-descriptor redirection followed by a shell invocation, including the existing subprocess,
pty.spawnandos.execlforms. Perl detection requires standard-stream duplication from the socket and shell execution. The packaged rules keep their original CRLF line endings and 76-column base64 wrapping.Fixes #592. Both current review findings are addressed in a892688, with replies on their individual threads.
Validation
The three benign-client regressions failed on the previous rule and pass with the repair. All 95 focused YARA tests pass, including the complete Python/Perl shell fixtures and additional pty/exec compatibility controls. Final
make lint,make format-checkandmake test-cipass: 5,983 passed, 14 skipped, 39 deselected and 4 expected failures. Independent agent review checked the decoded rules and reran the focused tests.Risk
These remain lexical heuristics with bounded 400-character spans, not a Python or Perl execution model. Tests scan fixture text only; they do not execute the shell examples. No provider-backed integration result is claimed.