信息服务上线渗透检测网络安全检查报告和解决方案

简介: 信息服务上线渗透检测网络安全检查报告和解决方案

项目场景

在健康云信息服务上线后,通过专业的网络安全团队,对系统进行全面的检测。渗透检测结果显示系统存在明显漏洞:文件上传漏洞、手机验证码发送接口流控功能、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服务器配置(宝塔)

  • 安装FILEINFO插件



  • 配置php.ini



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


49f213b9d7374aeba51b852bd9a567b8.png


手机验证码流控功能完善

未对每分钟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");
            }
        });

增加5分钟同一IP发送5次短信的验证

  • 验证5分钟内的发送条数
//读取数据库记录;
        $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));
        }


SQL注入漏洞

web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作。

主页中调用的查询API存在SQL注入

  • API访问参数传递
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=
  • Limit字段存在堆叠注入
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=

漏洞证明



修复建议

  • 输入过滤:严格控制输入数据的类型、长度,增加输入合法性判断;禁止出现一些特殊字符或关键词;
  • 预编译SQL语句(参数化查询);
  • 部署WAF;

核心代码

做参数过滤

   @$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 版 本信息,避免被攻击者识别出版本号


@漏刻有时

相关文章
|
19天前
|
SQL 监控 安全
构筑数字堡垒:网络安全与信息保护的深层剖析
【4月更文挑战第9天】在数字化时代,网络安全和信息安全已成为维护个人隐私、企业数据和国家安全不可或缺的一环。本文深入探讨了网络安全漏洞的形成机理、加密技术的进展,以及提升安全意识的重要性。通过对现有安全挑战的分析,提出了一系列创新的防御策略,并强调了构建一个全面的信息保护体系的必要性。
|
27天前
|
存储 安全 网络安全
云端防御战线:云计算环境下的网络安全与信息保护
在信息技术迅猛发展的今天,云计算作为支撑数字转型的重要基石,其安全性牵动着企业生存与发展的命脉。本文深入探讨了云计算环境中面临的安全威胁和挑战,并提出了一系列创新的安全策略和技术解决方案。通过综合分析公有云、私有云以及混合云服务模型中的安全需求,文章构建了一个多层次、全方位的网络安全防护体系。此外,针对数据加密、身份验证、访问控制等关键技术进行了深入剖析,旨在为读者提供一套系统的信息安全保护指南,确保在享受云计算带来的便利时,数据和资源的安全性不被妥协。
43 8
|
2天前
|
存储 SQL 安全
网络防御先锋:洞悉网络安全漏洞与加固信息防线
【4月更文挑战第26天】 在数字化的浪潮中,网络安全和信息安全已成为守护每个组织和个人数据资产的堡垒。本文将深入探讨网络安全领域内常见的安全漏洞类型、加密技术的最新进展以及提升安全意识的重要性。通过对这些关键领域的剖析,读者将获得构建坚固信息防线的知识武装,以应对日益复杂的网络威胁。
15 5
|
4天前
|
监控 安全 网络安全
云端防御战线:云计算环境下的网络安全与信息保护策略
【4月更文挑战第24天】 随着企业数字化转型的加速,云计算作为提供灵活、可扩展资源的关键平台,其安全性已成为企业关注的焦点。然而,云服务的共享性和开放性给传统的网络安全防护带来了新的挑战。本文将探讨云计算环境中面临的安全威胁,并针对这些威胁提出相应的防护措施和最佳实践,以期为信息安全管理者提供参考和指导。
|
5天前
|
安全 网络安全 区块链
网络防线的构筑者:深入网络安全与信息保护
【4月更文挑战第23天】在数字化时代,数据成为新石油,而网络安全则是油井防护的铁栅栏。本文将探讨网络安全漏洞的潜在风险、加密技术的防御策略以及提升安全意识的重要性。我们将剖析常见网络威胁,揭示加密技术如何为数据传输披上隐形斗篷,同时强调培养全民网络安全意识的必要性。通过实例分析和教育建议,旨在为读者打造一道坚不可摧的网络安全防线。
|
6天前
|
SQL 安全 算法
网络防线的构筑者:洞悉网络安全漏洞与加固信息防护
【4月更文挑战第22天】在数字化浪潮下,网络安全和信息安全成为维护社会稳定、保障个人隐私的重要基石。本文将深入探讨网络安全中存在的漏洞问题,介绍现代加密技术,并强调提升全民安全意识的必要性。通过对这些关键知识点的分享,旨在为读者提供一个关于如何构建和维护一个安全网络环境的全面视角。
|
6天前
|
监控 安全 网络安全
云端防御战线:云计算环境下的网络安全与信息保护策略
【4月更文挑战第22天】随着企业和个人用户对云服务的依赖日益加深,云计算环境的安全性成为信息技术领域关注的焦点。本文深入探讨了云计算平台面临的安全威胁、信息安全管理的挑战以及前沿防御技术。通过分析数据加密、身份验证、入侵检测等关键技术在云服务中的应用,提出了一个多层次、综合性的网络安全策略框架。此框架旨在为云服务提供商和使用者提供一套实用的安全保障措施,确保云资源的安全高效运营。
|
8天前
|
存储 安全 网络安全
云端防御策略:融合云服务与网络安全的未来之路
【4月更文挑战第20天】 随着企业数字化转型的加速,云计算已成为支撑现代业务架构的关键。然而,伴随其发展的网络安全威胁也不断演变,对信息安全提出更高要求。本文将深入探讨在动态云环境中实现网络安全防护的策略和技术,包括最新的加密技术、身份验证机制以及入侵检测系统等。通过分析当前云服务中的安全挑战,并结合前沿的网络安全技术,旨在为读者提供一个关于如何在享受云计算便利的同时保障数据安全的全面视角。
|
8天前
|
存储 安全 网络安全
构筑安全之盾:云计算环境下的网络安全与信息保护策略
【4月更文挑战第19天】随着云计算技术的飞速发展,企业和个人越来越依赖于云服务来存储、处理和交换数据。然而,这种便利性背后隐藏着潜在的安全风险。本文深入探讨了在云计算背景下,如何通过综合性的安全措施和策略来强化网络安全防护,确保数据的完整性、可用性和机密性。我们将分析当前面临的主要安全挑战,并基于最新的技术进展提出相应的解决方案,以期达到有效防御外部威胁和内部漏洞的目的。
|
9天前
|
监控 安全 算法
数字堡垒的构建者:网络安全与信息保护的现代策略
【4月更文挑战第19天】在信息化快速发展的今天,网络安全和信息安全已成为维护社会稳定、保障个人隐私和企业商业秘密的关键。本文将深入探讨网络安全漏洞的成因、加密技术的进展以及提升安全意识的重要性,旨在为读者提供一套综合性的网络防护策略,以应对日益猖獗的网络威胁。
8 1