在健康云信息服务上线后,通过专业的网络安全团队,对系统进行全面的检测。渗透检测结果显示系统存在明显漏洞:文件上传漏洞、手机验证码发送接口流控功能、SQL注入漏洞、越权漏洞和 jQuery 版 本信息等5项内容。



现有前端上传采用layui中的upload进行前端的文件大小、扩展名的验证,但是对于修改后缀名的危险文件无法进行过滤,需要采用服务端验证。
upload.render({
elem: '#uploadlicense'
, url: '?m=Index&a=indexDeal&act=upImg&fromType=license'
, multiple: false
, size: 512
, accept: 'file'
, exts: 'jpg|png'
, number: 1
, before: function (obj) {
loadingIndex = layer.load();
}
, done: function (res, index) {
layer.close(loadingIndex);
if (res.code != "0") {
return layer.msg('上传失败:' + res.msg);
}
if (res.code == "0") {
$("#user_license").val(res.imgUrl);
var imgHtml = "<a href=\"" + res.imgUrl + "\" target=\"_blank\">预览</a>";
$("#pre_user_license").html(imgHtml);
}
}
});
1.在服务器端进行过滤。
2.服务器端读取文件的部分内容作判断,可防止攻击者伪装文件类型上传。
$allow_type = array('application/pdf', 'image/png', 'image/jpeg', 'video/mp4');
//服务器端检查上传文件类型;
$tmpname = $file['tmp_name'];
$finfo = finfo_open(FILEINFO_MIME_TYPE);//返回 mime 类型
$mimetype = finfo_file($finfo, $tmpname);
finfo_close($finfo);
if (!in_array($mimetype, $allow_type)) {
$res['code'] = "1";
$res['msg'] = "不支持该文件类型上传";
die(json_encode_lockdata($res));
}
安装FILEINFO插件

配置php.ini

安装之后我们需要重启php确保生效。

未对每分钟IP请求发送验证码次数限制,通过随机生成手机号批量发送验证码,造成验证码发送次数配额消耗,增大运营成本。
手机验证码发送接口流控功能不完全
1.增加对IP访问此接口的流控功能。
2.增加验证码。

<div class="layui-form-item">
<label class="layui-form-label" style="width: 20%;">验证码</label>
<div class="layui-input-inline"><input type="text" name="captcha" id="captcha" autocomplete="off" class="layui-input"></div>
<div class="layui-form-mid layui-word-aux"> <img src="?m=Login&a=loginDeal&act=getCode" id="getCode" alt="" title="点击刷新验证码" style="cursor: pointer;"><span class="x-red"> * </span> 发送手机短信验证</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label" style="width: 20%;">短信验证码</label>
<div class="layui-input-inline"><input type="text" name="smscode" id="smscode" lay-verify="smscode" autocomplete="off" class="layui-input" disabled="disabled"></div>
<div class="layui-input-inline">
<input type="button" class="layui-btn layui-btn-primary" id="btnSendCode" disabled="disabled" value="获取验证码">
</div>
</div>
$("#user_phone").change(function () {
var mobile = $.trim($("#user_phone").val());
if (mobile.length == 11) {
$("#smscode").attr("disabled", false).css({"background-color": "#fff"});
$("#btnSendCode").attr("disabled", false).removeClass("layui-btn layui-btn-primary").addClass("layui-btn layui-btn-normal");
//单击发送验证码;
document.getElementById("btnSendCode").onclick = function () {
var captcha = $("#captcha").val();
//获取网站验证码;
$.getJSON("?m=Login&a=loginDeal&act=captcha", {mobile:mobile,captcha:captcha}, function (res) {
if (res.code == '0') {
layer.msg(res.msg, {icon: 1,time: 2000});
} else {
if (wait != 60) {
console.log("请" + wait + "秒后再试!");
return;
}
if (mobile == '') {
console.log("请填写手机号码");
return;
}
$("#smscode").val("");
time(document.getElementById("btnSendCode"));
$.getJSON("?m=Sms&a=smsDeal&act=login", {mobile: mobile}, function (res2) {
//console.log(res2.total);
if (res2.code == '0') {
layer.msg(res2.msg, {icon: 1,time: 2000});
} else {
//console.log(res2);
}
});
}
});
}
} else {
$("#smscode").attr("disabled", true);
$("#btnSendCode").attr("disabled", true).removeClass("layui-btn layui-btn-normal").addClass("layui-btn layui-btn-primary");
}
});
//读取数据库记录;
$fromTime = time() - 300;
$toTime = time();
$sql = "select log_id FROM " . $db->table('log') . " WHERE 1";
$sql .= " AND logs = 'smscode' AND log_ip ='" . getip() . "'";
$sql .= " AND log_time > '" . $fromTime . "' AND log_ip <'" . $toTime . "'";
$sql .= " ORDER BY log_id DESC";
$row = $db->queryall($sql);
if (count($row) >= 5) {
$res['code'] = 0;
$res['msg'] = '5分钟内最多发送5次短信.';
$res['total'] = count($row);
die(json_encode_lockdata($res));
} else {
$send = SmsDemo::sendSms($mobile, $signName, $templateCode, $rmdCode, '', '', '', '', 1);
$res['code'] = 1;
$res['send'] = $send;
$_SESSION['code'] = $rmdCode;
die(json_encode_lockdata($res));
}
$user_phone = get_param('mobile');
$captcha = isset($_GET["captcha"]) ? trim($_GET["captcha"]) : '';
if ($captcha != $_SESSION['authcode']) {
$res['code'] = "0";
$res['msg'] = "验证码错误";
die(json_encode_lockdata($res));
} else {
//增加数据库记录;
addlogs($user_phone, 'smscode', '', time(), getip());
$res['code'] = "1";
$res['msg'] = "验证码通过";
//验证码自动销毁;
session_destroy();
die(json_encode_lockdata($res));
}
web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作。
api/api.php?act=getMarkers&token=3cab7ce4142608c0f40c785b5ab5ca24&page=1&limit=300&keys=a&province=%E5%B1%B1%E4%B8%9C%E7%9C%81&city=&area=
Payload:act=getMarkers&token=3cab7ce4142608c0f40c785b5ab5ca24&page=1&limit=300;SELECT SLEEP(5)#&keys=a&province=%E5%B1%B1%E4%B8%9C%E7%9C%81&city=&area=



做参数过滤
@$p = get_safe2('page') == "" ? 1 : get_safe2('page');//获取用户选择的页码
@$pagesize = get_safe2('limit') == "" ? 600 : get_safe2('limit');//获取用户选择的每页显示多少条数据
@$limit = ($p - 1) * $pagesize;//偏移量
通过修改cookie值,可越权查看编辑其他用户的信息。


原来只通过user_id进行参数传递,由于使用自增ID,容易被猜测出来。现在同步增加$user_name查询参数,进行强制限制。
case "show";
$user_id = $_COOKIE['user_id'];
//判断是否一致,防止修改查看 2022-11-09 BY Poleung;
$user_name = $_COOKIE['dbUser'];
$row = $db->fetch('user', '*', array('user_id' => $user_id, 'user_name' => $user_name), ' user_id DESC');
//不存在数据;
if (!$row) {
redirect('?m=Pop&a=tips&act=tips&tips_id=7');
}
$pieces = explode(',', $row['user_type']);
break;
#脆弱的Javascript库

升 级 JavaScript 库 到 最 新 版 本 , 官 方 网 址 : https://jqueryui.com/download/,临时解决方案:隐藏 jQuery 版 本信息,避免被攻击者识别出版本号
@漏刻有时
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife
我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru