SQL注入漏洞代码分析

1.代码分析

HTML代码

复制代码
<form action="#" method="GET">
	<input type="text" name="id">
	<input type="submit" name="Submit" value="Submit">
</form>

action="#",将数据提交到当前页面。

PHP代码分析

复制代码
if(isset($_GET['Submit'])){ 		//判断Submit变量是否存在
      
    $id = $_GET['id']; 		//获取id变量的值并赋值给变量$id

    $getid = "SELECT first_name, last_name FROM users WHERE user_id = '1' and '1'='1'"; 
    //将select查询语句赋值给变量$getid

$result = mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' ); 
    //mysql_query()函数执行mysql查询
    //die() 函数输出一条消息,并退出当前脚本。
   //mysql_error() 函数返回上一个 MySQL 操作产生的文本错误信息。
   //or之前的语句执行不成功时,才会执行后面的语句。
  //and之前的语句执行成功时,才会执行后面的语句。

mysql_query()函数

复制代码
mysql_query()如果是执行查询之类的语句(select),那么会返回一个资源标识符,也就是我们要查找的数据结果集;

mysql_query()如果是执行增删改之类的语句,返回的就是true或者false了。

PHP代码分析

复制代码
$num = mysql_numrows($result); 		//返回结果集中行的数目
    $i = 0; 
    while ($i < $num) { 
        $first = mysql_result($result,$i,"first_name"); 	//返回结果集中first_name字段的值
        $last = mysql_result($result,$i,"last_name"); 	//返回结果集中last_name字段的值
        echo '<pre>'; 
        echo 'ID: ' . $id . '<br>First name: ' . $first . '<br>surname: ' . $last; 
        echo '</pre>'; 
        $i++; 
    } 

2.漏洞分析

SQL注入分类

按照所传递的数据类型分类: 数字型注入 SELECT first_name, last_name FROM users WHERE user_id= id字符型注入SELECTfirstn​ame,lastn​ameFROMusersWHEREuseri​d=′id' 无论何种类型,都可以通过直接输入单引号来判断是否存在注入点。 可以分别输入3和1+2,根据显示结果来判断数据类型。

字符型注入

字符型注入最关键的是如何闭合SQL语句以及注释多余的代码。

复制代码
SELECT first_name, last_name FROM users WHERE user_id = '1 'or 1=1 or ' '

' or 1=1 or '		假 or 真 or 假

1' or '1'='1		真 or 真

' or 1=1 #		假 or 真

' or 1=1 -- 		假 or 真

手工MySQL注入流程

复制代码
' union select 1,2 #
' union select user(),database() #
' union select table_name,2 from information_schema.tables where table_schema='dvwa' #
' union select column_name,2 from information_schema.columns where table_name='users' #
' union select user,password from users #

3.漏洞防御

如何防御SQL注入

SQL注入漏洞的形成原因:用户构造的语句被代入到数据库中执行。

防御SQL注入的首要原则:用户的一切输入都是有害的,或是说不被信任的。

防御SQL注入的主要方法:对用户输入的数据进行过滤。

medium级别的防御措施

复制代码
$id = $_GET['id']; 
$id = mysql_real_escape_string($id); 

使用mysql_real_escape_string()函数对用户输入的id参数进行了过滤。

可以将单引号【'】、双引号【"】、反斜杠【\】、空字符【null】等进行转义。
转义是把指定的字符转换成无意义的符号,比如PHP解析器不会把经过转义的引号当成引号来看待。

PHP中另一个功能类似的函数:addslashes()

medium级别的漏洞

复制代码
$getid = "SELECT first_name, last_name FROM users WHERE user_id = $id"; 


注入类型变成了数字型,mysql_real_escape_string()函数过滤无效。

high级别的防御措施

复制代码
$id = $_GET['id']; 
 $id = stripslashes($id); 
 $id = mysql_real_escape_string($id); 

stripslashes()函数的作用是删除由 addslashes() 函数添加的反斜杠,也就是去除addslashes()函数的转义。

magic_quotes_gpc魔术引号

在PHP配置文件php.ini中存在magic_quotes_gpc选项,被称为魔术引号。

在high级别下,PHP的magic_quotes_gpc被自动设为on。

开启之后,可以对所有的GET、POST和COOKIE传值的数据自动运行addslashes()函数

关闭魔术引号

修改C:\Windows\php.ini文件magic_quotes_gpc = Off

重启Apache服务

high级别的防御措施

复制代码
if (is_numeric($id)){ 
          $getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'"; 


在执行查询之前,使用了if语句进行判断,判断的条件是is_numeric()函数。
判断用户输入的数据是否是数字型,只要不是数字型就一概报错。
and、or、select等语句都无法执行。

如何从代码层面防范SQL注入

对于数字型注入,可以使用if语句,并以is_number()函数作为判断条件进行防御。

对于字符型注入,对用于接收用户参数的变量,用mysql_real_escape_string()、addslashes()等函数进行过滤。

SQL注入的防范措施

代码层面 1.对输入进行严格的转义和过滤; 2.使用参数化查询。

网络层面 1.通过WAF进行防护; 2.云端防护:安全狗、360网站卫士、阿里云盾等。

相关推荐
TDengine (老段)11 分钟前
TDengine taosAdapter — 多协议网关详解
大数据·数据库·物联网·时序数据库·iot·tdengine·涛思数据
Nturmoils11 分钟前
SQL Server 迁移到 KingbaseES:一次复杂 BI 查询的性能实测
数据库
蒲公英eric25 分钟前
从布尔盲注到参数化查询:DVWA SQL 盲注模块完整漏洞分析教程
sql·web安全·ai·dvwa·ai安全·sql 盲注
今天AI了吗1 小时前
MCP 协议打通 AI 与国产数据库,SQL 调优全流程一站式闭环
数据库·人工智能·sql
灯澜忆梦1 小时前
【MySQL11】进阶篇 | 索引_#3使用规则
数据库·sql·mysql·性能优化
名字还没想好☜1 小时前
Go 的 sync.Cond 实战:用条件变量做等待/通知,比忙轮询省 CPU
开发语言·数据库·后端·golang·go
sbjdhjd2 小时前
大三网安秋招核心学习前言(AI 安全 + Web 漏洞 + 内网渗透全考点)
人工智能·网络协议·学习·安全·网络安全·开源·php
wWYy.2 小时前
Mysql:有哪些锁?
数据库·mysql
李可以量化2 小时前
Tornado 从了解到精通(一)下:异步与非阻塞 IO 核心原理
java·数据库·tornado
云技纵横2 小时前
线上接口突然超时,怎么判断卡在 Nginx、线程池、连接池还是 SQL?
后端·sql·mysql