验证码的几个常见漏洞

5年前

把验证码存储在Cookie中

一般来说,我们会把验证码的值用Session存储起来,通过对比用户提交的验证码和Session中的验证码,就可以知道输入是否正确。由于Session会占用服务器资源,我曾经想过是否可以把验证码的值加密后存储在Cookie中。不过事实证明,这只是异想天开罢了。

假设验证码的值是a,通过sha1加密后得到的值为b = sha1(a),并且把b存储在Cookie中。而用户提交的验证码值为c,通过判断sha1(c)是否与b相等,可以知道输入的验证码是否正确。然而,Cookie是受客户端控制的。如果用户事先通过肉眼看到验证码的值是a,又从Cookie中得知此时的加密值为b,那么,他只要在提交前把Cookie的值修改为b,提交的验证码值为a,就可以永远通过验证。

没有进行非空判断

这种情况可以直接用代码来说明:

if (Request["captcha"] == Session["captcha"] as string)
{
    // 验证通过,继续操作
}
1460次阅读,3条评论

分析MySQL的授权许可

6年前

MySQL是开源软件,但开源不意味着免费,开源软件的使用应遵循该软件提供的使用授权许可。MySQL的授权许可是英文的,而且一直以来没有权威的中文译本,所以很多人都不清楚其中的细节。

最近我在做一些ASP.NET+MySQL的应用,特地对MySQL的授权许可进行了研究。

(以下说明,如有错误,欢迎指正)

使用MySQL作为数据库的应用是否会“被GPL”

MySQL开源软件(包括MySQL社区版数据库服务器、驱动程序和链接库等)是在GPL许可下提供的。GPL(General Public License)是一种开源许可,其大概的内容是:只要在一个软件中使用(“使用”指类库引用,修改后的代码或者衍生代码)GPL协议的产品,则该软件产品也必须采用GPL协议,即必须也开源。

应用程序是否也必须采用GPL进行开源,是由如何去使用MySQL决定的。如果把MySQL数据库内嵌到应用程序中,成为了应用程序内部的一部分,则整个应用程序都必须遵守GPL的规定。而对于大多数Web应用,数据库并不是跟应用程序绑在一起的,数据库跟应用程序是产品间相互协作的关系,这种情况就不在GPL的约束范围之内。

984次阅读,1条评论

微软发布PHP Manager For IIS 7

6年前

Windows环境下的软件一直以使用方便著称。昨天,微软发布了IIS Manager For IIS 7。这是一个图形化的PHP管理软件,可以在简化很多配置PHP环境的工作。

安装这个软件后(注意它仅支持IIS 7或以上版本),IIS的功能视图中就多了一个PHP Manager的图标。

IIS功能视图中的PHP Manager

双击进入PHP Manager后可以看到,其功能主要分为三大块:PHP SetupPHP SettingsPHP Extensions

862次阅读,1条评论

使用参数化查询防止SQL注入漏洞

7年前

SQL注入漏洞曾经是Web应用程序的噩梦,CMS、BBS、Blog无一不曾受其害。

SQL注入的原理

以往在Web应用程序访问数据库时一般是采取拼接字符串的形式,比如登录的时候就是根据用户名和密码去查询:

string sql = "SELECT TOP 1 * FROM [User] WHERE UserName = '" + userName + "' AND Password = '" + password + "'";

其中userName和password两个变量的值是由用户输入的。在userName和password都合法的情况下,这自然没有问题,但是用户输入是不可信的,一些恶意用户只要用一些技巧,就可以绕过用户名、密码登录。

假设password的值是"1' or '1' = '1",userName的值随便取,比如是"abc",那变量sql的值就是:

SELECT TOP 1 * FROM [User] WHERE UserName = 'abc' AND Password = '1' or '1' = '1'

由于'1' = '1'恒为真,因此只要User表中有数据,不管UserName、Password的值是否匹配,这条SQL命令准能查出记录来。就这样,登录系统就被破解了。

4372次阅读,3条评论

从表单数据创建实体对象

7年前

Web应用的基本流程就是通过表单提交数据到服务器,服务器端程序以这些数据建立实体对象,经过处理后更新到数据库。而从表单数据创建实体对象的过程通常是很麻烦的,必须考虑到以下几点:

  1. 创建什么类型的对象?
  2. 表单的各项数据如何映射到对象的各项属性?
  3. 提交到服务器的数据都是字符串类型的,要还原成对应属性的数据类型。

之前我就用泛型写了一个Request工具类。不过这个类仅仅是解决了第三个问题而已,而要解决前两个问题就得靠反射了。

要解决第一个问题,还得用泛型,也就是类型作为参数传入,由此得到这个通用函数的原型:

public class ReqHelper
{
  public static T GetEntity<T>()
  {

  }
}

而函数体的第一步,自然就是建立类型T的示例:

T entity = new T();

这段代码乍一看没错,但一编译就会报错,原因是编译器并不能确定T的构造函数的原型。因此还得用where关键字进一步约束T:

public static T GetEntity<T>() where T : new()
{
  T entity = new T();
}
603次阅读,1条评论

使用泛型打造Request工具类

7年前

在ASP.NET页面中可以使用Request对象获取指定参数的值,例如:

string value = Request["id"];

参数值都是string类型,但是进行处理的时候可能要转换成数字、日期等类型。

string value = Request["id"];
int id = Int32.Parse(value);

实际应用的时候还要考虑异常的情况。

string value = Request["id"];
int id;
Int32.TryParse(value, out id);

如果每个页面都这么写,显得非常麻烦,代码重复也很严重,还是封装成一个工具类吧。

public class ReqHelper
{
	public static string GetString(string paramName) { ... }
	public static int GetInt(string paramName) { ... }
	public static bool GetBool(string paramName) { ... }
	...
}
818次阅读,1条评论

EditPlus配置手记

7年前

最近打算换主IDE,主要原因是现在用的Dreamweaver太慢太占资源,特别是打开大文件的时候。而代替者就是EditPlus。下面简单记录一下如何把EditPlus配置成一个编程IDE。

首选项

无论是什么软件,一般都要先改全局设置,也就是首选项。

常规

常规

  • 还原最近文件的光标/标记/编码方式:这个一定要勾上,否则就不能保存代码折叠
  • 使用XHTML标签:标准化网页。
  • 自动关闭HTML标签:勾上这个以后,输入“<”后就会自动补全“>”,光标在两个字符之间。
6616次阅读,7条评论

IIS 7.5 下PHP(FastCGI模式)配置手记

7年前

自从有了FastCGI,IIS支持PHP变得非常简单。

版本选择

先到官网下载PHP 5.6,可以发现有4个版本:

  • VC11 x86 Non Thread Safe
  • VC11 x86 Thread Safe
  • VC11 x64 Non Thread Safe
  • VC11 x64 Thread Safe

官网已经注明,x64版本是实验性质的,所以还是用x86版吧。至于Thead Safe(线程安全)/Non Thead Safe(非线程安全),官网并没有说明各自用途何在。Google了一番以后,我找到了答案:FastCGI是单线程执行的,因而不需要线程安全版本,去掉线程安全的防护后可以提高执行效率;而ISAPI方式则是多线程模式,所以需要采用线程安全版本。综上所述,我们应下载 VC11 x86 Non Thread Safe 这个版本。

注意,这四个版本都是通过Visual Studio 2012编译器编译的,所以要先安装Visual C++ Redistributable for Visual Studio 2012,否则无法运行。此外,由于我们选用的是x86的php,所以Visual C++ Redistributable for Visual Studio 2012也要对应地安装x86版,千万不要因为系统是64位的就装了x64版。

3883次阅读,0条评论

使用JScript遍历Request表单参数集合

8年前

JScript下有一个Enumerator对象可以遍历集合。根据它的文档写了以下程序,可以遍历整个Request.QueryString集合:

var params = new Enumerator(Request.QueryString);
while (!params.atEnd()) {
  Response.Write(params.item() + ":" + Request.QueryString(params.item()) + "<br />");
  params.moveNext();
}

美中不足的是,Request对象本身不是集合,所以不能对Request对象进行遍历,下面这行代码会报错:

var params = new Enumerator(Request);
722次阅读,0条评论

使用JavaScriptSerializer进行JSON序列化

8年前

JSON是Javascript中常用的数据格式,然而,在.NET 2.0中没有内置序列化JSON的类,原因估计是当时Ajax尚未兴起。后来就有人写了一个Json.NET类库。.NET 3.5新增了一个把对象序列化为JSON字符串的类JavaScriptSerializer。这个类位于System.Web.Script.Serialization名字空间中(非Web项目需要添加System.Web.Extensions.dll引用),其使用方法也是非常简单的:

// 分类
public class Category
{
  public int CategoryId { get; set; } // 分类编号
  public string CategoryName { get; set; } // 分类名
}

Category testCategory = new Category()
{
  CategoryId = 1,
  CategoryName = "Test"
};

JavaScriptSerializer serializer = new JavaScriptSerializer();
Console.Write(serializer.Serialize(testCategory)); // 调用Serialize方法进行序列化
11698次阅读,0条评论