目录
- 1. 结合mysql数据库设计一个web登录页面
- 数据库sql搭建
- 项目结构如下:
- Login.html效果图如下:
- html代码
- php验证代码
- 2. 能够防住简单注入和宽字节注入
- 简单注入
- 双拼注入
- 宽字节注入
- 3. 能够基本防住手动注入和sqlmap攻击(测试案例)
- 防止手动注入
- 防御sqlmap攻击
- 4. 能够防止sql注入原因分析
- 使用js代码分析、处理并屏蔽客户端上的不安全字符,过滤字符串
- 使用正则表达式等方式替换、过滤传入的参数
- 使用php的sql过滤设置
- 总结
欢迎关注 『网络攻防CTF』 系列,持续更新中
欢迎关注 『网络攻防CTF』 系列,持续更新中
1. 结合mysql数据库设计一个web登录页面
数据库sql搭建
另存为sql_test.sql
文件导入即可
/*Navicat Premium Data TransferSource Server : localhostSource Server Type : MySQLSource Server Version : 50734Source Host : localhost:3306Source Schema : sql_testTarget Server Type : MySQLTarget Server Version : 50734File Encoding : 65001Date: 13/05/2022 10:15:53
*/SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (`username` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`pwd` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('admin', 'admin');SET FOREIGN_KEY_CHECKS = 1;
项目结构如下:
为了美观引用了layui框架(也可以没有,只是样式)
Login.html效果图如下:
输入用户名密码测试登陆。
html代码
layui文件可以在gitee官网上下载https://gitee.com/sentsin/layui
<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=gb2312"><title>防止SQL注入的登录页面</title><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"><title>基于layui框架的放sql注入网站</title><link rel="stylesheet" href="layui-master/src/css/layui.css"><link rel="stylesheet" href="layui-master/src/css/modules/code.css"><script src="layui-master/src/layui.js" type="text/javascript" charset="UTF-8"></script><script type="text/javascript">function Mycheck(str) {var mess = "不允许输入的字符:\r\n";var mark = "yes";if (str.indexOf(";") >= 0) {mark = "no";mess += " ; ";}if (str.indexOf("&") >= 0) {mark = "no";mess += " & ";}if (str.indexOf("<") >= 0) {mark = "no";mess += " < ";}if (str.indexOf(">") >= 0) {mark = "no";mess += " > ";}if (str.indexOf("--") >= 0) {mark = "no";mess += " -- ";}if (str.indexOf("/") >= 0) {mark = "no";mess += " / ";}if (str.indexOf("%") >= 0) {mark = "no";mess += " % ";}if (str.indexOf("'") >= 0) {mark = "no";mess += " ' ";}if (str.indexOf("#") >= 0) {mark = "no";mess += " # ";}if (mark == "no") {alert(mess);return false;} else returnreturn true;}</script></head><body style="font-size:12px">
<table width="382" border="0" align="center" cellpadding="0" cellspacing="0"><tr><td height="99" background="images/login_01.jpg"> </td></tr><tr><td height="160" bgcolor="#FEF7C3"><table class="layui-table" lay-size="lg" lay-even lay-skin="row" width="300" border="0" align="center"cellpadding="3" cellspacing="0"><form method='post' action='login.php' name="form1" onSubmit="Mycheck(form1.username.value)"><tr><td height="22" colspan="2" align="center"> </td></tr><tr><td height="22" align="right">mzh</td></tr><tr><td height="22" align="right">网工191</td></tr><tr><td height="22" align="right">19145120</td></tr><tr><td height="22" align="right">用户</td><td height="22"><input name="username" type="text" class="layui-input-inline" id="txt_name"size="18" maxlength="50"></td></tr><tr><td height="22" align="right">密码:</td><td height="22"><input name="passwd" type="password" class="layui-input-inline"id="txt_passwd" size="19" maxlength="50"></td></tr><tr><td height="22" colspan="2" align="center"><input name="login" type="submit" id="login"value="登 录"class="layui-btn layui-btn-radius layui-btn-warm"> <input type="reset" name="Submit2" value="重 置"class="layui-btn layui-btn-radius layui-btn-warm"></td></tr></form></table></td></tr>
</table>
<!-- Code injected by live-server -->
<script type="text/javascript">// <![CDATA[ <-- For SVG supportif ('WebSocket' in window) {(function () {function refreshCSS() {var sheets = [].slice.call(document.getElementsByTagName("link"));var head = document.getElementsByTagName("head")[0];for (var i = 0; i < sheets.length; ++i) {var elem = sheets[i];var parent = elem.parentElement || head;parent.removeChild(elem);var rel = elem.rel;if (elem.href && typeof rel != "string" || rel.length == 0 || rel.toLowerCase() =="stylesheet") {var url = elem.href.replace(/(&|\?)_cacheOverride=\d+/, '');elem.href = url + (url.indexOf('?') >= 0 ? '&' : '?') + '_cacheOverride=' + (new Date().valueOf());}parent.appendChild(elem);}}var protocol = window.location.protocol === 'http:' ? 'ws://' : 'wss://';var address = protocol + window.location.host + window.location.pathname + '/ws';var socket = new WebSocket(address);socket.onmessage = function (msg) {if (msg.data == 'reload') window.location.reload();else if (msg.data == 'refreshcss') refreshCSS();};if (sessionStorage && !sessionStorage.getItem('IsThisFirstTime_Log_From_LiveServer')) {console.log('Live reload enabled.');sessionStorage.setItem('IsThisFirstTime_Log_From_LiveServer', true);}})();} else {console.error('Upgrade your browser. This Browser is NOT supported WebSocket for Live-Reloading.');}// ]]>
</script>
</body></html>
php验证代码
<?phpsession_start();//开启session对话,必须在html前//post方法获取表单用户名,密码
$username = $_POST['username'];
$passwd = $_POST['passwd'];//连接数据库
$link = mysqli_connect('localhost','root','123456','sql_test');if (!$link)
{die("连接失败:".mysqli_connect_error());
}//检查用户名密码是否在数据库里已保存注册
$sql = 'select * from user where username="'.$username.'"and pwd="'.$passwd.'"';$result = mysqli_query($link,$sql);
$rows = mysqli_fetch_array($result);//查询数据表每一行if($rows){//数据库中查到用户名,密码匹配$_SESSION['username'] = $username;//保存session数据,全局变量echo '######################登陆成功###################';
}else{echo '######################用户名或密码错误######################';
}
?>
2. 能够防住简单注入和宽字节注入
简单注入
注入用户名19145120mzh' or 1=1#'
密码随意输入
这里检查是否含有特殊的'
引号字符,防止了注入,具体代码在html的js部分
if (str.indexOf("'") >= 0) {mark = "no";mess += " ' ";}
双拼注入
类似单注入,同样成功防止了注入。
注入用户名19145120mzh' 'oorr 1=1#'
密码随意输入
这里检查是否含有特殊的'
引号字符,防止了注入,具体代码在html的js部分
if (str.indexOf("'") >= 0) {mark = "no";mess += " ' ";}
宽字节注入
首先输入测试用户密码得到格式标准化的url
我这里随便输入了用户mzh
密码123
得到了urlhttp://127.0.0.1:5500/login.html?username=mzh&pwd=123&login=%E7%99%BB+%E5%BD%95
在url后面添加%df%27%20or%201=1%23
注入代码
把url改为http://127.0.0.1:5500/login.html?txt_name=mzh&txt_passwd=123%df%27%20or%201=1%23&login=%E7%99%BB+%E5%BD%95
追加的%df%27%20or%201=1%23
表示url编码的空格or空格1=1#
(这里的空格就是空格,一个字符,我这么写是为了方便大家理解)
常用的理解。%df一般是用来转换编码的
%df’(浏览器自动进行url编码%27)->%df%27
下图登录失败了,宽字节注入也失败了。
因为我们的js检查了url
if (str.indexOf("%") >= 0) {mark = "no";mess += " % ";}
function refreshCSS() {var sheets = [].slice.call(document.getElementsByTagName("link"));var head = document.getElementsByTagName("head")[0];for (var i = 0; i < sheets.length; ++i) {var elem = sheets[i];var parent = elem.parentElement || head;parent.removeChild(elem);var rel = elem.rel;if (elem.href && typeof rel != "string" || rel.length == 0 || rel.toLowerCase() =="stylesheet") {var url = elem.href.replace(/(&|\?)_cacheOverride=\d+/, '');elem.href = url + (url.indexOf('?') >= 0 ? '&' : '?') + '_cacheOverride=' + (new Date().valueOf());}parent.appendChild(elem);}}
3. 能够基本防住手动注入和sqlmap攻击(测试案例)
防止手动注入
随便输入异常符号都无法成功的注入
select * from news where id=http://……?id=1
因为是post的方法,并且js对url处理,url也被锁死。
哪怕我在url中注入正确的用户名admin和密码admin都无法成功注入,哪怕是异常字符也会被过滤掉。
防御sqlmap攻击
url已经隐藏,无法通过url进行注入攻击了。
4. 能够防止sql注入原因分析
使用js代码分析、处理并屏蔽客户端上的不安全字符,过滤字符串
功能介绍:检查是否包含“\ \
”、“/
” “%
” "'
"等字符。
function Mycheck(str) {var mess = "不允许输入的字符:\r\n";var mark = "yes";if (str.indexOf(";") >= 0) {mark = "no";mess += " ; ";}if (str.indexOf("&") >= 0) {mark = "no";mess += " & ";}if (str.indexOf("<") >= 0) {mark = "no";mess += " < ";}if (str.indexOf(">") >= 0) {mark = "no";mess += " > ";}if (str.indexOf("--") >= 0) {mark = "no";mess += " -- ";}if (str.indexOf("/") >= 0) {mark = "no";mess += " / ";}if (str.indexOf("%") >= 0) {mark = "no";mess += " % ";}if (str.indexOf("'") >= 0) {mark = "no";mess += " ' ";}if (mark == "no") {alert(mess);return false;} else returnreturn true;}
使用正则表达式等方式替换、过滤传入的参数
function refreshCSS() {var sheets = [].slice.call(document.getElementsByTagName("link"));var head = document.getElementsByTagName("head")[0];for (var i = 0; i < sheets.length; ++i) {var elem = sheets[i];var parent = elem.parentElement || head;parent.removeChild(elem);var rel = elem.rel;if (elem.href && typeof rel != "string" || rel.length == 0 || rel.toLowerCase() =="stylesheet") {var url = elem.href.replace(/(&|\?)_cacheOverride=\d+/, '');elem.href = url + (url.indexOf('?') >= 0 ? '&' : '?') + '_cacheOverride=' + (new Date().valueOf());}parent.appendChild(elem);}}
使用php的sql过滤设置
(其实类似我前面的js代码转化过滤)
打开magic_quotes_gpc来防止SQL注入。php.ini中有一个设置:magic_quotes_gpc = Off这个默认是关闭的,如果它打开后将自动把用户提交对sql的查询进行转换,比如把 ’ 转为 '等,对于防止sql注射有重大作用。
如果magic_quotes_gpc=Off,则使用addslashes()函数。
总结
大家喜欢的话,给个👍,点个关注!继续跟大家分享敲代码过程中遇到的问题!
版权声明:
发现你走远了@mzh原创作品,转载必须标注原文链接
Copyright 2022 mzh
Crated:2022-3-6
欢迎关注 『网络攻防CTF』 系列,持续更新中
欢迎关注 『网络攻防CTF』 系列,持续更新中
【网络攻防CTF】草稿(保姆级图文)
【更多内容敬请期待】