范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

PHP安全编码规范不可忽略

  目录1、安全编码的基本原则 1.1 所有输入数据都是有害的 1.2 不依赖运行环境的安全配置 1.3 安全控制措施落实在最后执行阶段 1.4 最小化 1.5 失败终止 二、 常见漏洞安全编码 2.1 低版本框架、库漏洞 2.2 Command Injection 2.3 SQL Injection 2.4 XSS 2.5 CSRF 2.6 URL Redirect 2.7 路径可控 2.8 Code Injection 2.9 Xpath Injection 2.10 资源泄露 2.11 XXE 2.12 SSRF 2.13 敏感信息泄露 2.14 越权漏洞 2.15 MongoDB Injection 2.16 弱类型漏洞 2.17 任意文件上传 2.18 本地文件包含 2.19 并发问题 2.20 WebSocket跨站劫持 1、安全编码基本原则1.1 所有输入数据都是有害的
  直接输入数据:
  对于用户通过 GET, POST, COOKIE, REQUEST等输入的数据以及框架提供的数据来源,即通信协议中从客户端传过来的一切变量,无论是用户手动填写的数据或是客户端浏览器或操作系统自动填写的数据,都可能产生安全问题,需要进行严格的安全性检查。
  间接地输入数据:
  从数据库、文件、网络、内部API获取的数据等,即一些不直接来源于用户,但是又不是程序中定义好的常量数据。比如用户的输入经过层层转化输出到数据库或文件,后面又再次利用的时候,这时获得的数据依然是不可信的,同样需要进行严格的安全性检查。1.2 不依赖运行环境的安全配置
  不能寄希望于配置文件的安全选项,必须将程序置身于最不安全的配置下进行考虑。1.3 安全控制措施落实在最后执行阶段
  每个安全问题都有其产生的原因,例如SQL注入的原因是SQL语句参数拼接。因此对SQL注入问题的防范,需要在SQL语句执行前对参数进行安全处理,因为此时才能确定预期的参数数据类型、数据范围等。1.4 最小化
  最小化原则适用于所有与安全相关的领域,在代码安全方面主要表现为:
  1、用户输入最小化。尽可能少地使用用户的输入。
  2、用户输入范围最小化。过滤参数时应使用白名单策略,对于可明确定义范围的参数检查参数的有效性,譬如Email,卡号,身份证号等。
  3、返回信息最小化。程序错误信息应对用户屏蔽,不要将原始错误信息直接返回到用户侧。1.5 失败终止
  对用户提交的数据进行安全性检查的时候,如果发现数据不符合要求应终止业务的执行,不要试图修正和转换用户提交的参数继续向下执行。二、 常见漏洞安全编码2.1 低版本框架、库漏洞
  安全方法: 此类安全问题应使用稳定的高版本框架、库进行开发。2.2 Command Injection
  安全方法: 无法规避此类功能时,应使用白名单控制:if(isset($_POST["target"])) { $target = $_POST["target"]; switch ($target) { case "www.protect.domain": echo "" . shell_exec("nslookup www.protect.domain") . ""; break; case "web.protect.domain": echo "" . shell_exec("nslookup web.protect.domain") . ""; break; ... default: echo "" . shell_exec("nslookup www.protect.domain") . ""; } }2.3 SQL Injection
  安全方法:
  注意: 不论项目是否使用了框架,涉及到的表名、字段名用户可控时,均应先使用白名单对此类数据进行处理:switch ($order){ case "id": $order="id"; break; case "name":$order="name"; break; default :$order="id"; }
  a、未使用框架时,可使用安全SDK项目提供的安全方法://查询 $result=$this->db->select()->from("table_name")->where("id","=",$id)->execute()->fetchAll(); //删除 $result=$this->db->delete()->from("table_name")->where("name","like","%".$name."%")->execute(); //插入 $result=$this->db->insert(array("name","age"))->into("table_name")->values(array($name,$age))->execute(); //更新 $result=$this->db->update(array("name" => $name))->table("table_name")->where("id", "=", $id)->execute();
  b、使用Yii、laravel、CodeIgniter框架时,可使用框架自带的数据库访问方法。
  Yii 2.0//查询 Users::find()->where(["id"=>$id])->orderBy("name")->select("id,name")->one(); //插入 $user=new Users(); $user->age=$age; $user->name=$name; $user->save(); //单条更新 $use=Users::find()->where(["id"=>$id])->orderBy("name")->select("id,name")->one(); $use->name=$name; $use->save(); //多条更新 $result=Users::find()->where([">","id",$id])->orderBy("name")->select("id,name")->all(); foreach ($result as $item){ $item->name=$name; $item->save(); } //删除 Users::deleteAll(["id"=>$id]);
  Laravel//查询 DB::table("table_name")->where("id",$id)->orderBy("id")->get(); //插入 DB::table("table_name")->insert(["name" => $name, "age" => $age]); //更新 DB::table("table_name")->where("id", $id)->update(["name" => $name]); //删除 DB::table("table_name")->where("age", $age)->delete();
  CodeIgniter//查询 $result = $this->db->select("*")->from("table_name")->where("userid", $userid)->order_by("id")->get(); //插入 $this->db->insert("table_name", array("title" => $title, "userid" => $userid)); //更新 $this->db->where("id",$id)->update("table_name", array("name" => $title, "age" => $age)); //删除 $this->db->where("id", $id)->delete("table_name");2.4 XSS
  安全方法:
  a、用户可控数据不需存储直接响应的,应编码输出。// html实体编码输出 $this->securityUtil->encodeForHTML($data); // javascript编码输出 $this->securityUtil->encodeForJavaScript($data)
  b、用户可控数据需存储展示或用于其他系统展示的,应过滤危险字符。$this->securityUtil->purifier($_GET["data"]);
  注意: 输入过滤会改变用户输入。应结合具体业务场景搭配使用输入过滤、输出编码。2.5 CSRF
  安全方法:
  前端应从cookie中获取在认证通过后植入的csrf_token,并以POST方式提交包含csrf_token值的请求,前端代码如下:function getCookie() { var value = "; " + document.cookie; var parts = value.split("; csrf_token="); if (parts.length == 2) return parts.pop().split(";").shift(); } $.ajax({ type: "post", url: "/xxxx", data: {csrf_token:getCookie()}, dataType: "json", success: function (data) { if (data.ec == 200) { //do something } } });
  后端应从POST请求体中提取csrf_token参数值,进行校验,代码如下:if(!$this->securityUtil->verifyCSRFToken()){ return ; //csrf token 校验失败 } // 开始处理业务逻辑 注意: 受csrf_token生成方式影响,当存在XSS时,会导致全局CSRF防护措施失效。2.6 URL Redirect
  安全方法: 此类安全问题服务端应根据具体的业务需求防止不安全的重定向:
  a、如果跳转后的链接比较少且比较固定,那么可以在服务端对参数进行白名单限制,非白名单里面的URL禁止跳转。$index=intval($_GET["index"]); switch($index){ case 1: $url="https://www.protect.domain/"; break; case 2: $url="https://web.protect.domain/"; break; ... default: $url="https://web.protect.domain/"; } header("Location:".$url); 当链接比较多时,可根据索引从数据库检索。
  b、如仅希望在当前域跳转,或因业务需要,跳转的链接经常变化且比较多,应做个二次确认页,对非当前域的链接,提示用户将跳转到其他网站:$white=[".protect.domain"]; //校验是否为信任域 if(!$this->securityUtil->verifyRedirectUrl($url,$white)){ // 非信任域名,提供二次确认页 } // 开始处理业务逻辑2.7 路径可控
  安全方法: 无法规避外界指定路径时,应使用白名单处理:$directory = $_GET["directory"]; switch ($directory) { // $directory重新赋值 case "./image":$directory="./image"; break; case "./page":$directory="./page"; break; ... default:$directory="./image"; } while($line = readdir($directory)) { //do something }2.8 Code Injection
  安全方法: 无法规避此类功能时,应精确匹配用户的提交数据:$name=strval($_POST["name"]); $regex="/^[a-zA-Z0-9]{3,20}$/"; if(preg_match($regex,$name,$matches) && $matches[0]===$name) { eval ("echo "" . $name . "";"); }2.9 Xpath Injection
  安全方法: 此类安全问题应精确匹配用户输入:if(isset($_POST["login"]) && $_POST["login"]){ if(isset($_POST["password"]) && $_POST["password"]){ $login = strval($_POST["login"]); $password = strval($_POST["password"]); $xml = simplexml_load_file("./heroes.xml"); $regex="/^[a-zA-Z0-9]{3,20}$/"; if(preg_match($regex,$login,$match_login) && $match_login[0]===$login){ if(preg_match($regex,$password,$match_password) && $match_password[0]===$password){ $result = $xml->xpath("/heroes/hero[login= "" . $login . "" and password= "" . $password . "" ]"); //业务逻辑 } } } }2.10 资源泄露
  安全方法: 此类安全问题应在相关操作完成后释放资源:$file = fopen("file.txt", "w") or die("Unable to open file!"); ... //关闭由fopen()函数打开的文件 fclose($file);2.11 XXE
  安全方法: 此类安全问题应在解析XML数据时显式禁止加载外部实体://禁止加载外部实体 libxml_disable_entity_loader(true); //解析xml数据 $xml = simplexml_load_string($data);2.12 SSRF
  安全方法: 应校验传入ip地址是否为内部ip:if (!$this->securityUtil->verifySSRFURL($url)) { return ; //内部ip } //开始处理业务逻辑2.13 敏感信息泄露
  安全方法: 此类安全问题应在代码上线之前删除注释信息(特别是敏感信息),合理设置忽略文件:
  a、gitlab/github
  根据目录新建文档 .gitignore,内容可参考.gitignore
  b、SVN
  新建文档.svnignore,内容可参考.gitignore,执行:svn propset svn:ignore -R -F .svnignore .
  注意: 当使用add的时候,禁止使用:svn add *
  这样会把忽略中的文件也添加到仓库。应使如下命令:svn add --force . 2.14 越权漏洞
  安全方法: 涉及到用户数据的增删改查,应校验数据归属:$articleId=$_GET["articleId"]; //用户登录状态下,从session取出用户唯一标识userid $userId = session("userId"); ... //关联用户信息执行数据库操作 $stmt = $db->prepare("UPDATE articles SET del_flag=1 WHERE articleId=? AND userId=?"); $stmt->bind_param("ss",$articleId, $userid); $stmt->execute(); 2.15 MongoDB Injection
  安全方法:
  涉及到MongoDB的操作,应禁用execute方法,校验数据类型:$appId = $this->request->post("appId"); $num = $this->request->post("num"); ... //校验数据类型 if(!is_array($appId)&&!is_array($num)) { $criteria = ["appId" => $appId, "num" => $num]; $ret = $this->mongodb->findOne($criteria); }
  预期数据类型明确的(如商品数量),应在接收用户提交数据时直接强制数据类型转换,避免因校验不严谨可能带来的其他问题。2.16 弱类型漏洞
  安全方法:
  注意:
  a、涉及多字符串拼接进行md5运算时,应在各拼接字符串之间添加分隔符://避免md5("1234"."14"."234")===md5("1234"."1"."4234") md5($secret . "|" . $uid . "|" . $code);
  b、涉及到函数返回结果既可能是布尔值(FALSE),也可能是等同于布尔值(FALSE)的非布尔值且返回结果用于判断时,需显式判断执行结果
  以内置函数strpos为例:int strpos ( string $haystack , mixed $needle [, int $offset = 0 ] )
  该函数:
  1)返回$needle在$haystack中首次出现的数字位置;
  2)未找到时返回布尔值FALSE;
  3)当$needle在$haystack起始位置出现时,会返回0.
  则安全编码应为:$domain="https://www.protect.domain"; //禁止 if(!strpos($domain,"https")) 或 if(strpos($domain,"https")!=false)的方式 if(strpos($domain,"https")!==false){ //处理业务逻辑 }
  此类安全问题应使用=== 代替 == , !== 代替 !=。if (isset($_GET["id"]) && isset($_GET["userId"])) { $id = strval($_GET["id"]); $userId = strval($_GET["userId"]); //防止出现 md5("240610708")==md5("QNKCDZO") if (md5($id) !== md5($userId)) { return ; } //业务逻辑 }2.17 任意文件上传
  安全方法: 此类安全问题应校验上传文件大小、后缀、类型等是否符合要求:$config=array("limit"=>5 * 1024 * 1024, //允许上传的文件最大大小 "type"=>array( //允许的上传文件后缀及MIME "gif"=>"image/gif", "jpg"=>"image/jpeg", "png"=>"image/png") ); $file = $_FILES["file"]; $data=$this->securityUtil->verifyUploadFile($file, $config); if($data["flag"]!==true){ return; //上传失败 } //生成新的文件名拼接$data["ext"]上传到文件服务器2.18 本地文件包含
  安全方法: 无法规避外界指定文件名时,应使用白名单处理:$filename =$_GET["filename"]; switch ($filename) { case "lfi.txt":include("./lfi.txt"); break; ... default:include("./notexists.txt"); }2.19 并发问题
  安全方法:
  php+mysql(InnoDB、REPEATABLE-READ)
  此类安全问题在已使用事务的前提下,应使用悲观锁或乐观锁解决:
  悲观锁:mysqli_query($conn, "BEGIN"); $rs = mysqli_query($conn, "SELECT num FROM oversold WHERE id = 1 FOR UPDATE "); //for UPDATE $row = mysqli_fetch_array($rs); $num = $row[0]; if($num>0) { //do something mysqli_query($conn, "UPDATE oversold SET num = num - 1 WHERE id = 1"); } if(mysqli_errno($conn)) { mysqli_query($conn, "ROLLBACK"); } else { mysqli_query($conn, "COMMIT"); } mysqli_close($conn); SELECT … FOR UPDATE加悲观锁,保证总是获取最新的数据,适合写入频繁的场景.
  乐观锁:
  需使用一个新的字段version保存版本号:mysqli_query($conn, "BEGIN"); $result = mysqli_query($conn, "SELECT num,version FROM oversold WHERE id = 1 "); $row = mysqli_fetch_array($result); $num = $row[0]; $version=$row[1]; if($num>0) { //do something $stmt=$conn->prepare("UPDATE oversold SET num = num - 1,version=version+1 WHERE id = 1 AND version= ? "); $stmt->bind_param("i",$version); $stmt->execute(); } if(mysqli_errno($conn)) { mysqli_query($conn, "ROLLBACK"); } else { mysqli_query($conn, "COMMIT"); } mysqli_close($conn);
  乐观锁比较适合数据修改比较少,读取比较频繁的场景。
  注意: 悲观锁会带来比较大的性能开销,而乐观锁可能会读取到脏数据,具体采用哪种加锁方式可根据具体业务场景确定。
  php+redis
  当redis版本不小于2.6.12时,应使用set指令限流避免并发问题。set指定用法如下:redis > SET KEY VALUE [EX seconds] [PX milliseconds] [NX|XX]   EX seconds - 设置指定的过期时间,单位为秒。   PX milliseconds - 设置指定的过期时间,单位为毫秒。   NX - 仅当KEY不存在时,设置KEY的值为VALUE。   XX - 仅当KEY存在时,设置KEY的值为VALUE。
  代码示例:$res=$redis->set($key, $value, ["nx", "px"=>$ps]); if(!$res){ throw new Exception("操作太快了,请稍后再试!"); }//开始处理业务逻辑
  以上代码,在$ps毫秒内,对指定的$key,仅允许执行一次业务逻辑。
  注意: 涉及到的key应结合具体业务场景注意key过期时间的设置,防止key的膨胀。2.20 WebSocket跨站劫持
  安全方法: 此类安全问题服务端应校验Origin头:$origin="https://www.protect.domain/"; ... function CheckOrigin(){ if (array_key_exists("Origin", $_SERVER)) { $value = $_SERVER["Origin"]; if($origin===$value){ return ture; } } return false; }

华为又增新机,具备5G芯片四摄后环,下个月发布据媒体透漏,华为将会在下个月发布新一代的Nova9系列,另外网上也曝光了华为nova9系列新机的外观。从外观上来看,这款手机采用的是双孔曲面屏四摄后环,造型设计与荣耀50系列很类似分享8个好用到爆的App,让你的手机瞬间变成黑科技大家好我是非凡资源李李今天我给大家分享8个好用到爆的App,让你的手机瞬间变成黑科技!一。安卓Alook浏览器支持系统AndroidiOS安装平台应用宝AppStoreiOS系统上开学季好物推荐性价比高的学生蓝牙耳机现在不少学生党都购买蓝牙耳机的想法,但学生党如何挑选到合适自己的呢?学生党购物一看质量二看性价比,所以,在这里就整理了一些质量好性价比高的无线蓝牙耳机!一Xisem西圣Ava推荐指iOS14。7。1系统更新,用户反馈部分iPhone信号无服务近日,根据外媒报道,在几周前苹果发布了iOS14。7。1正式版,修复了AppleWatch解锁漏洞,并解决了一个可以被主动利用的安全漏洞。现在,一些升级到iOS14。7。1的iPh姚婷被华为看中的天才少女,年薪156万,她有什么过人之处?156万的年薪是很多人穷极一生无法达到,或是想都不敢想的事情,然而这是华为给天才少女姚婷开出的薪资。那么姚婷究竟是何方神圣,能够一毕业就让华为迫不及待地开出高价年薪,想把姚婷招揽旗大众最便宜的电动车,ID。3能否成为年轻人新宠随着国家能源机构的调整,纯电汽车也将迎来新的发展风口,除了比亚迪广汽新能源蔚来等本土车企外,特斯拉大众丰田也在如火如荼推进新能源汽车的发展规划。继ID。4ID。6之后,大众汽车在新手机好评榜排名全球第一的小米全军覆没,华为新机未进前五现如今各大手机厂商为了增强市场竞争力,在配置外观方面都做到了尽善尽美,此时好评率就成为了用户考虑的一大重要因素,7月份的手机好评榜隆重登场,全球第一的小米全军覆没,前五中也未见华为被遗忘的骁龙888手机,屏下摄像120Hz55W6400万双主摄降价600智能手机行业竞争激烈,现在国内手机市场主要是华米OV,而之前很火的中兴在手机业务方面逐渐边缘化了,不过也一直在推出新的机型,例如今天要说的这款骁龙888旗舰机就来自中兴的中兴Axo外行买电脑如何选?最简单两句话说清楚说起选购笔记本,可能有的朋友觉得不知道如何选择,不知道应该去看哪些方面,其实,并不复杂。首先,笔记本分两种,玩游戏为主的和工作为主的。买笔记本时,主要需要看的地方是CPU影响电脑的预算10002000元内有什么手机值得买?hello,大家好,我是山外。2021年已经过去一半了,是时候进行上半年中手机盘点了,可能有很多朋友也需要更换手机了。那么预算10002000元内,有什么手机值得我们购买呢?本次手NANK南卡N2S,音质出众,告别电量恐慌症前言最近抖音热搜的梗,因牛郎织女没有打疫苗取消七夕节,很搞笑但是也很实际。当下来说疫情局势紧张,真的不建议大家出门约会,吃饭,去人多的地方聚集。对于我而言,给她选择一件好的礼物,或
科技助力出行来源人民网人民日报海外版电子驾驶证近日在全国全面推行,这意味着电子驾驶证与纸质驾驶证具有同等效力,司机在没有带实体证件的情况下,可以在线亮证,通过电子证件接受查验等。驾驶证电子化已韶音OpenMove骨传导运动蓝牙耳机,让运动变得更快乐很多人喜欢做运动挤公交坐地铁的时候佩戴蓝牙耳机,因为这样方便使用。但是,传统的蓝牙耳机,因为塞在耳朵里面,容易给人一种不适合,特别是长时间佩戴,总会出现胀痛感。如果运动的时候戴着入北京加快建设全球数字经济标杆城市工业互联网平台数量接入资源量国家级智能制造系统方案供应商数量均居全国第一,2021年,北京加快建设全球数字经济标杆城市,数字经济高速发展,前三季度数字经济总量达12418亿元,已占数字经济潮涌,城市准备好了吗来源解放日报原标题数字经济潮涌,城市准备好了吗近年来,全球数字经济体量不断增加,在国民经济中地位持续提升,已成为世界经济增长潜力所在。不久前,中国提出促进数字时代互联互通倡议,支持净水器哪个牌子质量好,性价比高的净水器多伦斯美的沁园安吉尔哪个更好一点?我08年在青岛的时候就接触过这一行业,现在已经十年了,技术还是那时候的技术。净水器基本上是分两种,一种是超滤膜净水,一种是反渗透Ro膜净水,简单说Ro膜过滤出来的就是纯净水,他们的华为高端旗舰回归性价比,麒麟9000鸿蒙徕卡三摄,已跌破5000元对于华为来说目前只能推出4G手机,前几天华为刚发布了一款新旗舰P50pocket,作为一款顶级折叠手机,该机搭载骁龙888处理器,依旧支持4G网络。目前好的一点是,华为可以采购高通性能比麒麟9000更强,售价却不到P50Pro一半,新款5G旗舰定价亲民最近两年,为了阻止华为在科技领域高速发展,老美进行了多次无理的打压,导致华为手机的市场份额出现了明显的下滑。尽管华为在2021年推出了不少新款手机,但由于大多数都是4G手机,又不愿6nm5G芯片平台客户量产,展锐楚庆已跻身先进半导体技术第一梯队智东西(公众号zhidxcom)作者云鹏编辑心缘智东西12月27日消息,今天下午,展锐通过一场发布会正式宣布,展锐第二代5G芯片平台唐古拉T770唐古拉T760已经实现客户产品量产展锐第二代5G芯片平台实现客户产品量产展锐今天在线上发布会上宣布,第二代5G芯片平台唐古拉T770唐古拉T760实现客户产品量产。展锐CEO楚庆表示第二代5G芯片平台实现客户产品量产,体现了展锐在半导体技术和通信技术上解析数字经济的底座科技EDA新思科技未来已来,只是尚未流行。iPhone13一经发布,即供不应求。该机型搭载最新A15芯片,采用5nm工艺制造,集成150亿个晶体管。在这款仅100平方毫米左右的方寸之间,晶体数字人民币的畅想比特币和数字人民币比特币是大资本无国无家逐利的产物锚定的是技术数字人民币是主权货币代表的国家信用两者不可相提并论封建王朝的规律皇权官阶百姓是三角共生关系生产资料是土地皇帝建立官阶体