近些天做一个WEB应用程序的时候被人进行了SQL注入,本来是觉得,POD模块使用了参数化查询就不会存在这种被SQL注入的情况,事实告诉我,我还是太年轻了。

至于SQL注入是什么,在这里就不再探讨,本质上是应用程序在编程过程中存在逻辑漏洞导致的SQL执行语句与我们想的不一致所触发的非授权访问。一般来说通过安装软/硬WAF能够较好的解决和处理这个问题,同时也需要应用程序猿在编程过程中能够有意识的避免这个问题的发生。

先看我之前写的SQL查询代码,这边PDO链接的代码就不放出了,已经建立的链接使用变量$db来表示。

	#php代码,关于SQL查询
	<?php
	$username = $_GET['username'];
	$password = $_GET['password'];
	$query = "select * from user where username='$username' and password='$password'";
	$stat = $db->prepare($query);
	$stat->execute();
	if(count($stat->fetchAll)){
		echo "用户登录成功!";
	}else{
		echo "用户登录失败!" ;
	}
	?>

在这边我们确实是使用PHP的PDO模块进行了SQL链接,但是本质上我们没有使用参数化查询。
我们需要知道PHP在执行代码prepare时,将会对query进行预编译处理。而本质上,我们传入的参数username和password也将同时进入语句内部。这将会导致预处理在本质上没有进行参数化的查询。
如果用户通过构造恶意参数,发送GET请求:
例如:
http://xxx.xxx.xx?username=admin&password='20%or1=‘1’–+
就可以实现绕过密码直接登陆用户名为admin的账号,这在网络安全中被称为永真绕过,这也是由于应用程序猿在编程中粗心大意所导致的问题。
同时,如果页面存在回显、response字段长度信息,那么可以通过构造恶意的SQL查询指令来对数据库中的内容进行拆解。拆解后数据存在泄漏的风险,严重的可以直接获得系统内部权限。
不过一般SQL和WEB应用服务器是分离的,也能够较大程度的保证WEB服务器的安全。

解决方案也很简单,查阅资料后得出结果,预处理的正确使用方法如下:

#php代码,关于SQL查询,已经进行预处理的优化,解决SQL注入问题
	<?php
	$username = $_GET['username'];
	$password = $_GET['password'];
	$query = "select * from user where username=? and password=?";
	$stat = $db->prepare($query);
	$stat->bindParm(1,$username);
	$stat->bindParm(2,$password);
	$stat->execute();
	if(count($stat->fetchAll)){
		echo "用户登录成功!";
	}else{
		echo "用户登录失败!" ;
	}
	?>