玲玲's profile玲玲的共享空间PhotosBlogGuestbookMore ![]() | Help |
玲玲的共享空间 |
||||||||||||||
|
February 13 使用StatSVN统计Subversion库中的代码开发情况入门StatSVN能够从Subversion版本库中取得信息,然后生成描述项目开发的各种表格和图表。 比如: 代码行数的时间线; 针对每个开发者的代码行数; 开发者的活跃程度; 开发者最近所提交的; 文件数量; 平均文件大小; 最大文件; 哪个文件是修改最多次数的; 目录大小; 带有文件数量和代码行数的Repository tree。 StatSVN当前版本能够生成一组包括表格与图表的静态HTML文档。 StatSVN使用JFreeChart来生成chart。 下面打包好的脚本文件,可以作为大家的参考 转帖请包含作者等版权信息、并注明来自:我用Subversion - 使用StatSVN统计Subversion库中的代码开发情况入门 November 04 学习英文Chapter 19: SecurityThe Internet can be a scary place. These days, high-profile security gaffes seem to crop up on a daily basis. We’ve seen viruses spread with amazing speed, swarms of compromised computers wielded as weapons, a never-ending arms race against spammers, and many, many reports of identify theft from hacked Web sites. As Web developers, we have a duty to do what we can to combat these forces of darkness. Every Web developer needs to treat security as a fundamental aspect of Web programming. Unfortunately, it turns out that implementing security is hard — attackers need to find only a single vulnerability, but defenders have to protect every single one. Django attempts to mitigate this difficulty. It’s designed to automatically protect you from many of the common security mistakes that new (and even experienced) Web developers make. Still, it’s important to understand what these problems are, how Django protects you, and — most important — the steps you can take to make your code even more secure. First, though, an important disclaimer: We do not intend to present a definitive guide to every known Web security exploit, and so we won’t try to explain each vulnerability in a comprehensive manner. Instead, we’ll give a short synopsis of security problems as they apply to Django. The Theme of Web SecurityIf you learn only one thing from this chapter, let it be this: Never — under any circumstances — trust data from the browser. You never know who’s on the other side of that HTTP connection. It might be one of your users, but it just as easily could be a nefarious cracker looking for an opening. Any data of any nature that comes from the browser needs to be treated with a healthy dose of paranoia. This includes data that’s both “in band” (i.e., submitted from Web forms) and “out of band” (i.e., HTTP headers, cookies, and other request information). It’s trivial to spoof the request metadata that browsers usually add automatically. Every one of the vulnerabilities discussed in this chapter stems directly from trusting data that comes over the wire and then failing to sanitize that data before using it. You should make it a general practice to continuously ask, “Where does this data come from?” SQL InjectionSQL injection is a common exploit in which an attacker alters Web page parameters (such as GET/POST data or URLs) to insert arbitrary SQL snippets that a naive Web application executes in its database directly. It’s probably the most dangerous — and, unfortunately, one of the most common — vulnerabilities out there. This vulnerability most commonly crops up when constructing SQL “by hand” from user input. For example, imagine writing a function to gather a list of contact information from a contact search page. To prevent spammers from reading every single email in our system, we’ll force the user to type in someone’s username before providing her email address: def user_contacts(request):
user = request.GET['username']
sql = "SELECT * FROM user_contacts WHERE username = '%s';" % username
# execute the SQL here...
Note In this example, and all similar “don’t do this” examples that follow, we’ve deliberately left out most of the code needed to make the functions actually work. We don’t want this code to work if someone accidentally takes it out of context. Though at first this doesn’t look dangerous, it really is. First, our attempt at protecting our entire email list will fail with a cleverly constructed query. Think about what happens if an attacker types "' OR 'a'='a" into the query box. In that case, the query that the string interpolation will construct will be: SELECT * FROM user_contacts WHERE username = '' OR 'a' = 'a'; Because we allowed unsecured SQL into the string, the attacker’s added OR clause ensures that every single row is returned. However, that’s the least scary attack. Imagine what will happen if the attacker submits "'; DELETE FROM user_contacts WHERE 'a' = 'a'". We’ll end up with this complete query: SELECT * FROM user_contacts WHERE username = ''; DELETE FROM user_contacts WHERE 'a' = 'a'; Yikes! Where’d our contact list go? The SolutionAlthough this problem is insidious and sometimes hard to spot, the solution is simple: never trust user-submitted data, and always escape it when passing it into SQL. The Django database API does this for you. It automatically escapes all special SQL parameters, according to the quoting conventions of the database server you’re using (e.g., PostgreSQL or MySQL). For example, in this API call: foo.get_list(bar__exact="' OR 1=1") Django will escape the input accordingly, resulting in a statement like this: SELECT * FROM foos WHERE bar = '\' OR 1=1' Completely harmless. This applies to the entire Django database API, with a couple of exceptions:
In each of these cases, it’s easy to keep yourself protected. In each case, avoid string interpolation in favor of passing in bind parameters. That is, the example we started this section with should be written as follows: from django.db import connection
def user_contacts(request):
user = request.GET['username']
sql = "SELECT * FROM user_contacts WHERE username = %s;"
cursor = connection.cursor()
cursor.execute(sql, [user])
# ... do something with the results
The low-level execute method takes a SQL string with %s placeholders and automatically escapes and inserts parameters from the list passed as the second argument. You should always construct custom SQL this way. Unfortunately, you can’t use bind parameters everywhere in SQL; they’re not allowed as identifiers (i.e., table or column names). Thus, if you need to, say, dynamically construct a list of tables from a POST variable, you’ll need to escape that name in your code. Django provides a function, django.db.backend.quote_name, which will escape the identifier according to the current database’s quoting scheme. Cross-Site Scripting (XSS)Cross-site scripting (XSS), is found in Web applications that fail to escape user-submitted content properly before rendering it into HTML. This allows an attacker to insert arbitrary HTML into your Web page, usually in the form of <script> tags. Attackers often use XSS attacks to steal cookie and session information, or to trick users into giving private information to the wrong person (aka phishing). This type of attack can take a number of different forms and has almost infinite permutations, so we’ll just look at a typical example. Consider this extremely simple “Hello, World” view: def say_hello(request):
name = request.GET.get('name', 'world')
return render_to_response("hello.html", {"name" : name})
This view simply reads a name from a GET parameter and passes that name to the hello.html template. We might write a template for this view as follows: <h1>Hello, {{ name }}!</h1>
So if we accessed http://example.com/hello/name=Jacob, the rendered page would contain this: <h1>Hello, Jacob!</h1> But wait — what happens if we access http://example.com/hello/name=<i>Jacob</i>? Then we get this: <h1>Hello, <i>Jacob</i>!</h1> Of course, an attacker wouldn’t use something as benign as <i> tags; he could include a whole set of HTML that hijacked your page with arbitrary content. This type of attack has been used to trick users into entering data into what looks like their bank’s Web site, but in fact is an XSS-hijacked form that submits their back account information to an attacker. The problem gets worse if you store this data in the database and later display it it on your site. For example, MySpace was once found to be vulnerable to an XSS attack of this nature. A user inserted JavaScript into his profile that automatically added him as your friend when you visited his profile page. Within a few days, he had millions of friends. Now, this may sound relatively benign, but keep in mind that this attacker managed to get his code — not MySpace’s — running on your computer. This violates the assumed trust that all the code on MySpace is actually written by MySpace. MySpace was extremely lucky that this malicious code didn’t automatically delete viewers’ accounts, change their passwords, flood the site with spam, or any of the other nightmare scenarios this vulnerability unleashes. The SolutionThe solution is simple: always escape any content that might have come from a user. If we simply rewrite our template as follows: <h1>Hello, {{ name|escape }}!</h1>
then we’re no longer vulnerable. You should always use the escape tag (or something equivalent) when displaying user-submitted content on your site. Why Doesn’t Django Just Do This for You? Modifying Django to automatically escape all variables displayed in templates is a frequent topic of discussion on the Django developer mailing list. So far, Django’s templates have avoided this behavior because it subtly changes what should be relatively straightforward behavior (displaying variables). It’s a tricky issue and a difficult tradeoff to evaluate. Adding hidden implicit behavior is against Django’s core ideals (and Python’s, for that matter), but security is equally important. All this is to say, then, that there’s a fair chance Django will grow some form of auto-escaping (or nearly auto-escaping) behavior in the future. It’s a good idea to check the official Django documentation for the latest in Django features; it will always be more up to date than this book, especially the print edition. Even if Django does add this feature, however, you should still be in the habit of asking yourself, at all times, “Where does this data come from?” No automatic solution will ever protect your site from XSS attacks 100% of the time. Cross-Site Request ForgeryCross-site request forgery (CSRF) happens when a malicious Web site tricks users into unknowingly loading a URL from a site at which they’re already authenticated — hence taking advantage of their authenticated status. Django has built-in tools to protect from this kind of attack. Both the attack itself and those tools are covered in great detail in Chapter 14. Session Forging/HijackingThis isn’t a specific attack, but rather a general class of attacks on a user’s session data. It can take a number of different forms:
The SolutionThere are a number of general principles that can protect you from these attacks:
Notice that none of those principles and tools prevents man-in-the-middle attacks. These types of attacks are nearly impossible to detect. If your site allows logged-in users to see any sort of sensitive data, you should always serve that site over HTTPS. Additionally, if you have an SSL-enabled site, you should set the SESSION_COOKIE_SECURE setting to True; this will make Django only send session cookies over HTTPS. Email Header InjectionSQL injection’s less well-known sibling, email header injection, hijacks Web forms that send email. An attacker can use this technique to send spam via your mail server. Any form that constructs email headers from Web form data is vulnerable to this kind of attack. Let’s look at the canonical contact form found on many sites. Usually this sends a message to a hard-coded email address and, hence, doesn’t appear vulnerable to spam abuse at first glance. However, most of these forms also allow the user to type in his own subject for the email (along with a “from” address, body, and sometimes a few other fields). This subject field is used to construct the “subject” header of the email message. If that header is unescaped when building the email message, an attacker could submit something like "hello\ncc:spamvictim@example.com" (where "\n” is a newline character). That would make the constructed email headers turn into: To: hardcoded@example.com Subject: hello cc: spamvictim@example.com Like SQL injection, if we trust the subject line given by the user, we’ll allow him to construct a malicious set of headers, and he can use our contact form to send spam. The SolutionWe can prevent this attack in the same way we prevent SQL injection: always escape or validate user-submitted content. Django’s built-in mail functions (in django.core.mail) simply do not allow newlines in any fields used to construct headers (the from and to addresses, plus the subject). If you try to use django.core.mail.send_mail with a subject that contains newlines, Django will raise a BadHeaderError exception. If you do not use Django’s built-in mail functions to send email, you’ll need to make sure that newlines in headers either cause an error or are stripped. You may want to examine the SafeMIMEText class in django.core.mail to see how Django does this. Directory TraversalDirectory traversal is another injection-style attack, wherein a malicious user tricks filesystem code into reading and/or writing files that the Web server shouldn’t have access to. An example might be a view that reads files from the disk without carefully sanitizing the file name: def dump_file(request):
filename = request.GET["filename"]
filename = os.path.join(BASE_PATH, filename)
content = open(filename).read()
# ...
Though it looks like that view restricts file access to files beneath BASE_PATH (by using os.path.join), if the attacker passes in a filename containing .. (that’s two periods, a shorthand for “the parent directory”), she can access files “above” BASE_PATH. It’s only a matter of time before she can discover the correct number of dots to successfully access, say, ../../../../../etc/passwd. Anything that reads files without proper escaping is vulnerable to this problem. Views that write files are just as vulnerable, but the consequences are doubly dire. Another permutation of this problem lies in code that dynamically loads modules based on the URL or other request information. A well-publicized example came from the world of Ruby on Rails. Prior to mid-2006, Rails used URLs like http://example.com/person/poke/1 directly to load modules and call methods. The result was that a carefully constructed URL could automatically load arbitrary code, including a database reset script! The SolutionIf your code ever needs to read or write files based on user input, you need to sanitize the requested path very carefully to ensure that an attacker isn’t able to escape from the base directory you’re restricting access to. Note Needless to say, you should never write code that can read from any area of the disk! A good example of how to do this escaping lies in Django’s built-in static content-serving view (in django.views.static). Here’s the relevant code: import os
import posixpath
# ...
path = posixpath.normpath(urllib.unquote(path))
newpath = ''
for part in path.split('/'):
if not part:
# strip empty path components
continue
drive, part = os.path.splitdrive(part)
head, part = os.path.split(part)
if part in (os.curdir, os.pardir):
# strip '.' and '..' in path
continue
newpath = os.path.join(newpath, part).replace('\\', '/')
Django doesn’t read files (unless you use the static.serve function, but that’s protected with the code just shown), so this vulnerability doesn’t affect the core code much. In addition, the use of the URLconf abstraction means that Django will never load code you’ve not explicitly told it to load. There’s no way to create a URL that causes Django to load something not mentioned in a URLconf. Exposed Error MessagesDuring development, being able to see tracebacks and errors live in your browser is extremely useful. Django has “pretty” and informative debug messages specifically to make debugging easier. However, if these errors get displayed once the site goes live, they can reveal aspects of your code or configuration that could aid an attacker. Furthermore, errors and tracebacks aren’t at all useful to end users. Django’s philosophy is that site visitors should never see application-related error messages. If your code raises an unhandled exception, a site visitor should not see the full traceback — or any hint of code snippets or Python (programmer-oriented) error messages. Instead, the visitor should see a friendly “This page is unavailable” message. Naturally, of course, developers need to see tracebacks to debug problems in their code. So the framework should hide all error messages from the public, but it should display them to the trusted site developers. The SolutionDjango has a simple flag that controls the display of these error messages. If the DEBUG setting is set to True, error messages will be displayed in the browser. If not, Django will render return an HTTP 500 (“Internal server error”) message and render an error template that you provide. This error template is called 500.html and should live in the root of one of your template directories. Because developers still need to see errors generated on a live site, any errors handled this way will send an email with the full traceback to any addresses given in the ADMINS setting. Users deploying under Apache and mod_python should also make sure they have PythonDebug Off in their Apache conf files; this will suppress any errors that occur before Django has had a chance to load. A Final Word on SecurityWe hope all this talk of security problems isn’t too intimidating. It’s true that the Web can be a wild and wooly world, but with a little bit of foresight, you can have a secure Web site. Keep in mind that Web security is a constantly changing field; if you’re reading the dead-tree version of this book, be sure to check more up to date security resources for any new vulnerabilities that have been discovered. In fact, it’s always a good idea to spend some time each week or month researching and keeping current on the state of Web application security. It’s a small investment to make, but the protection you’ll get for your site and your users is priceless. What’s NextIn the `next chapter`_, we’ll finally cover the subtleties of deploying Django: how to launch a production site and how to set it up for scalability. Docutils System MessagesSystem Message: ERROR/3 (<string>, line 526); backlinkUnknown target name: “next chapter”. 计算机安全性能测试软件安全性测试包括程序、数据库安全性测试。根据系统安全指标不同测试策略也不同。 用户认证安全的测试要考虑问题: 1. 明确区分系统中不同用户权限 2. 系统中会不会出现用户冲突 3. 系统会不会因用户的权限的改变造成混乱 4. 用户登陆密码是否是可见、可复制 5. 是否可以通过绝对途径登陆系统(拷贝用户登陆后的链接直接进入系统) 6. 用户推出系统后是否删除了所有鉴权标记,是否可以使用后退键而不通过输入口令进入系统 系统网络安全的测试要考虑问题 1. 测试采取的防护措施是否正确装配好,有关系统的补丁是否打上 2. 模拟非授权攻击,看防护系统是否坚固 3. 采用成熟的网络漏洞检查工具检查系统相关漏洞(即用最专业的黑客攻击工具攻击试一下,现在最常用的是 NBSI 系列和 IPhacker IP ) 4. 采用各种木马检查工具检查系统木马情况 5. 采用各种防外挂工具检查系统各组程序的客外挂漏洞 数据库安全考虑问题: 1. 系统数据是否机密(比如对银行系统,这一点就特别重要,一般的网站就没有太高要求) 2. 系统数据的完整性(我刚刚结束的企业实名核查服务系统中就曾存在数据的不完整,对于这个系统的功能实现有了障碍) 3. 系统数据可管理性 4. 系统数据的独立性 5. 系统数据可备份和恢复能力(数据备份是否完整,可否恢复,恢复是否可以完整)
July 30 mysql修改密码新手在这个上往往容易范错误,导致不能进入MYSQL,整得非常郁闷。 我来做几个例子相信很快就明白了 。 1、原来的密码是123456 C:\>type mysql5.bat @echo off mysql -uroot -p123456 -P3306 正确的修改MYSQL用户密码的格式是: 我们这里用 用户:root(可以换成其他的) 密码:woshiduide 来演示新密码。 C:\>mysqladmin -uroot -p password woshiduide Enter password: ****** 于是修改成功。 注意PASSWORD关键字后面的空格 有好多人是这样修改的: C:\>mysqladmin -uroot -p password 'woshiduide' Enter password: ****** C:\>mysqladmin -uroot -p password 'woshiduide' Enter password: ********* Warning: single quotes were not trimmed from the password by your command line client, as you might have expected. 而这个时候真正的密码是'woshiduide' C:\>mysql -uroot -p'woshiduide' Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 18 Server version: 5.1.17-beta-community-nt-debug MySQL Community Server (GPL) Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> 而新手往往这样: C:\>mysql -uroot -pwoshiduide ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: Y ES) 所以非常郁闷,BAIDU、GOOGLE的搜了一大堆。 我现在把密码改回去。 C:\>mysqladmin -uroot -p'woshiduide' password 123456 2、还有就是可以直接进入MYSQL,然后修改密码。 mysql> use mysql Database changed mysql> update user set PASSWORD = PASSWORD('woshiduide') where USER='root' and H OST='localhost'; Query OK, 1 row affected (0.05 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> flush privileges; mysql> exit Bye C:\>mysql -uroot -pwoshiduide Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 23 Server version: 5.1.17-beta-community-nt-debug MySQL Community Server (GPL) Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> Query OK, 0 rows affected (0.02 sec) 3、还有一种就是用SET PASSWORD 命令修改: C:\>mysql5.bat Enter password: ****** Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 8 Server version: 5.1.17-beta-community-nt-debug-log MySQL Community Server (GPL) Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> set password for root@'localhost' = password('woshiduide'); Query OK, 0 rows affected (0.02 sec) mysql> flush privileges; Query OK, 0 rows affected (0.09 sec) mysql> exit Bye 4、GRANT 也可以,不过这里不介绍。因为涉及到权限的问题。 July 22 jspwiki搭建Wiki的概念 Wiki 指一种超文本系统。这种超文本系统支持面向社群的协作式写作,同时也包括一组支持这种写作的辅助工具。我们可以在Web的基础上对Wiki文本进行浏览、创建、更改,而且创建、更改、发布的代价远比HTML文本小;同时Wiki系统还支持面向社群的协作式写作,为协作式写作提供必要帮助;最后,Wiki的作者自然构成了一个社群,Wiki系统为该社群提供简单的交流工具。与其它超文本系统相比,Wiki有使用方便及开放的特点,所以Wiki系统可以帮助我们在一个社群内共享某领域的知识。 JSPWiki 简介 JSPWiki是一个基于文本文件的简易wiki系统包括了身份认证和版本控制功能。完全采用JSP/Sevelet开发,采用UTF-8,能很好的支持中文,可以直接使用中文名作为页面(page)名。是一个简单易用的Wiki引擎。本文将向您展示如何建立一个自己的JSPWiki 应用。包括改变模板,安装插件以及为你的wiki加入身份认证功能。
目录 在Tomcat下建立JSPWiki应用 [#1] 1. 下载JSPWiki,解压缩,把jspwiki.war直接Copy到Tomcat下面webapps目录下,更名为wiki.war。
2. 启动tomcat,wiki.war会自动解压缩到webapps目录下
3. 到%Tomcat%/webapps/wiki/classes/WEB-INFO目录下面修改jspwiki.properties文件,作如下修改
4. 可以运行http://localhost:8080/wiki/Install.jsp帮助完成上述配置 ,为了能够在wiki中使用HTML需要修改 jspwiki.properties,把allowHTML 选项打开
更换模板 [#2] 1. 下载模板redman,并且解包到tomcat_home\webapps\JSPWiki目录下的template的目录下,目录名称应该就是redman
2. 修改jspwiki.propertiest文件,把
改成
安装插件 [#3]
安装java2html插件 1. 下载java2html插件
2. 把下载下来的java2html.jar拷贝到 tomcat_home\webapps\JSPWiki\WEB-INF\lib目录下
3. 修改 jspwiki.propertiest文件
安装PDF插件 1. 首先需要下载其它组件。下载Apache FOP 并解包把avalon-framework.jar (或者其他版本,比如:avalon-framework-cvs-20020806.jar)、batik.jar、fop.jar拷贝到WEB-INF/lib下;下载 jTidy 并解包,拷贝Tidy.jar to WEB-INF/lib目录下;下载 JIMI 并解包,把JimiProClasses.zip拷贝到WEB-INF/lib/目录并改名为JimiProClasses.jar.
2. 在jspwiki 下载pdf插件
3. 把下载下来的wikipdf.jar拷贝到 tomcat_home\webapps\JSPWiki\WEB-INF\lib目录下
4. 修改 tomcat_home\webapps\JSPWiki目录下Web.xml文件,增加下面的内容
5. 修改templates/default/ViewTemplate.jsp文件,加入下面的内容
注意: 修改jspwiki.propertiest文件时,"="后面的变量值后面不能有多余的空格或者tab,否则JSPWiki无法正常读取配置文件导致改动没有效果。
使用身份认证功能 [#4] 1. 修改jspwiki.properties文件,加入下面的内容:
2. 编辑对应的password.txt文件加入合法用户,例如:
3. 设置全部页面的默认访问权限,增加一个DefaultPermissions页面,包含下面的内容
[{SET defaultpermissions='ALLOW view Guest;DENY edit Guest;ALLOW edit KnownPerson'}] 4. 管理员用户组。可以在jspwiki.propertiest文件中指定管理员用户组的名称,如:
5. 那么默认的管理员用户组被命名为WikiAdmin,然后可以创建WikiAdmin页面加入成员,下面指令可以在WikiAdmin中加入JackJones,JillJones两个用户
[{SET members='JackJones, JillJones'}] 6. 如果需要设置单独页面的访问权限,可在页面内容前面加上访问规则,例如:
[{ALLOW view Guest}] [{DENY edit Guest}] [{ALLOW edit ebu, ubi}] 7. 如果需要增加一个用户组Xyz,增加一个Xyz的页面,加入下面的指令
[{SET members='Foo, Bar'}] }] 注意: JSPWiki有几个默认的用户组。
任何一个访问wiki的用户都属于Guest用户组;
任何一个使用user prefenrences设置了用户名的用户都属于NamedGuest用户组;
所有通过了身份认证的用户属于KnownPerson用户组。 注意: 目前的身份认证处理方式是临时的。
目前的身份认证方式是临时的,到2.4以上的版本会改变。目前权限规则实现有问题, 必须使用管理员用户组。因为加上了禁止guest访问
的权限管理规则后,除了管理员外所有用户都无法编辑wiki。 如果希望一个用户有wiki的编辑权限,别忘了把他加到管理员用户组。 |
|||||||||||||
|
|