Intro
看来考研是凶多吉少了,虽然很痛苦,但也没办法。
一念之间,就错了这么多莫名其妙的简单题目,真吐血了。
时间是没办法停止的,只能继续往下走了。
Bugku
各种Web思路
GitHack:把/.git用
wget -r
递归下载下来,再在本地用git show
和git reflog
查看提交日志Burp抓包看不同发包返回的变化
直接找请求头多余的参数
PHP超全局变量,
$GLOBALS
是一个包含所有变量的数组绕过本地IP检测:在请求头加X-Forwarded-For:127.0.0.1
打开页面是一个游戏,看js源码发现用
xmlhttp.get
实现发起请求:xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4 && xmlhttp.status==200) { document.getElementById("livesearch").innerHTML=xmlhttp.responseText; document.getElementById("livesearch").style.border="1px solid #A5ACB2"; } } var ppp='182.150.122.47'; var sign = Base64.encode(score.toString()); xmlhttp.open("GET","score.php?score="+score+"&ip="+ppp+"&sign="+sign,true); xmlhttp.send();
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
- 构造score和对应的base64,注意可能有空格
- **同时提交GET和POST**,可以在url里穿get,再设置请求为POST,在请求体里写POST参数
- `request = requests.Session()`,python发请求时用这个可以**保留sessionID(即维持会话)**,在每次返回都不同的网页保留参数时很重要
## 各种绕过
- php**弱类型比较**绕过:`==`会将字符串转换为数字比较
- >PHP 的弱比较规则会根据具体的情况进行类型转换,主要包括以下几种:
>
>1. **数字和字符串比较**:
> - 字符串会被尝试转换为数字(如果可能的话)。
> - 例如,`'123abc' == 123` 会返回 `true`,因为 `'123abc'` 会被转换为数字 `123`。
>2. **布尔值和其他类型比较**:
> - `false` 会被转换为 `0`,`true` 会被转换为 `1`。
> - 例如,`false == 0` 和 `true == 1` 都为 `true`。
>3. **空值(null)和其他类型比较**:
> - `null` 会被转换为 `0` 或空字符串 `''`,这取决于比较的类型。
> - 例如,`null == 0` 和 `null == ''` 都为 `true`。
>4. **数组与其他类型比较**:
> - 数组与标量值(如整数、字符串等)进行比较时,总是返回 `false`,即使数组是空的。
> - 例如,`[] == 0` 返回 `false`。
- 例如`$num == 1`的比较可以用`1abc`绕过,注意为防止加引号被过滤,最好直接用**1abc**
- 绕过PHP的**strcmp()**:
- ```php
if (!strcmp($v3, $flag)) {
echo $flag;
}此代码校验v3与flag是否相等,相等则echo
绕过用v3为数组即可:
v3[]=1111;
,strcmp
无法比较数组。
**file_get_contents()**绕过:
- 使用
php://input
伪协议绕过
① 将要GET的参数?xxx=php://input【这个input伪协议会将请求体直接赋值给文件输出流】
② 用post方法传入想要file_get_contents()
函数返回的值 - 例如如上就是构造
file_get_contents($fn) == $ac
- 用
data://
伪协议绕过
将url改为:?xxx=data://text/plain;base64,想要file_get_contents()
函数返回的值的base64编码
或者将url改为:?xxx=data:text/plain,(url编码的内容)
- 使用
哈希碰撞
校验代码:
1 |
|
注意需要绕过key的过滤,双写kekeyy:http://114.67.175.224:10301/index.php?kekeyy1=s878926199a&kekeyy2=s155964671a
具体md5绕过原理
1
2 $_GET['name'] != $_GET['password']
MD5($_GET['name']) == MD5($_GET['password'])满足上述规则时,可以使用以0E开头的hash值绕过,因为处理hash字符串时,PHP会将每一个以 0E开头的哈希值解释为0,那么只要传入的不同字符串经过哈希以后是以 0E开头的,那么PHP会认为它们相同
因为处理hash字符串时,PHP会将每一个以 0E开头的哈希值解释为0,那么只要传入的不同字符串经过哈希以后是以 0E开头的,那么PHP会认为它们相同
基本的原理是这样的,但更严谨的字符串格式是,0e
开头,同时后面都是数字,不能包含其他字符的字符串,md5 值才会相等(==
的结果为 True,但 ===
的结果为 False)。
1 |
|
数组绕过
1 | $_POST['param1']!==$_POST['param2'] && md5($_POST['param1'])===md5($_POST['param2']) |
当满足上面的条件时,由于PHP中MD5函数的特性,可以使用数组绕过
1 | md5([1,2]) == md5([3,4]) == NULL |
故只要GET方法传入a[]=1&b[]=2
即可绕过
注意:这种绕过同样可以用在
sha1()
上,即构造参数为数组即可。
MD5碰撞
1 | (string)$_POST['param1']!==(string)$_POST['param2'] && md5($_POST['param1'])===md5($_POST['param2']) |
使用MD5碰撞生成 工具 得到hash值相同的不同字符串
先建立两个空文件,然后
1 | .\fastcoll_v1.0.0.5.exe -i .\a.txt .\b.txt -o c.txt d.txt |
生成的c.txt 和 d.txt中的字符串就是hash值相等的字符串
Burp爆破+过滤
当返回结果在登录成果与失败长度不同时,可直接按照length过滤出结果
但均相同时,例如发生重定向使参数再发往另一个页面校验时,则需要过滤结果中特定的参数(例如如果成功就发请求,失败则不发):
1 | var r = {code: 'bugku10000'} |
当为else中的结果时,必然有r.code != bugku10000
,故可过滤这个字符串。
即出现bugku10000
时必然爆破失败,用burp的Grep-Match即可
过狗一句话
1 | $poc = "a#s#s#e#r#t"; //定义变量poc |
此时直接用?s=system("ls")
传参执行命令即可。
利用命令执行一句话木马连蚁剑
1 |
|
当有如上代码类似的可控参数,且该参数被传入命令执行函数时:
1 | ?hello=eval($_POST['attack']) |
注意:连接URL必须要有eval参数,因为只有将eval这行命令始终执行才能连接shell
若可上传文件,则无需在url里加参数执行命令。
file()函数读取文件
1 | $a = file("flag.php"); |
可将文件存到一个数组中。
正则表达式
匹配字符串中的一部分:
例如字符串为:Give me value post about 1746343788+1822614677*504148665+2072024330-450765037*810208960-1242073504+201049388+1538795160*765620361-422466013=?
要匹配其中的表达式计算部分:
1 | re.search(r"Give me value post about (.*?)=\?", res.text, re.S).group(1) |
即将中间和两边加起来分为两个元素,再引用后一个,即group(1)
会话保留的请求
请求每次分配一个随机的会话ID,再次请求如果继续用这个SESSIONID需要用如下这种写法:
1 | import requests |
注意请求时必须写成这种形式,否则不能携带同一sessionID