知乎专栏 |
SQL注入,OS命令注入,缓冲溢出、跨站脚本、缺少验证、缺少认证、使用硬编码证书、敏感数据忘记加密、不受限制上传文件类型、依赖不可信的输入、用不必要的高级权限执行任务、跨站请求伪造....
这是一个计数器的例子
<?php session_start(); if(isset($_SESSION['count'])){ $_SESSION['count']++; }else{ $_SESSION['count'] = 1; } print($_SESSION['count']);
首先在IE浏览器上访问该文件,查看目前计数器数值。
现在开始演示如果更改用户的Session数据
通过Firebug等工具,查看PHPSESSID的值,例如我的是 75ff0dd6a0824a2b607777b58c27f78a
cat /tmp/sess_75ff0dd6a0824a2b607777b58c27f78a count|i:100;
将 count|i:100; 改为 count|i:1000; 再次去浏览器刷新看看现在计数器的数值是多少。
通过这种方法可以实现,提升权限,绕过登录等等。
由于session 存储在 tmp 目录下,一旦网站被注入就来带安全隐患
Apache进程所有者: nobody
程序所有者: www
apache 可以读取程序并运行,但apache 无法改写代码,/tmp等特殊目录可以写入操作
重置权限命令
chown www:www -R /www chown nobody:nobody -R /www/www.example.com/tmp find /www/ -type d -exec chmod 755 {} \; find /www/ -type f -exec chmod 644 {} \; chmod 744 -R /www/www.example.com/tmp
屏蔽访问权限
<Directory> <DirectoryMatch> <Files> <FilesMatch> <Location> <LocationMatch>
并不是所有目录和文件都需要提供给用户的,例如早期PHP项目中没有使用框架,常常有include, config等等目录需要屏蔽
例 12.3. Example for ECSHOP
<VirtualHost *:80> ServerAdmin webmaster@example.com DocumentRoot /www/www.example.com/ ServerName www.example.com ServerAlias example.com DirectoryIndex index.html index.php CustomLog "|/srv/httpd/bin/rotatelogs /www/logs/www.example.com/access.%Y-%m-%d.log 86400 480" combined <Location /data/> Order allow,deny Deny from all </Location> <Location /images/upload/> Order allow,deny Deny from all </Location> <Location /temp/> Order allow,deny Deny from all </Location> <Location /includes/> Order allow,deny Deny from all </Location> <Location /library/> Order allow,deny Deny from all </Location> <Location /plugin/> Order allow,deny Deny from all </Location> <Directory /www/www.example.com/images/> <Files *.php> Order allow,deny Deny from all </Files> </Directory> <Directory /www/www.example.com/js/> <Files *.php> Order allow,deny Deny from all </Files> </Directory> <Directory /www/www.example.com/themes/> <Files *.php> Order allow,deny Deny from all </Files> </Directory> </VirtualHost>
我们需要在框架的URL(PATHINFO)对象中加入检查功能
/news/%d.html 只能匹配数字ID /news/123.html 合法,如果/news/abc.html 非法 /login/%s.html 只能匹配字符串 /login/neo.html /product/[0-9/a-z].html 可以配置数字已经字符
post 数据还有上传文件也做同样检查
这里仅仅给你一个思路,实现起来也并不难
在开发中会经常会遇到这样的需求,例如投票模块,要防止恶意刷票,下面来介绍几种解决方按:
1、来源IP / MAC地址限制 这个是使用最多也是最广泛的方式,通过获取访问用户的来源IP地址,来限制在一段时间内所能使用的票数。 经常用电脑的老手是很容易绕出这种限制的。PPP/PPPoE拨号用户,可以通过断线重拨来更换IP地址; 每个网络位置会有一个全球唯一的MAC位址。所以我们也可以根据MAC地址限制用户访问 2、Cookies / Session验证 这种方式用的也比较多,清除浏览器Cookies,就可以很容易的绕过这种限制了 关闭浏览器,Session就会被销毁;客户端禁用Cookie,Session也会失效; 4、验证码,包括图像,语音,电话,邮件以及回答问题 首先说图片验证码,有些变态的网站,大家可以看到用户的注册、登录、回复、发帖等等,都会使用验证码,但是这种方式会让用户有时感觉很恶心,随着OCR(Optical Character Recognition,光学字符识别)技术的成熟,图片验证码已经不再安全,识别率可能达到90%以上甚至100% 语音有播放方式和电话方式,听喇叭中读取字符,然后输入验证码。不要以为这是最安全的,语音是一种波形,通过DSP(Digital Signal Processing,数字信号处理)技术很容易识别 手机短信与电子邮件,不多说了 回答问题 如果没有足够海量的题库,很快问题的内容和答案就会被收集。反而让正常投票的用户,觉得投票很恶心、麻烦,产生厌恶心理。渐渐的也被我们抛弃了。 5、注册用户可能投票模块 游客不能参与,必须注册了账户才能进行投票,并且限制新注册用户,在一段时间内不能参与投票。 6、随机投票地址 让每一个访问页面的用户得到一个随机唯一的KEY可能通过UUID/GUID生成,通过这个KEY,生成一个投票地址,该地址只能访问一次,使用过后便作废。 总结:很快就会有新的应对方式。我们只能通过上面几种方案的组合方式,增加用户刷新难度,让用户在无法在短期内实现应对方案,你没想出一种新方式。
; Error handling and logging ; ; 出错控制和登记 ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 错误报告是按位的。或者将数字加起来得到想要的错误报告等级。 ; E_ALL - 所有的错误和警告 ; E_ERROR - 致命性运行时错 ; E_WARNING - 运行时警告(非致命性错) ; E_PARSE - 编译时解析错误 ; E_NOTICE - 运行时提醒(这些经常是是你的代码的bug引起的, ;也可能是有意的行为造成的。(如:基于未初始化的变量自动初始化为一个 ;空字符串的事实而使用一个未初始化的变量) ; E_CORE_ERROR - 发生于PHP启动时初始化过程中的致命错误 ; E_CORE_WARNING - 发生于PHP启动时初始化过程中的警告(非致命性错) ; E_COMPILE_ERROR - 编译时致命性错 ; E_COMPILE_WARNING - 编译时警告(非致命性错) ; E_USER_ERROR - 用户产生的出错消息 ; E_USER_WARNING - 用户产生的警告消息 ; E_USER_NOTICE - 用户产生的提醒消息 ; 例子: ; error_reporting = E_ALL & ~E_NOTICE ; 显示所有的错误,除了提醒 ; error_reporting = E_COMPILE_ERROR|E_ERROR|E_CORE_ERROR ; 仅显示错误 error_reporting = E_ALL & ~E_NOTICE ; 显示所有的错误,除了提醒 display_errors = On ; 显示出错误信息(作为输出的一部分) ; 在最终发布的web站点上,强烈建议你关掉这个特性,并使用 ; 错误日志代替(参看下面)。 ; 在最终发布的web站点继续让 display_errors 有效可能 ; 暴露一些有关安全的信息,例如你的web服务上的文件路径、 ; 你的数据库规划或别的信息。 display_startup_errors = Off ; 甚至当display_erroes打开了,发生于PHP的启动的步骤中 ; 的错误也不会被显示。 ; 强烈建议保持使 display_startup_errors 关闭, ; 除了在改错过程中。 log_errors = Off ; 在日志文件里记录错误(服务器指定的日志,stderr标准错误输出,或error_log(下面的)) ; 正如上面说明的那样,强烈建议你在最终发布的web站点以日志记录错误 ; 取代直接错误输出。 track_errors = Off ; 保存最近一个 错误/警告 消息于变量 $php_errormsg (boolean) ;error_prepend_string = "<font color=ff0000>;" ; 于错误信息前输出的字符串 ;error_append_string = "</font>;" ; 于错误信息后输出的字符串 ;error_log = filename ; 记录错误日志于指定文件 ;error_log = syslog ; 记录错误日志于系统日志 syslog (NT 下的事件日志, Windows 95下无效) warn_plus_overloading = Off ; 当将‘+’用于字符串时警告 这项去掉 ; E_WARNING - 运行时警告(非致命性错)