原创

离站提示JS工具:Ouibounce

离站提示JS工具:Ouibounce,当离开网站时给出一个提醒,从jobbole看到的.tip:和bootstrap的model 结合时要在参数的callback中 手动 用$('#share').modal();触发,官网没说,这个要注意.demo如下:[repo owner=”carlsednaoui” name=”ouibounce”]

开源的电子邮件模板

开源的电子邮件模板,质量相当的高.网址: https://www.sendwithus.com/resources/templates 

git在线学习

在线学习git命令,15分钟就能会.网址: https://try.github.io

tabIndent.js让你在Textarea中也能用Tab键

很多程序员都会习惯性的在Textarea中按Tab键进行缩进,结果是——焦点移动到下一个控件去了。tabIndent.js就是一个专门用来解决这个问题的小巧脚本,只需要在页面中引用它,并调用tabIndent.renderAll();即可处理class为tabindent的Textarea。[repo owner=”julianlam” name=”tabIndent.js”]

Web 热图库 Heatmap.js

Heatmap.js用来生成基于用户自定义数据上的web 热图,内嵌html5 画布元素。可根据以下数据来源绘制热图:静态数据鼠标移动鼠标点击支持浏览器:Firefox 3.6+, Chrome 10, Safari 5, Opera 11 and IE 9+.[repo owner=”pa7” name=”heatmap.js”]

上传攻击框架

作者是阿里巴巴安全工程师@卷成团变成个球的CasperKid君 。文章是CK在2011年编写的,在当下仍具有非常重要参考价值。很多web 站点存在上传验证方式不严格的安全缺陷,是web 渗透中关键的突破口 ,站长小伙伴要注意哦!0x00 上传检测流程概述0x01 客户端检测绕过(javascript 检测)0x02 服务端检测绕过(MIME 类型检测)0x03 服务端检测绕过(目录路径检测)0x04 服务端检测绕过(文件扩展名检测)黑名单检测白名单检测.htaccess 文件攻击0x05 服务端检测绕过(文件内容检测)文件幻数检测文件相关信息检测文件加载检测0x06 解析攻击网络渗透的本质直接解析本地文件包含解析.htaccess 解析web 应用程序解析漏洞及其原理0x07 上传攻击框架轻量级检测绕过攻击路径/扩展名检测绕过攻击文件内容性检测绕过攻击上传攻击框架结语下载: Upload_Attack_Framework.pdf

动物之魂

动物之魂。丨俄罗斯插画家 Alexandra Khitrova 的空灵系列插画.

hello 2015

hello 2015,我们在上线!

Web安全之SQL注入攻击技巧与防范

from: http://www.plhwin.com/2014/06/13/web-security-sql/Web安全简史在Web1.0时代,人们更多是关注服务器端动态脚本语言的安全问题,比如将一个可执行脚本(俗称Webshell)通过脚本语言的漏洞上传到服务器上,从而获得服务器权限。在Web发展初期,随着动态脚本语言的发展和普及,以及早期工程师对安全问题认知不足导致很多”安全血案”的发生,至今仍然遗留下许多历史问题,比如PHP语言至今仍然无法从语言本身杜绝「文件包含漏洞」(参见这里),只能依靠工程师良好的代码规范和安全意识。伴随着Web2.0、社交网络、微博等一系列新型互联网产品的兴起,基于Web环境的互联网应用越来越广泛,Web攻击的手段也越来越多样,Web安全史上的一个重要里程碑是大约1999年发现的SQL注入攻击,之后的XSS,CSRF等攻击手段愈发强大,Web攻击的思路也从服务端转向了客户端,转向了浏览器和用户。在安全领域,一般用帽子的颜色来比喻黑客的善与恶,白帽子是指那些工作在反黑客领域的技术专家,这个群体是”善”的的象征;而黑帽子则是指那些利用黑客技术造成破坏甚至谋取私利造成犯罪的群体,他们是”恶”的代表。“白帽子”和”黑帽子”是两个完全对立的群体。对于黑帽子而言,他们只要找到系统的一个切入点就可以达到入侵破坏的目的,而白帽子必须将自己系统所有可能被突破的地方都设防,以保证系统的安全运行。这看起来好像是不公平的,但是安全世界里的规则就是这样,可能我们的网站1000处都布防的很好,考虑的很周到,但是只要有一个地方疏忽了,攻击者就会利用这个点进行突破,让我们另外的1000处努力白费。常见攻击方式一般说来,在Web安全领域,常见的攻击方式大概有以下几种:1、SQL注入攻击2、跨站脚本攻击 - XSS3、跨站伪造请求攻击 - CSRF4、文件上传漏洞攻击5、分布式拒绝服务攻击 - DDOS说个题外话,本来这篇文章一开始的标题叫做 「Web安全之常见攻击方法与防范」,我原本想把上面的这5种方法都全部写在一篇文章里,可是刚写完第一个SQL注入攻击的时候,就发现文章篇幅已经不短了,又很难再进行大幅度的精简,所以索性把Web安全分成一个系列,分多篇文章来呈现给大家,下面你看到的就是第一篇「Web安全之SQL注入攻击的技巧与防范」。SQL注入常见攻击技巧SQL注入攻击是Web安全史上的一个重要里程碑,它从1999年首次进入人们的视线,至今已经有十几年的历史了,虽然我们现在已经有了很全面的防范对策,但是它的威力仍然不容小觑,SQL注入攻击至今仍然是Web安全领域中的一个重要组成部分。以PHP+MySQL为例,让我们以一个Web网站中最基本的用户系统来做实例演示,看看SQL注入究竟是怎么发生的。1、创建一个名为demo的数据库:CREATE DATABASE `demo` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;2、创建一个名为user的数据表,并插入1条演示数据:CREATE TABLE `demo`.`user` (`uid` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '用户uid',`username` VARCHAR( 20 ) NOT NULL COMMENT '用户名',`password` VARCHAR( 32 ) NOT NULL COMMENT '用户密码') ENGINE = INNODB;INSERT INTO `demo`.`user` (`uid`, `username`, `password`) VALUES ('1', 'plhwin', MD5('123456'));实例一通过传入username参数,在页面打印出这个会员的详细信息,编写 userinfo.php 程序代码:<?phpheader('Content-type:text/html; charset=UTF-8');$username = isset($_GET['username']) ? $_GET['username'] : '';$userinfo = array();if($username){ //使用mysqli驱动连接demo数据库 $mysqli = new mysqli("localhost", "root", "root", 'demo'); $sql = "SELECT uid,username FROM user WHERE username='{$username}'"; //mysqli multi_query 支持执行多条MySQL语句 $query = $mysqli->multi_query($sql); if($query){ do { $result = $mysqli->store_result(); while($row = $result->fetch_assoc()){ $userinfo[] = $row; } if(!$mysqli->more_results()){ break; } } while ($mysqli->next_result()); }}echo '<pre>',print_r($userinfo, 1),'</pre>';上面这个程序要实现的功能是根据浏览器传入的用户名参数,在页面上打印出这个用户的详细信息,程序写的这么复杂是因为我采用了mysqli的驱动,以便能使用到 `multi_query` 方法来支持同时执行多条SQL语句,这样能更好的说明SQL注入攻击的危害性。假设我们可以通过 http://localhost/test/userinfo.php?username=plhwin 这个URL来访问到具体某个会员的详情,正常情况下,如果浏览器里传入的username是合法的,那么SQL语句会执行:SELECT uid,username FROM user WHERE username='plhwin'但是,如果用户在浏览器里把传入的username参数变为 `plhwin';SHOW TABLES-- hack`,也就是当URL变为 `http://localhost/test/userinfo.php?username=plhwin';SHOW TABLES-- hack` 的时候,此时我们程序实际执行的SQL语句变成了:SELECT uid,username FROM user WHERE username='plhwin';SHOW TABLES-- hack'_注意:在MySQL中,最后连续的两个减号表示忽略此SQL减号后面的语句,我本机的MySQL版本号为5.6.12,目前几乎所有SQL注入实例都是直接采用两个减号结尾,但是实际测试,这个版本号的MySQL要求两个减号后面必须要有空格才能正常注入,而浏览器是会自动删除掉URL尾部空格的,所以我们的注入会在两个减号后面统一添加任意一个字符或单词,本篇文章的SQL注入实例统一以 `-- hack` 结尾。_经过上面的SQL注入后,原本想要执行查询会员详情的SQL语句,此时还额外执行了 SHOW TABLES; 语句,这显然不是开发者的本意,此时可以在浏览器里看到页面的输出:Array( [0] => Array ( [uid] => 1 [username] => plhwin )[1] =&gt; Array ( [Tables_in_demo] =&gt; user ))你能清晰的看到,除了会员的信息,数据库表的名字`user`也被打印在了页面上,如果作恶的黑客此时将参数换成 `plhwin';DROP TABLE user-- hack`,那将产生灾难性的严重结果,当你在浏览器中执行`http://localhost/test/userinfo.php?username=plhwin';DROP TABLE user-- hack` 这个URL后,你会发现整个 `user` 数据表都消失不见了。通过上面的例子,大家已经认识到SQL注入攻击的危害性,但是仍然会有人心存疑问,MySQL默认驱动的mysql_query方法现在已经不支持多条语句同时执行了,大部分开发者怎么可能像上面的演示程序那样又麻烦又不安全。是的,在PHP程序中,MySQL是不允许在一个mysql_query中使用分号执行多SQL语句的,这使得很多开发者都认为MySQL本身就不允许多语句执行了,但实际上MySQL早在4.1版本就允许多语句执行,通过PHP的源代码,我们发现其实只是PHP语言自身限制了这种用法,具体情况大家可以看看这篇文章「PHP+MySQL多语句执行」。实例二如果系统不允许同时执行多条SQL语句,那么SQL注入攻击是不是就不再这么可怕呢?答案是否定的,我们仍然以上面的user数据表,用Web网站中常用的会员登录系统来做另外一个场景实例,编写程序login.php,代码如下:<?phpif($_POST){…

Web应用的缓存设计模式

from: http://robbinfan.com/blog/38/orm-cache-sumupORM缓存引言从10年前的2003年开始,在Web应用领域,ORM(对象-关系映射)框架就开始逐渐普及,并且流行开来,其中最广为人知的就是Java的开源ORM框架Hibernate,后来Hibernate也成为了EJB3的实现框架;2005年以后,ORM开始普及到其他编程语言领域,其中最有名气的是Ruby on rails框架的ORM - ActiveRecord。如今各种开源框架的ORM,乃至ODM(对象-文档关系映射,用在访问NoSQLDB)层出不穷,功能都十分强大,也很普及。然而围绕ORM的性能问题,也一直有很多批评的声音。其实ORM的架构对插入缓存技术是非常容易的,我做的很多项目和产品,但凡使用ORM,缓存都是标配,性能都非常好。而且我发现业界使用ORM的案例都忽视了缓存的运用,或者说没有意识到ORM缓存可以带来巨大的性能提升。ORM缓存应用案例我们去年有一个老产品重写的项目,这个产品有超过10年历史了,数据库的数据量很大,多个表都是上千万条记录,最大的表记录达到了9000万条,Web访问的请求数每天有300万左右。老产品采用了传统的解决性能问题的方案:Web层采用了动态页面静态化技术,超过一定时间的文章生成静态HTML文件;对数据库进行分库分表,按年拆表。动态页面静态化和分库分表是应对大访问量和大数据量的常规手段,本身也有效。但它的缺点也很多,比方说增加了代码复杂度和维护难度,跨库运算的困难等等,这个产品的代码维护历来非常困难,导致bug很多。进行产品重写的时候,我们放弃了动态页面静态化,采用了纯动态网页;放弃了分库分表,直接操作千万级,乃至近亿条记录的大表进行SQL查询;也没有采取读写分离技术,全部查询都是在单台主数据库上进行;数据库访问全部使用ActiveRecord,进行了大量的ORM缓存。上线以后的效果非常好:单台MySQL数据库服务器CPU的IO Wait低于5%;用单台1U服务器2颗4核至强CPU已经可以轻松支持每天350万动态请求量;最重要的是,插入缓存并不需要代码增加多少复杂度,可维护性非常好。总之,采用ORM缓存是Web应用提升性能一种有效的思路,这种思路和传统的提升性能的解决方案有很大的不同,但它在很多应用场景(包括高度动态化的SNS类型应用)非常有效,而且不会显著增加代码复杂度,所以这也是我自己一直偏爱的方式。因此我一直很想写篇文章,结合示例代码介绍ORM缓存的编程技巧。今年春节前后,我开发自己的个人网站项目,有意识的大量使用了ORM缓存技巧。对一个没多少访问量的个人站点来说,有些过度设计了,但我也想借这个机会把常用的ORM缓存设计模式写成示例代码,提供给大家参考。我的个人网站源代码是开源的,托管在github上:robbin_siteORM缓存的基本理念我在2007年的时候写过一篇文章,分析ORM缓存的理念:ORM对象缓存探讨 ,所以这篇文章不展开详谈了,总结来说,ORM缓存的基本理念是:以减少数据库服务器磁盘IO为最终目的,而不是减少发送到数据库的SQL条数。实际上使用ORM,会显著增加SQL条数,有时候会成倍增加SQL。数据库schema设计的取向是尽量设计 细颗粒度 的表,表和表之间用外键关联,颗粒度越细,缓存对象的单位越小,缓存的应用场景越广泛尽量避免多表关联查询,尽量拆成多个表单独的主键查询,尽量多制造 n + 1 条查询,不要害怕“臭名昭著”的 n + 1 问题,实际上 n + 1 才能有效利用ORM缓存利用表关联实现透明的对象缓存在设计数据库的schema的时候,设计多个细颗粒度的表,用外键关联起来。当通过ORM访问关联对象的时候,ORM框架会将关联对象的访问转化成用主键查询关联表,发送 n + 1条SQL。而基于主键的查询可以直接利用对象缓存。我们自己开发了一个基于ActiveRecord封装的对象缓存框架:second_level_cache ,从这个ruby插件的名称就可以看出,实现借鉴了Hibernate的二级缓存实现。这个对象缓存的配置和使用,可以看我写的ActiveRecord对象缓存配置 。下面用一个实际例子来演示一下对象缓存起到的作用:访问我个人站点的首页。 这个页面的数据需要读取三张表:blogs表获取文章信息,blog_contents表获取文章内容,accounts表获取作者信息。三张表的model定义片段如下,完整代码请看models :class Account < ActiveRecord::Base acts_as_cached has_many :blogsendclass Blog < ActiveRecord::Base acts_as_cached belongs_to :blog_content, :dependent => :destroy belongs_to :account, :counter_cache => trueendclass BlogContent < ActiveRecord::Base acts_as_cachedend传统的做法是发送一条三表关联的查询语句,类似这样的:SELECT blogs.*, blog_contents.content, account.name FROM blogs LEFT JOIN blog_contents ON blogs.blog_content_id = blog_contents.id LEFT JOIN accounts ON blogs.account_id = account.id往往单条SQL语句就搞定了,但是复杂SQL的带来的表扫描范围可能比较大,造成的数据库服务器磁盘IO会高很多,数据库实际IO负载往往无法得到有效缓解。我的做法如下,完整代码请看home.rb :@blogs = Blog.order('id DESC').page(params[:page])这是一条分页查询,实际发送的SQL如下:SELECT * FROM blogs ORDER BY id DESC LIMIT 20转成了单表查询,磁盘IO会小很多。至于文章内容,则是通过blog.content的对象访问获得的,由于首页抓取20篇文章,所以实际上会多出来20条主键查询SQL访问blog_contents表。就像下面这样:DEBUG - BlogContent Load (0.3ms) SELECT `blog_contents`.* FROM `blog_contents` WHERE `blog_contents`.`id` = 29 LIMIT 1DEBUG - BlogContent Load (0.2ms) SELECT `blog_contents`.*…