RoarCTF 部分WP

作者: Err0rzz | 来源:发表于2019-10-20 23:15 被阅读0次

    WEB

    easy_calc

    访问calc.php不带num参数的时候就可以得到calc.php源码

    <?php 
    error_reporting(0); 
    if(!isset($_GET['num'])){ 
        show_source(__FILE__); 
    }else{ 
            $str = $_GET['num']; 
            $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^']; 
            foreach ($blacklist as $blackitem) { 
                    if (preg_match('/' . $blackitem . '/m', $str)) { 
                            die("what are you want to do?"); 
                    } 
            } 
            eval('echo '.$str.';'); 
    } 
    ?> 
    

    输入?num=phpinfo(),发现有403错误。
    接下来就是绕WAF的问题。
    参考利用PHP函数parse_str绕过IDS、IPS和WAF,只需要在参数num前加一个%20即可,如下

    然后就是绕单引号和个别函数之类的过滤。
    尝试如下:
    1. 因为不能使用引号和system,所以无法直接执行系统命令,如lspwd等,所以使用?%20num=dirname(__FILE__)?%20num=print_r(scandir(dirname(__FILE__)))读取当前路径和当前目录下的文件 ,一开始我以为flagindex.html里,所以想用highlight_file()去读取文件,但是不能使用引号的情况下,无法读取指定文件。
    2. 既然num参数被加了黑名单过滤,那可不可以在别的地方执行命令?这里参考一叶飘零师傅无参Getshell,里面随便用一个方法都能绕过过滤。我这里使用的是
    3. 还能通过编码的方式来实现绕过,如使用eval(base64_decode(cHJpbnRfcihzY2FuZGlyKCcvJykpOzs7)) 其中base64编码过的部分为print_r(scandir('/'));;;,为什么是三个分号我也没搞懂。。
    4. 还能使用a{b}的方式来替代a['b'],从而绕过引号过滤,如eval(get_defined_vars(){_GET}{a})&a=print_r(scandir('/'));,其中{_GET}{a}[_GET][a]一样。

    simple_upload

    题目如下:

    <?php 
    namespace Home\Controller; 
    
    use Think\Controller; 
    
    class IndexController extends Controller 
    { 
        public function index() 
        { 
            show_source(__FILE__); 
        } 
        public function upload() 
        { 
            $uploadFile = $_FILES['file'] ; 
             
            if (strstr(strtolower($uploadFile['name']), ".php") ) { 
                return false; 
            } 
             
            $upload = new \Think\Upload();// 实例化上传类 
            $upload->maxSize  = 4096 ;// 设置附件上传大小 
            $upload->allowExts  = array('jpg', 'gif', 'png', 'jpeg');// 设置附件上传类型 
            $upload->rootPath = './Public/Uploads/';// 设置附件上传目录 
            $upload->savePath = '';// 设置附件上传子目录 
            $info = $upload->upload() ; 
            if(!$info) {// 上传错误提示错误信息 
              $this->error($upload->getError()); 
              return; 
            }else{// 上传成功 获取上传文件信息 
              $url = .substr($upload->rootPath,1).$info['file']['savepath'].$info['file']['savename'] ; 
              echo json_encode(array("url"=>$url,"success"=>1)); 
            } 
        } 
    }
    

    已知的是使用了ThinkPHP的框架,发现以下代码为开发者自己写的过滤,怀疑存在问题

    if (strstr(strtolower($uploadFile['name']), ".php") ) { 
             return false; 
    } 
    

    该代码将判断文件名是否存在.php
    打开thinkphp3.2.3源码中/Library/Think/Upload.class.php,找到对应的上传文件处理过程代码,如下:

     // 对上传文件数组信息处理
    $files   =  $this->dealFiles($files);    
    foreach ($files as $key => $file) {
       $file['name']  = strip_tags($file['name']);
       if(!isset($file['key']))   $file['key']    =   $key;
    /* 通过扩展获取文件类型,可解决FLASH上传$FILES数组返回文件类型错误的问题 */
       if(isset($finfo)){
           $file['type']   =   finfo_file ( $finfo ,  $file['tmp_name'] );
    }
    

    可以发现,thinkphp框架会对filename进行strip_tags操作


    剥去标签,这样的话我们文件后缀只需要在php中插入任何HTML标签即可绕过过滤,且可以正常解析。
    构造一个上传页面
    <html>
    <body>
        <form action="http://cndljjs6roarctf.4hou.com.cn:37326/index.php/home/index/upload" method="post" enctype="multipart/form-data">
            <label for="file">Filename:</label>
            <input type="file" name="file" id="file" />
            <br />
            <input type="submit" name="submit" value="Submit" />
        </form>
    </body>
    </html>
    

    上传任意一个php文件,然后抓包修改后缀为p<img>hp,上传成功

    访问目标文件,得到flag

    Easy java

    点开help,发现url里有个Download?filename=,怀疑存在任意文件下载
    GET改成POST,发现下载成功。

    下载WEB-INF/web.xml查看目录结构 查阅javaweb的目录结构,以及得到的servlet-class值,可以下载到所需要的class文件 可以发现文件中有着一串base64编码过的字符串,解码得到flag

    Crypto

    RSA

    题目如下:

    A=(((y%x)**5)%(x%y))**2019+y**316+(y+1)/x
    p=next_prime(z*x*y)
    q=next_prime(z)
    A =  2683349182678714524247469512793476009861014781004924905484127480308161377768192868061561886577048646432382128960881487463427414176114486885830693959404989743229103516924432512724195654425703453612710310587164417035878308390676612592848750287387318129424195208623440294647817367740878211949147526287091298307480502897462279102572556822231669438279317474828479089719046386411971105448723910594710418093977044179949800373224354729179833393219827789389078869290217569511230868967647963089430594258815146362187250855166897553056073744582946148472068334167445499314471518357535261186318756327890016183228412253724
    n =  117930806043507374325982291823027285148807239117987369609583515353889814856088099671454394340816761242974462268435911765045576377767711593100416932019831889059333166946263184861287975722954992219766493089630810876984781113645362450398009234556085330943125568377741065242183073882558834603430862598066786475299918395341014877416901185392905676043795425126968745185649565106322336954427505104906770493155723995382318346714944184577894150229037758434597242564815299174950147754426950251419204917376517360505024549691723683358170823416757973059354784142601436519500811159036795034676360028928301979780528294114933347127
    c =  41971850275428383625653350824107291609587853887037624239544762751558838294718672159979929266922528917912189124713273673948051464226519605803745171340724343705832198554680196798623263806617998072496026019940476324971696928551159371970207365741517064295956376809297272541800647747885170905737868568000101029143923792003486793278197051326716680212726111099439262589341050943913401067673851885114314709706016622157285023272496793595281054074260451116213815934843317894898883215362289599366101018081513215120728297131352439066930452281829446586562062242527329672575620261776042653626411730955819001674118193293313612128
    

    未知数有三个,包括xyz,我们能做的就是通过AN恢复出未知数的值。
    先观察A,可以发现有个迷惑性的运算,**2019,我们要知道, 即使是2^{2019},结果也是至少2019/3位的十进制数,而A仅仅为607位,因此我们可以知道(((y\%x)^5)\%(x\%y))的值,其实为1。
    接下来就是解方程了,我们可以通过化解等式得到x=(y+1)/(A-1-y^{316}),而且很明显,A的主要是有y**316组成。这样的话,我们可以通过遍历y来确定y的值,然后求得x。代码如下:

    for y in range(1000):
        if y**316>A:
            y-=1
            break
    x = (y+1)/(A-1-y**316)
    

    然后是如何根据N恢复出pq
    我们首先需要知道的是,z*x*yz其实并没有相差太多,所以next_prime(z*x*y)next_prime(z)也不会相差太多。
    所以我们可以用求根的方法,然后在根值附件寻找,代码如下:

    z = gmpy2.iroot(n/(x*y),2)[0]
    q = gmpy2.next_prime(z)
    while True:
        if n % q == 0:
            break
        q = gmpy2.next_prime(q)
    p = n/q
    

    接下来就是正常的RSA的过程了,另外,加密密钥e可以试试几个常用的就能试出来了,总的代码如下

    import gmpy2
    from libnum import n2s
    # A=(((y%x)**5)%(x%y))**2019+y**316+(y+1)/x
    # p=next_prime(z*x*y)
    # q=next_prime(z)
    A =  2683349182678714524247469512793476009861014781004924905484127480308161377768192868061561886577048646432382128960881487463427414176114486885830693959404989743229103516924432512724195654425703453612710310587164417035878308390676612592848750287387318129424195208623440294647817367740878211949147526287091298307480502897462279102572556822231669438279317474828479089719046386411971105448723910594710418093977044179949800373224354729179833393219827789389078869290217569511230868967647963089430594258815146362187250855166897553056073744582946148472068334167445499314471518357535261186318756327890016183228412253724
    n =  117930806043507374325982291823027285148807239117987369609583515353889814856088099671454394340816761242974462268435911765045576377767711593100416932019831889059333166946263184861287975722954992219766493089630810876984781113645362450398009234556085330943125568377741065242183073882558834603430862598066786475299918395341014877416901185392905676043795425126968745185649565106322336954427505104906770493155723995382318346714944184577894150229037758434597242564815299174950147754426950251419204917376517360505024549691723683358170823416757973059354784142601436519500811159036795034676360028928301979780528294114933347127
    c =  41971850275428383625653350824107291609587853887037624239544762751558838294718672159979929266922528917912189124713273673948051464226519605803745171340724343705832198554680196798623263806617998072496026019940476324971696928551159371970207365741517064295956376809297272541800647747885170905737868568000101029143923792003486793278197051326716680212726111099439262589341050943913401067673851885114314709706016622157285023272496793595281054074260451116213815934843317894898883215362289599366101018081513215120728297131352439066930452281829446586562062242527329672575620261776042653626411730955819001674118193293313612128
    for y in range(1000):
        if y**316>A:
            y-=1
            break
    x = (y+1)/(A-1-y**316)
    z = gmpy2.iroot(n/(x*y),2)[0]
    q = gmpy2.next_prime(z)
    while True:
        if n % q == 0:
            break
        q = gmpy2.next_prime(q)
    p = n/q
    d = gmpy2.invert(0x10001,(p-1)*(q-1))
    m = pow(c,d,n)
    print n2s(m)
    

    babyrsa

    import sympy
    import random
    
    def myGetPrime():
        A= getPrime(513)
        print(A)
        B=A-random.randint(1e3,1e5)
        print(B)
        return sympy.nextPrime((B!)%A)
    p=myGetPrime()
    #A1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467234407
    #B1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467140596
    
    q=myGetPrime()
    #A2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858418927
    #B2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858351026
    
    r=myGetPrime()
    
    n=p*q*r
    #n=85492663786275292159831603391083876175149354309327673008716627650718160585639723100793347534649628330416631255660901307533909900431413447524262332232659153047067908693481947121069070451562822417357656432171870951184673132554213690123308042697361969986360375060954702920656364144154145812838558365334172935931441424096270206140691814662318562696925767991937369782627908408239087358033165410020690152067715711112732252038588432896758405898709010342467882264362733
    c=pow(flag,e,n)
    #e=0x1001
    #c=38620963949231568493951852806812359956058522979245676395704780066879051018892175913415575431734194586035432099562300809271498658506900105389975586615280808081596988894713047252672924018208747721253303054480800386069769084714127190055658807083226038640292692679215406182331245636616583141043207599068234065117886147748321058731290102675088056205224134057176167818706519201527516421824645801542347535393294450756726281744763656819345306146716190523210020241675468
    #so,what is the flag?
    

    主要的问题就是大数阶乘模运算怎么求
    这里用到的是威尔逊定理,当且仅当p为素数时:( p -1 )! ≡ -1 ( mod p )来减少阶乘模的运算量。
    已知( A -1 )! ≡ -1 ( mod A ),B=A-r,求(B)!≡? (mod A),即(A-r)!≡? (mod A)
    解过程如下\begin{align} ( A -1 )! &≡ -1 ( mod A ) \\ ( A -2 )!& ≡ -1 *(A-1)^{-1}( mod A ) \\ \cdots \\ ( A -r )!& ≡ -1 *(A-1)^{-1}(A-2)^{-1}\cdots(A-r+1)^{-1}( mod A ) \end{align}
    代码如下:

    import gmpy2
    import libnum
    def getpq(A,B):
        rand = A - B
        b = -1
        for i in range(1,rand):
            tmp = (b%A)*gmpy2.invert(A-i,A)
            b = tmp%A
        return gmpy2.next_prime(b)
    
    A1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467234407
    B1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467140596
    p = getpq(A1,B1)
    
    A2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858418927
    B2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858351026
    q= getpq(A2,B2)
    
    n = 85492663786275292159831603391083876175149354309327673008716627650718160585639723100793347534649628330416631255660901307533909900431413447524262332232659153047067908693481947121069070451562822417357656432171870951184673132554213690123308042697361969986360375060954702920656364144154145812838558365334172935931441424096270206140691814662318562696925767991937369782627908408239087358033165410020690152067715711112732252038588432896758405898709010342467882264362733
    
    r=n/(p*q)
    e=0x1001
    d = gmpy2.invert(e,(p-1)*(q-1)*(r-1))
    c=38620963949231568493951852806812359956058522979245676395704780066879051018892175913415575431734194586035432099562300809271498658506900105389975586615280808081596988894713047252672924018208747721253303054480800386069769084714127190055658807083226038640292692679215406182331245636616583141043207599068234065117886147748321058731290102675088056205224134057176167818706519201527516421824645801542347535393294450756726281744763656819345306146716190523210020241675468
    m = pow(c,d,n)
    print libnum.n2s(m)
    

    相关文章

      网友评论

        本文标题:RoarCTF 部分WP

        本文链接:https://www.haomeiwen.com/subject/bmqkmctx.html