谈谈PHP网站的防SQL注入,谈谈phpsql注入

转自维基百科:

谈谈PHP网站的防SQL注入,谈谈phpsql注入

SQL(Structured Query Language)即结构化查询语言。SQL 注入,就是把 SQL
命令插入到 Web 表单的输入域或页面请求参数的查询字符串中,在 Web表单向
Web 服务器提交 GET 或 POST
请求时,如果服务器端未严格验证参数的有效性和合法性,将导致数据库服务器执行恶意的
SQL 命令。

SQL 注入攻击的过程:

(1)判断 Web 应用是否可以进行 SQL 注入。

(2)寻找 SQL 注入点。

(3)猜解用户名和密码。

(4)寻找 Web 系统管理后台入口。

(5)实施入侵和破坏。

SQL注入是一种代码注入技术,用于攻击)数据驱动的应用程序,在这种应用程序中,恶意的SQL语句被插入输入字段中执行(例如将数据库内容转储给攻击者)。[\[1\]](https://en.wikipedia.org/wiki/SQL_injection#cite_note-1) SQL注入必须利用应用程序软件中的安全漏洞,例如,当用户输入被错误地过滤为嵌入在SQL语句中的字符串文字 转义字符,或者用户输入没有强类型和意外执行时。SQL注入通常被称为网站的攻击媒介),但可以用来攻击任何类型的SQL数据库。

一、     SQL注入漏洞测试工具

SQL注入攻击允许攻击者欺骗身份,篡改现有数据,导致拒绝问题,如排除交易或更改余额,允许完整披露系统上的所有数据,破坏数据或使其不可用,并成为数据库服务器

1.    Sqlmap

Sqlmap 是一个自动化的 SQL 注入工具, 其主要功能是扫描,发现并利用给定的
URL 的 SQL 注入漏洞,日前支持的数据库是MS SQL Server, MySQL, oracle 和
postgresql。 SQLMAP 采用四种独特的 SQL 注入技术,分别是盲推理 SQL 注入,
UNION 查询 SQL 注入,堆查询和基于时间的 SQL
盲注入。其广泛的功能和选项包括数据库指纹,枚举,
数据库提取,访问目标文件系统,并在获取完全操作权限时实行任意命令。

1.1      sqlmap 常用命令介绍

Target(目标):至少需要设置其中一个选项,设置目标 URL。

-d DIRECT 直接连接到数据库。

-u URL,–url=URL 目标 URL。

Request(请求):这些选项可以用来指定如何连接到目标 URL。

――data=DATA 通过 POST 发送的数据字符串。

――cookie=COOKIE HTTP Cookie 头。

Optimization(优化):这些选项可用于优化 sqlmap 的性能。

-o 开户所有优化开关

–threads=THREADS 最大的 HTTP( S)请求并发量(默认为 1)。

Injection(注入):这些选项可以用来指定测试哪些参数。

-p TESTPARAMETER 可测试的参数。

–prefix=PREFIX 注入 payload 字符串前缀。

在2012年的一项研究中,观察到平均每个月的网络应用程序收到4次攻击活动,零售商受到的攻击是其他行业的两倍。

2     SQLIer

SQLIer可以找到网站上一个有SQL注入漏洞的URL,并根据有关信息来生成利用SQL注入漏洞,但它不要求用户的交互。通过这种方法,它可以生成一个UNION SELECT查询,进而可以强力攻击数据库口令。这个程序在利用漏洞时并不使用引号,这意味着它可适应多种网站。  

SQLIer通过“true/false”
SQL注入漏洞强力口令。借助于“true/false” SQL注入漏洞强力口令,用户是无法从数据库查询数据的,只能查询一个可返回“true”、“false”值的语句。  

据统计,一个八个字符的口令(包括十进制ASCII代码的任何字符)仅需要大约1分钟即可破解。

2.1      其使用语法如下,sqlier [选项] [URL]

其选项如下: 

-c :[主机] 清除主机的漏洞利用信息 

-s :[秒]在网页请求之间等待的秒数  

-u:[用户名]从数据库中强力攻击的用户名,用逗号隔开

-w:[选项]将[选项]交由wget

此外,此程序还支持猜测字段名,有如下几种选择:  

–table-names [表格名称]:可进行猜测的表格名称,用逗号隔开

–user-fields[用户字段]:可进行猜测的用户名字段名称,用逗号隔开

–pass-fields [口令字段]:可进行猜测的口令字段名称,用逗号隔开

SQL注入(SQLI)被Open
Web应用程序安全项目认为是2007年和2010年排名前10的Web应用程序漏洞之一。[\[5\]](https://en.wikipedia.org/wiki/SQL_injection#cite_note-5) 2013年,SQLI被评为OWASP前十名的头号攻击。[\[6\]](https://en.wikipedia.org/wiki/SQL_injection#cite_note-6) SQL注入有四个主要的子类:

3     Pangolin

Pangolin是一款帮助渗透测试人员进行SQL注入(SQL
Injeciton)测试的安全工具。Pangolin与JSky(Web应用安全漏洞扫描器、Web应用安全评估工具)都是NOSEC公司的产品。Pangolin具备友好的图形界面以及支持测试几乎所有数据库(Access、MSSql、MySql、Oracle、Informix、DB2、Sybase、PostgreSQL、Sqlite)。Pangolin能够通过一系列非常简单的操作,达到最大化的攻击测试效果。它从检测注入开始到最后控制目标系统都给出了测试步骤。Pangolin是目前国内使用率最高的SQL注入测试的安全软件。

  • 经典的SQLI
  • 盲或推理SQL注入
  • 数据库管理系统 –
    特定的SQLI
  • 复杂的SQLI

二、     防范SQL注入攻击

1.    对输入的数据进行过滤(过滤输入)

a)     
对于动态构造SQL查询的场合,可以使用替换字符和删除特殊字符的方法。

b)    
检查用户输入的合法性,防止非法数据输入。数据检查应当在客户端和服务器端执行。执行服务器端验证,是为了弥补客户端验证机制的不足。

c)      限制表单或查询字符串输入的长度范围。

d)     加密用户登录名称、 密码等数据。

  • SQL注入+认证不足[\[7\]](https://en.wikipedia.org/wiki/SQL_injection#cite_note-7)
  • SQL注入+ DDoS攻击[\[8\]](https://en.wikipedia.org/wiki/SQL_injection#cite_note-8)
  • SQL注入+ DNS劫持[\[9\]](https://en.wikipedia.org/wiki/SQL_injection#cite_note-9)
  • SQL注入+ XSS [\[10\]](https://en.wikipedia.org/wiki/SQL_injection#cite_note-10)

2.    对发送到数据库的数据进行转义(转义输出)

尽量使用为自定义数据库设计的转义函数。如果没有,使用函数addslashes()是比较好的方法,对字符串型参数使用mysql_real_escape_string函数、对数字型参数使用intval,floatval函数强制过滤则更好。当所有用于建立一个
SQL 语句的数据被正确过滤和转义时,实际上也就避免了 SQL注入的风险。

在风暴蠕虫是复合SQLI的一种表示。[\[11\]](https://en.wikipedia.org/wiki/SQL_injection#cite_note-11)

3.    参数化查询

参数化查询(Parameterized Query)指的是 Web
程序在实施数据库查询时,在需提交数值或数据的地方避免直接赋值,而是采用参数来传递给值。

使用参数化查询技术,数据库服务器不会将参数的内容视为 SQL
指令的一个组成部分来处理,在数据库系统完成对 SQL
指令的编译后,再载入参数运行。因此,即使参数中含有指令,也不会被数据库编译运行。

这个分类代表了SQLI的状态,尊重它的发展到2010年 –
进一步的改进正在进行。[\[12\]](https://en.wikipedia.org/wiki/SQL_injection#cite_note-12)

4.    使用存储过程

存储过程存储在数据库系统内部, Web 应用程序通过调用来执行存储过程,
该技术允许用户定义变量、有条件执行以及其它丰富的编程功能。程序开发者利用存储过程事先构建好的
SQL
查询语句代码,然后在使用中通过参数传输数值。存储过程在使用时起到三点安全作用:首先,存储过程执行前要进行预编译,编译出错不予执行;其次,对于数据的授权访问是基于存储过程而不是直接访问基本表,攻击者无法探测到
select 语句;最后,存储过程可以指定和验证用户提供的值类型。

但是,存储过程也存在一定的局限,如果存储过程中执行的命令是拼接字符串,则会存在被注入攻击的隐患。此外,存储过程并不支持所有的数据库平台。

技术实现[ 编辑]

5.    使用PDO连接数据库

防止SQL注入最好的方法就是不要自己设置SQL
命令和参数,而是用PDO的prepare和bind,原理就在于要把SQL查询命令和传递的参数分开。使用prepare的时候,DB
server会把SQL语句解析成SQL命令。使用bind的时候,只是动态传递DB
Server解析好的 SQL 命令。