[深入学习Web安全](1)Web雏形
0x00 目录
0x00 目录
0x01 前言
0x02 浅谈C/S架构
0x03 简析协议
0x04 HTTP协议
0x05 浏览器行为
0x01 前言
路随远也,行之,则必达。——致所有志者。
我学习Web安全已经有一段时间了,对于我来说,在这条路上,有无数的坎坷。因为我是零基础,单纯因为兴趣才走上这条路的。
这条路上,感谢无数好心大牛的帮助,也感谢类似WOOYUN这样的平台,虽然我离梦想还有很远,但是,借奶嘴表哥很喜欢的一句话“路随远也,行之,则必达”!
这是一份深入了解Web安全的文章,记录我这些年学习所得,与大家分享。
0x02 浅谈C/S架构
我们先来看这样一个程序:
很明显,这是一个Python的简单的服务端,其实C/S架构的S就是指服务端(Server),而这个C则是客户端(Client)。我们在上面的图中的第7行可以看到如下代码:
[Python]纯文本查看复制代码
1
s.bind(('',6666))
也就是bind方法,这个方法是说将socket绑定到某个机器的某个端口上,这样一个方法的参数是一个元组(tuple),这个元组应有两个参数,一是主机,二是端口。
这里的主机是''其实意思是本机,而端口是6666。接下来,我们详细说下端口(Port),有这样一个经典的比喻:如果把IP地址比作一间房子 ,端口就是出入这间房子的门。真正的房子只有几个门,但是一个IP地址的端口可以有65536(即:2^16)个之多!端口是通过端口号来标记的,端口号只有整数,范围是从0 到65535(2^16-1)。而一个运行在网络上的程序,也就是说一个能够进行网络通讯的程序都会使用到端口,服务端将自己绑定在一个端口上,客户端则去连接服务端绑定的端口来建立通讯。
所以会有这样一句话:网络通信其实就是两个进程之间在通讯!
相信这句话也很好理解,我们的程序运行起来之后就成为了进程,而要进行网络通讯就要使用端口,我们来举个例子:
首先,我们准备这样一个Python程序server.py,代码如下:
[Python]纯文本查看复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15#coding:utf-8
#author:P0werZh4i
fromsocketimport*
fromtimeimportsleep
s=socket(AF_INET,SOCK_STREAM)
s.bind(('',6666))
s.listen(1)
whileTrue:
sock,addr=s.accept()
print'Connected by ',addr
whileTrue:
sleep(0.1)
sock.send('Hello,There is ichunqiu!')
然后在同目录下准备一个client.py,代码如下:
[Python]纯文本查看复制代码
01
02
03
04
05
06
07
08
09
10#coding:utf-8
#author:P0werZh4i
fromsocketimport*
c=socket(AF_INET,SOCK_STREAM)
c.connect(('127.0.0.1',6666))
whileTrue:
text=c.recv(1024)
printtext
如下图:

然后打开两个bash,如下图:

一个运行server.py,如图:

另一个运行client.py,如图:

可以看到,server端的输出:“Connected by ('127.0.0.1',40690)”。
也就是说我们的客户端在进行连接的时候,系统给它分配了一个40690端口进行通讯。
这样的通讯就是C/S架构程序的通信。0x03 简析协议
我们来看这样一个例子:
我们这个例子是按照这样的格式写的,首先A是Client端,B是Server端A:[XXX]的XXX代表是A发给B的数据包的内容是XXX,而B:[XXX]则代表B发回给A的数据包的内容是XXX。
然后,我们假设A与B之间的通讯遵循ICHUNQIU协议(随便取的名),这样一个协议规定,在客户端发往服务端的数据中开头必须是一个带括号的内容,括号里必须是操作,例如这个例子中A最先发给B的“(login)admin”就是一个login操作,然后,这样一个ICHUNQIU协议规定在)必须是该操作的参数,用key=value的形式表示,若有多个参数则用key1=value1,key2=value2...来表示。
所以很明显这里A最先发给B的“(login)admin”是不遵循ICHUNQIU协议的,因为他的)后面的参数并未以key=value的形式存在。
接着ICHUNQIU协议还规定,如果服务端在发现客户端传来的数据包不符合ICHUNQIU协议的规范,则返回一个"(error)1"。
这也是我们可以看到的。
再接下来,A向B发送了这样一个数据包“(login)username=admin,password=”,这样一个数据包遵循了ICHUNQIU协议,所以不会返回(error)1,但是在服务端验证帐号密码时发现密码为空,于是返回了“(info)Empty password!”,这个ICHUNQIU协议就规定了,当客户端接收到来自服务端的数据包时也要验证()里的行为(操作),这里是info,然后,ICHUNQIU协议还规定info操作的参数不以key=value的形式存在,而是整个就是参数,然后客户端应当将Info操作的参数输出给用户。
OK,例子就说到这里,相信大家已经感觉到什么是协议了。
其实,协议就是两个进程在进行网络通信时所遵循的规范。
0x04 HTTP协议
我们来做一个简单的实验,首先我们代开Burpsuite,然后设置好代理,然后访问i春秋主页“http://www.ichunqiu.com”。
burp截取到的HTTP请求(也就是客户端发给i春秋服务器的数据包)如下:
[Python]纯文本查看复制代码
1
2
3
4
5
6
7
8GET/HTTP/1.1
Host: [url]www.ichunqiu.com[/url]
User-Agent: Mozilla/5.0(X11; Linux x86_64; rv:43.0) Gecko/20100101Firefox/43.0Iceweasel/43.0.4
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: pgv_pvi=52xxx768; pgv_si=s956xxx368; ci_session=076701xxxb92d6752; chkphone=acWxNxxxqyiQuDIO0O0O; Hm_lvt_9104989ce242a8e03049eaceca950328=14xxxxx33; Hm_lpvt_9104989ce242a8e03049eaceca950328=146xxx06; Hm_lvt_1a32f7c660491887db0960e9c314b022=1xxx; Hm_lpvt_1a32f7c660491887db0960e9c314b022=14xxx07; __jsluid=a487426e0fxxxxxb513
Connection: close
额,Cookie打了下码,整了很多xxx,嘿嘿,这个无所谓,我们继续来说,首先我们观察HTTP请求的第一行:
[Python]纯文本查看复制代码
1
GET/HTTP/1.1
由于这是网站,也就是Web服务,所以他会在通讯时遵循HTTP协议,根据HTTP协议规定,在HTTP请求中,第一行应该书写如下:
[Python]纯文本查看复制代码
1
HTTP方法 请求路径 协议版本
根据这个规定我们就能发现我们访问i春秋主页是使用的GET方法,请求的路径是/,也就是Web的根目录,所遵循的HTTP协议版本是1.1。
接着我们看第二行:
[Python]纯文本查看复制代码
1
Host: [url]www.ichunqiu.com[/url]
根据HTTP协议,到第二行开始就不存在顺序了,这些被统称为HTTP请求头,都是已如下格式存在:
[Python]纯文本查看复制代码
1
2
3
4key1: value1
key2: value2
key3: value2
......
所以我们直接看key,这个第二行的key是Host(一定要区分大小写),值是www.ichunqiu.com。
这个Host是值我们要访问的目标服务器域名或者IP。
接着一些其他参数,我们就不再说了,大家有兴趣的可以自行百度(会用百度的人,一定能成为大神)。
接着,我们说几个对于我们学习Web安全很重要的几个请求头:
User-Agent:这个HTTP请求头对于我们来说可以获得发送这个HTTP请求的人所使用的电脑,浏览器信息,例如,我们上例中的UA:Mozilla/5.0 (X11; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0 Iceweasel/43.0.4,我们就能够得知这个请求的发送者用的浏览器是Iceweasel/43.0.4,系统是Linux x86_64。
Cookie:这个呢,其实是一个身份标识,我们这样说,HTTP协议使用的是一种不是常连接的连接,也就是说,我们每一次请求和获得响应是使用的不同的Socket,于是,我们怎么验证一个人在我们网站上的身份呢?就是使用这个Cookie来验证(暂时懂这些就OK,后面还会专门说)。
Refer:这个是指你发起这次HTTP请求时的页面的URL。例如:你在http://www/baidu.com/ok.php这个页面上点击了一个链接,然后跳转到目标目标服务器如果读取你的Refer就能看到你从哪里来。
关于HTTP协议就暂时说这样一些。
0x05 浏览器行为
我们再接着来做个实验,我们知道一个Web程序会被分为“前端/后端”,我们先写这样一个HTML的文件:
[HTML]纯文本查看复制代码
1
2
3
4
5
6
7
8
Demo
http://bbs.ichunqiu.com/data/attachment/block/cd/cd3b58433c837413c2cfd8c40f01aca6.jpg"/>
我们来加载下这个页面,如下:

我们右键-InspctElement,如下图:

我们转到Network选项卡,如下:

然后刷新页面,如下图:

可以看到,这个页面为了得到这个图片,对www.ichunqiu.com发起了一次GET请求。
这就叫浏览器行为,什么意思呢?
我们来准备这样一个HTML文件,代码如下:
[HTML]纯文本查看复制代码
01
02
03
04
05
06
07
08
09
10
Demo
http://bbs.ichunqiu.com/data/attachment/block/cd/cd3b58433c837413c2cfd8c40f01aca6.jpg"/>
http://bbs.ichunqiu.com">
http://woaiichunqiu.com/?testestetstetst"/>
我们可以加载下这个页面,查看Network,如下图:

可以看到只要是src属性,浏览器都会发起GET请求,请求src属性的URL。这就是浏览器行为,也就是说,我们在前端发起HTTP请求的是我们的浏览器。
OK,就到这里了,下一篇继续。
1.png(67.24 KB, 下载次数: 2)
