douhezhang8932 2014-01-20 11:21
浏览 77
已采纳

使用Go / Python使用CSRF令牌登录到站点

I want to backup automatically web content from a site which requires login. I try to login by simulating a POST request. But I get the error:

csrf token: CSRF attack detected

Here are some extracts from the code I use:

func postLoginForm(csrfToken string) {
    values := make(url.Values)
    values.Set("signin[username]", "myusername") 
    values.Set("signin[password]", "mypassword") 

    values.Set("signin[_csrf_token]", csrfToken)
    resp, err := http.PostForm("https://spwebservicebm.reaktor.no/admin/nb", values)

    dumpHTTPResponse(resp) // show response to STDOUT
}

The csrf token I get by fetching the login page and scanning it for a hidden input field named signin[_csrf_token]. The important part of the code for doing that is the following:

// Finds input field named signin[_csrf_token] and returns value as csrfToken
func handleNode(n *html.Node) (csrfToken string, found bool) {
    if n.Type == html.ElementNode && n.Data == "input" {
        m := make(map[string]string)
        for _, attr := range n.Attr {
            m[attr.Key] = attr.Val
        }
        if m["name"] == "signin[_csrf_token]" {
            return  m["value"], true
        }
    }

    for c := n.FirstChild; c != nil; c = c.NextSibling {
         if csrfToken, found = handleNode(c); found {
             return 
         }       
    }

    return "", false
}

I don't need to be using Go, that is just because I am most familiar with that. Using python could be a solution as well, but I did not have any more luck with that.

  • 写回答

2条回答 默认 最新

  • dongyan1993 2014-01-21 09:54
    关注

    The issue is that Go 1.2 does not automatically use a cookie jar for its HTTP requests. The first request is to get the CSRF token from the login page. The second request is to POST a login using that CSRF token. But since no session cookie is attached to the HTTP header on the second request the server does not know that it is the same program trying to login. Thus the server thinks it is a CSRF attempt (that you picked the CSRF token from somewhere else and tried to reuse it).

    So to get login page and extract CSRF token, we first create our own client object. Otherwise we have nowhere to attach the cookie jar. http.PostForm does give access to cookie jar:

    client = &http.Client{}
    

    Create a cookie Jar described in authenticated http client requests from golang . This was easier to setup and debug than the official: http://golang.org/pkg/net/http/cookiejar/ Cookie Jar

    jar := &myjar{}
    jar.jar = make(map[string] []*http.Cookie)
    client.Jar = jar    
    
    resp, err := client.Get("https://spwebservicebm.reaktor.no/admin")      
    doc, err := html.Parse(resp.Body)
    

    Then to login, we reuse the client object with the cookie jar attached to it:

    values := make(url.Values)
    values.Set("signin[username]", "myusername")
    values.Set("signin[password]", "mypassword")                                       
    values.Set("signin[_csrf_token]", csrfToken)
    
    resp, err := client.PostForm("https://spwebservicebm.reaktor.no/admin/login", values)
    

    You'll notice that the code is almost identical to the one in the question except we use client.PostForm instead of http.PostForm.

    Thanks to dommage and answer to authenticated http client requests from golang for getting me on right track.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 如果要做一个老年人平板有哪些需求
  • ¥15 k8s生产配置推荐配置及部署方案
  • ¥15 matlab提取运动物体的坐标
  • ¥15 人大金仓下载,有人知道怎么解决吗
  • ¥15 一个小问题,本人刚入门,哪位可以help
  • ¥15 python安卓开发
  • ¥15 使用R语言GD包一直不出结果
  • ¥15 计算机微处理器与接口技术相关问题,求解答图片的这个问题,有多少个端口,端口地址和解答问题的方法和思路,不要AI作答
  • ¥15 如何根据一个截图编写对应的HTML代码
  • ¥15 stm32标准库的PID角度环