设为首页 收藏本站
查看: 802|回复: 0

[经验分享] perl写cgi要注意的几个字符

[复制链接]

尚未签到

发表于 2018-9-1 07:58:45 | 显示全部楼层 |阅读模式
  1、“有毒”的NULL字符
  ---------------------
  如果我说:"root"=="root",相信没有什么人反对。但同时我也这样说:
  "root"!="root"!还有多少人会认为我是个“正常人”?:)
  但在各种不同的编程语言中,确实存在着这种情况。
  对于每一个希望发现CGI漏洞的安全专家或***来说,最常用的方法之一是
  通过传递特殊字符(串),绕过CGI限制以执行系统级调用或程序。如果你仔细
  留意的话,或许也会发现NULL字符确实有它的“妙用”。:)
  阅读以下例子:
  # parse $user_input
  $database="$user_input.db";
  open(FILE "<$database");
  这个例子用于打开客户端指定的数据库文件。例如客户端输入"backend",则系
  统将打开"backend.db"文件考只读方式)。(注:在这里我们暂且不讨论"../"
  的安全问题。)这种处理方式在互联网中是很常见的。
  现在,让我们在客户端输入"backend%00",在该PERL程序中$database=
  "backend.db",然后调用open函数打开该文件。但结果是什么呢?系统会打
  开"backend"文件(,如果该文件存在)!
  出现这种情况的原因是由于PERL允许在字符串变量中使用NULL空字符,而
  在C语言中字符串则不允许包含空字符。因此,也就有了"root"!="root"(在
  PERL中)和"root"="root"(在C语言中)。由于系统内核/调用等都是使用C
  语言编写,因此当PERL将"backend.db"字符串传递到(C语言的)链接库/程序
  时,空字符以后的字符将被忽略?(或许还有利用价值?我还没发现。:))
  这种编程缺陷的影响可大可小。试想一下,如果利用以上编程原理编写一个
  给系统其他管理员修改除了root外的其他用户口令的PERL程序:
  $user=$ARGV[1] # user the jr admin wants to change
  if ($user ne "root"){
  # do whatever needs to be done for this user }
  那么,聪明的你应该知道如何绕过这个限制修改root用户口令了吧?对了,只要
  使 $user="root",则PERL会执行上面程序中花括号内的语句。除非所有处理
  过程均使用PERL,否则一旦该变量传递给系统,则会造成安全问题。如修改root
  用户口令等。
  也许你认为很难遇到这种会造成严重安全问题的情况,那么我们能否将它作
  为一种寻找网站源程序漏洞的间接手段呢?;-)
  不知你有没有经常遇到这种类型的CGI程序,该程序用于打开客户端(提交
  的表单中)要求的页面?如:
  page.cgi?page=1
  然后网站是否返回页面"1.html"呢?;-) 好,现在将其改为:
  page.cgi?page=page.cgi%00 (%00 == '' escaped)
  这样,我们就可以得到我们感兴趣的文件内容了!这种方法连PERL的"-e"参数也
  可绕过:
  $file="/etc/passwd.txt.whatever.we.want";
  die("hahaha! Caught you!) if($file eq "/etc/passwd");
  if (-e $file){
  open (FILE, ">$file");}
  绕过这段程序的后果你应该想像得到吧?:)
  解决方法?最简单地,过滤NULL空字符。在PERL程序中,
  $insecure_data=~s///g;
  ------------------------
  2、漏网之鱼--反斜杠()
  ------------------------
  对于每一个关心CGI安全的人,也许都看过 W3C 的 WWW Security FAQ 中关
  于CGI安全编程一节。其中列出了建议过滤的字符:
  &;`'" *?~<>^()[]{}$nr
  但我在很多时候发现反斜杠()往往被遗忘了。以下是正确的过滤表达式:
  s/([&;`'\ "*?~<>^()[]{}$nr])/\$1/g;
  但在很多商业的CGI程序中反斜杠却没有被包含进去,这可能是程序员们写程序
  时被这些过滤用的匹配表达式搞迷糊了?
  那么,没有过滤反斜杠会造成安全问题吗?试想一下,如果向你的程序中发
  送如下一行内容:
  user data `rm -rf /`
  大多数情况下,程序员编写的程序会将以上内容过滤为:
  user data `rm -rf /`
  从而保护了系统。但如果PERL程序中忘记过滤了反斜杠,当客户端向该程序提交
  如下内容时:
  user data `rm -rf / `
  经过匹配表达式后为:
  user data \`rm -rf / \`
  怎么样,看出危险了吗?由于两个反斜杠经系统解释后为一个字符"",但`字符
  却因此没有被过滤掉,`rm -rf / `将被系统执行!不过,由于其中还含有一个
  反斜杠字符,执行时系统会出错。你自己想办法绕过这个限制吧?;-)
  利用反斜杠的另一个应用--绕过系统目录进入限制。请看以下表达式:
  s/..//g;
  这个匹配表达式的作用非常简单,就是过滤字符串中的".."。当输入为:
  /usr/tmp/../../etc/passwd
  将被过滤为:
  /usr/tmp///etc/passwd
  这样,你将无法访问/etc/passwd文件。(注:*nix系统允许///,试一下'ls -l
  /etc////passwd'命令就知道了。)
  现在,让我们的“好伙伴”反斜杠来帮忙。将输入改为:
  /usr/tmp/../../etc/passwd
  则由于反斜杠的存在而不符合过滤表达式。当PERL中存在如下程序段时,
  $file="/usr/tmp/.\./.\./etc/passwd";
  $file=s/..//g;
  system("ls -l $file");
  当运行到执行系统调用时,执行的命令会是"ls -l /usr/tmp/../../etc/
  passwd"。想知道会得到什么输出吗?自己在机器上试试吧。;-)
  然而,以上方法只适用于系统调用或``命令中。无法绕过PERL中的'-e'命令
  和open函数(非管道)。如下程序:
  $file="/usr/tmp/.\./.\./etc/passwd";
  open(FILE, "<$file") or die("No such file");
  执行时将显示"No such file"并退出。我还没有找出绕过这个限制的方法。:(
  解决方法:只要别忘了过滤反斜杠字符(),就已足够了。
  --------------------------------
  3、畅通无阻的“管道”--字符" "
  --------------------------------
  在PERL的open函数中,如果在文件名后加上" ",则PERL将会执行这个文件,
  而不是打开它。即:
  open(FILE, "/bin/ls")
  将打开并得到/bin/ls的二进制代码,但
  open(FILE, "/bin/ls ")
  将执行/bin/ls命令!
  以下过滤表达式
  s/( )/\$1/g
  可以限制这个方法。PERL会提示"unexpected end of file"。如果你找到绕过这
  个限制的方法,请告诉我。:-)
  综合应用
  现在让我们综合以上几种编程安全漏洞加以利用。先举个例子,$FORM是客
  户端需要提交给CGI程序的变量。而在CGI程序中有如下语句:
  open(FILE, "$FORM")
  那我们可以将"ls "传递给$FORM变量来获得当前目录列表。现在让我们考虑如下
  程序段:
  $filename="/safe/dir/to/read/$FORM"
  open(FILE, $filename)
  如何再执行"ls"命令呢?只要能使$FORM="../../../../bin/ls "即可。如果系
  统对目录操作加入了".."过滤,则可利用反斜杠的漏洞绕过它。
  在这段程序中,我们还可以在命令中加入参数。如"touch /backend ",将
  建立/backend文件。(但我不会使用这个文件名,因为它是我的名字。:-))
  现在,让我们在程序段中加入更多的安全限制:
  $filename="safe/dir/to/read/$FORM"
  if(!(-e $filename)) die("I don't think so!")
  open(FILE, $filename)
  这样我们还需要绕过"-e"的限制。由于我们在$FORM变量中使用了" "字符,当
  "-e"运算符检查"ls "文件时,因为不存在此文件而退出程序。如何当"-e"检查
  时去掉管道符,而调用open函数时又含有管道符呢?回忆一下在前面谈到的NULL
  字符的利用,我们就知道应该如何做了。只要使$FORM="ls "(注:在客户端
  提交的表单中为"ls%00 ")即可。其中的原理复习一下前面提到的内容就会明白
  了。
  需要说明的是,以上程序段中,我们无法象再上一段程序那样执行带参数的
  命令,这是因为"-e"运算符的限制所致。举例如下:
  $filename="/bin/ls /etc "
  open(FILE, $filename)
  将显示/etc目录下文件列表。
  $filename="/bin/ls /etc "
  if(!(-e $filename)) exit;
  open(FILE, $filename)
  将导致因不存在文件而退出。
  $filename="/bin/ls /etc "
  if(!(-e $filename)) exit;
  open(FILE, $filename)
  将只显示当前目录下文件列表。


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-560894-1-1.html 上篇帖子: perl 笔记-chop函数 下篇帖子: perl笔记 -STDOUT&STDERR区别
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表